Nncase studio (#1125)
* update * fix csproj * tmp commit * refactor finish * fix build * update * update * update * add ShapeBucketView * update * fix cancel and simulate time * update font family and progress bar * fix build * fix * Apply code-format changes * move file location * fix * update page switch logic * resolve feedback * close DBus * update * add some comment * update * fix build * update * update * Apply code-format changes * add CustomValidation * add validate * add some validate * Apply code-format changes * resolve review * fix msg box * add CompileConfig * fix config export and import * Apply code-format changes * update preprocess * Apply code-format changes * add publish and upload for nncase-studio * change artifacts name * fix --------- Co-authored-by: FusionBolt <FusionBolt@users.noreply.github.com>pull/1143/head
|
@ -114,6 +114,7 @@ jobs:
|
|||
dotnet restore -r ${{matrix.config.rid}}
|
||||
dotnet build -c ${{matrix.config.buildType}} --no-restore
|
||||
dotnet publish src/Nncase.Compiler -c ${{matrix.config.buildType}} --no-restore --sc false -r ${{matrix.config.rid}}
|
||||
dotnet publish src/Nncase.Studio -c ${{matrix.config.buildType}} --no-restore --sc false -r ${{matrix.config.rid}}
|
||||
|
||||
- name: Set up Dotnet Test settings
|
||||
uses: 1arp/create-a-file-action@0.2
|
||||
|
|
|
@ -12,6 +12,14 @@
|
|||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Avalonia" Version="11.0.2"/>
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.0.2"/>
|
||||
<PackageVersion Include="Avalonia.Themes.Fluent" Version="11.0.2"/>
|
||||
<PackageVersion Include="Avalonia.Fonts.Inter" Version="11.0.2"/>
|
||||
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.0.2"/>
|
||||
<PackageVersion Include="MessageBox.Avalonia" Version="3.1.2" />
|
||||
|
||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.2.1" />
|
||||
<PackageVersion Include="Google.OrTools" Version="9.4.1874" />
|
||||
<PackageVersion Include="AnyTensorFlow.NET" Version="0.70.1" />
|
||||
<PackageVersion Include="BitFields" Version="0.1.0" />
|
||||
|
@ -46,6 +54,7 @@
|
|||
<PackageVersion Include="NetFabric.Hyperlinq" Version="3.0.0-beta48" />
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageVersion Include="Nncase.FlatBuffers" Version="2.0.0" />
|
||||
<PackageVersion Include="NumSharp" Version="0.30.0" />
|
||||
<PackageVersion Include="OrtKISharp" Version="0.0.2" />
|
||||
<PackageVersion Include="RazorLight" Version="2.3.0" />
|
||||
<PackageVersion Include="Singulink.Collections.Weak" Version="1.0.2" />
|
||||
|
|
|
@ -77,6 +77,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nncase.Tests.TestFixture",
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nncase.Passes", "src\Nncase.Passes\Nncase.Passes.csproj", "{E6462E82-B48F-4AFA-AE34-725EF0A9CB42}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nncase.Studio", "src\Nncase.Studio\Nncase.Studio.csproj", "{B9A09DA2-EF1A-4C0E-A0F5-427AFBB5C769}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -171,6 +173,10 @@ Global
|
|||
{E6462E82-B48F-4AFA-AE34-725EF0A9CB42}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E6462E82-B48F-4AFA-AE34-725EF0A9CB42}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E6462E82-B48F-4AFA-AE34-725EF0A9CB42}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B9A09DA2-EF1A-4C0E-A0F5-427AFBB5C769}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B9A09DA2-EF1A-4C0E-A0F5-427AFBB5C769}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B9A09DA2-EF1A-4C0E-A0F5-427AFBB5C769}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B9A09DA2-EF1A-4C0E-A0F5-427AFBB5C769}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -201,6 +207,7 @@ Global
|
|||
{E365B1B1-4D13-4839-9763-A7A7C5F32FD4} = {BCA74168-F015-4B5B-B4CD-C83AE06B9822}
|
||||
{98A03405-CA53-4EC4-9B18-94D1C8DF9453} = {E5A4516C-4080-4346-991D-57A7AA76ADA6}
|
||||
{E6462E82-B48F-4AFA-AE34-725EF0A9CB42} = {BCA74168-F015-4B5B-B4CD-C83AE06B9822}
|
||||
{B9A09DA2-EF1A-4C0E-A0F5-427AFBB5C769} = {BCA74168-F015-4B5B-B4CD-C83AE06B9822}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {9492E141-292E-4D60-9C6E-3738AB234DB2}
|
||||
|
|
|
@ -244,6 +244,25 @@ internal class Compiler : ICompiler
|
|||
});
|
||||
}
|
||||
|
||||
public async Task CompileWithReportAsync(IProgress<int> progress, CancellationToken token)
|
||||
{
|
||||
CancellationTokenSource cts = new();
|
||||
var internalToken = cts.Token;
|
||||
using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(internalToken, token))
|
||||
{
|
||||
try
|
||||
{
|
||||
var task = Task.Run(CompileAsync, linkedCts.Token);
|
||||
Report(progress, 9, linkedCts.Token);
|
||||
await task.WaitAsync(linkedCts.Token);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task CompileAsync()
|
||||
{
|
||||
var target = _compileSession.Target;
|
||||
|
@ -278,6 +297,14 @@ internal class Compiler : ICompiler
|
|||
linkedModel.Serialize(output);
|
||||
}
|
||||
|
||||
private void Report(IProgress<int> progress, int maxPassCount, CancellationToken token)
|
||||
{
|
||||
while (_runPassCount < maxPassCount && !token.IsCancellationRequested)
|
||||
{
|
||||
progress?.Report(_runPassCount);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<IRModule> InitializeModuleAsync(IRModule module)
|
||||
{
|
||||
_module = module;
|
||||
|
|
|
@ -49,6 +49,11 @@ public interface ICompiler
|
|||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task CompileAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Compile module with report pass number.
|
||||
/// </summary>
|
||||
Task CompileWithReportAsync(IProgress<int> progress, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Generate code to stream.
|
||||
/// </summary>
|
||||
|
|
|
@ -153,6 +153,11 @@ public class QuantizeOptions
|
|||
/// </summary>
|
||||
public bool ExportQuantScheme { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets quantize scheme path.
|
||||
/// </summary>
|
||||
public string ExportQuantSchemePath { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether export weight range by channel.
|
||||
/// </summary>
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<Application xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Nncase.Studio.App"
|
||||
xmlns:local="using:Nncase.Studio"
|
||||
RequestedThemeVariant="Default">
|
||||
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
|
||||
|
||||
<Application.DataTemplates>
|
||||
<local:ViewLocator/>
|
||||
</Application.DataTemplates>
|
||||
|
||||
<Application.Styles>
|
||||
<FluentTheme />
|
||||
<StyleInclude Source="Style/ButtonStyle.axaml"></StyleInclude>
|
||||
<StyleInclude Source="Style/CustomValidation.axaml"></StyleInclude>
|
||||
<StyleInclude Source="Style/Logo.axaml"></StyleInclude>
|
||||
<StyleInclude Source="Style/GridStyle.axaml"></StyleInclude>
|
||||
|
||||
<Style Selector="TextBox.contentMessage">
|
||||
<Setter Property="FontSize" Value="30"></Setter>
|
||||
</Style>
|
||||
</Application.Styles>
|
||||
|
||||
<Application.Resources>
|
||||
<!-- <FontFamily x:Key="NunitoFont">Assets\Fonts\Nunito-Black.ttf</FontFamily> -->
|
||||
</Application.Resources>
|
||||
</Application>
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Nncase.Studio.ViewModels;
|
||||
using Nncase.Studio.Views;
|
||||
|
||||
namespace Nncase.Studio;
|
||||
|
||||
public partial class App : Application
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
desktop.MainWindow = new MainWindow { DataContext = new MainWindowViewModel(), };
|
||||
}
|
||||
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 172 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 71 KiB |
After Width: | Height: | Size: 44 KiB |
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Data.Converters;
|
||||
using DynamicData;
|
||||
using NetFabric.Hyperlinq;
|
||||
|
||||
namespace Nncase.Studio;
|
||||
|
||||
public class EnumConverter : IValueConverter
|
||||
{
|
||||
// enum to selected index
|
||||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
var index = Enum.GetNames(value.GetType()).IndexOf(value.ToString());
|
||||
return index;
|
||||
}
|
||||
|
||||
// to enum
|
||||
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
// to enum or to other
|
||||
if (value == null || (int)value < 0)
|
||||
{
|
||||
return Activator.CreateInstance(targetType);
|
||||
}
|
||||
|
||||
var values = Enum.GetNames(targetType)[(int)value];
|
||||
return Enum.Parse(targetType, values);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Models\"/>
|
||||
<AvaloniaResource Include="Assets\**"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia"/>
|
||||
<PackageReference Include="Avalonia.Desktop"/>
|
||||
<PackageReference Include="Avalonia.Themes.Fluent"/>
|
||||
<PackageReference Include="Avalonia.Fonts.Inter"/>
|
||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||
<!-- <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics"/>-->
|
||||
<PackageReference Include="Avalonia.ReactiveUI"/>
|
||||
<PackageReference Include="CommunityToolkit.Mvvm"/>
|
||||
<PackageReference Include="NumSharp" />
|
||||
<PackageReference Include="MessageBox.Avalonia"/>
|
||||
|
||||
<ProjectReference Include="..\Nncase.Compiler\Nncase.Compiler.csproj" />
|
||||
<ProjectReference Include="..\Nncase.CodeGen\Nncase.CodeGen.csproj" />
|
||||
<ProjectReference Include="..\Nncase.Core\Nncase.Core.csproj" />
|
||||
<ProjectReference Include="..\Nncase.Diagnostics\Nncase.Diagnostics.csproj" />
|
||||
<ProjectReference Include="..\Nncase.Graph\Nncase.Graph.csproj" />
|
||||
<ProjectReference Include="..\Nncase.EGraph\Nncase.EGraph.csproj" />
|
||||
<ProjectReference Include="..\Nncase.Evaluator\Nncase.Evaluator.csproj" />
|
||||
<ProjectReference Include="..\Nncase.Importer\Nncase.Importer.csproj" />
|
||||
<ProjectReference Include="..\Nncase.Simulator\Nncase.Simulator.csproj" />
|
||||
<ProjectReference Include="..\Nncase.Quantization\Nncase.Quantization.csproj" />
|
||||
<ProjectReference Include="..\Nncase.Passes\Nncase.Passes.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Nncase.Modules.StackVM\Nncase.Modules.StackVM.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<UpToDateCheckInput Remove="Style\EnumComboBox.axaml" />
|
||||
<UpToDateCheckInput Remove="Assets\Fonts\Noto_Sans_TC\NotoSansTC-VariableFont_wght.ttf" />
|
||||
<UpToDateCheckInput Remove="Assets\Fonts\Noto_Sans_TC\OFL.txt" />
|
||||
<UpToDateCheckInput Remove="Assets\Fonts\Noto_Sans_TC\README.txt" />
|
||||
<UpToDateCheckInput Remove="Assets\Fonts\Noto_Sans_TC\static\NotoSansTC-Black.ttf" />
|
||||
<UpToDateCheckInput Remove="Assets\Fonts\Noto_Sans_TC\static\NotoSansTC-Bold.ttf" />
|
||||
<UpToDateCheckInput Remove="Assets\Fonts\Noto_Sans_TC\static\NotoSansTC-ExtraBold.ttf" />
|
||||
<UpToDateCheckInput Remove="Assets\Fonts\Noto_Sans_TC\static\NotoSansTC-ExtraLight.ttf" />
|
||||
<UpToDateCheckInput Remove="Assets\Fonts\Noto_Sans_TC\static\NotoSansTC-Light.ttf" />
|
||||
<UpToDateCheckInput Remove="Assets\Fonts\Noto_Sans_TC\static\NotoSansTC-Medium.ttf" />
|
||||
<UpToDateCheckInput Remove="Assets\Fonts\Noto_Sans_TC\static\NotoSansTC-Regular.ttf" />
|
||||
<UpToDateCheckInput Remove="Assets\Fonts\Noto_Sans_TC\static\NotoSansTC-SemiBold.ttf" />
|
||||
<UpToDateCheckInput Remove="Assets\Fonts\Noto_Sans_TC\static\NotoSansTC-Thin.ttf" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Media.Fonts;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Nncase.Studio;
|
||||
|
||||
internal class Program
|
||||
{
|
||||
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
||||
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
|
||||
// yet and stuff might break.
|
||||
[STAThread]
|
||||
public static void Main(string[] args) => BuildAvaloniaApp()
|
||||
.StartWithClassicDesktopLifetime(args);
|
||||
|
||||
// Avalonia configuration, don't remove; also used by visual designer.
|
||||
public static AppBuilder BuildAvaloniaApp()
|
||||
=> AppBuilder.Configure<App>()
|
||||
.UsePlatformDetect()
|
||||
.UseNncaseFontManager()
|
||||
.ConfigureCompiler()
|
||||
.LogToTrace()
|
||||
.UseReactiveUI()
|
||||
.DisableDBus();
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Design.PreviewWith>
|
||||
<Border Padding="20">
|
||||
<!-- Add Controls for Previewer Here -->
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
|
||||
<Style Selector="Button">
|
||||
<Setter Property="Margin" Value="10"></Setter>
|
||||
<Setter Property="MinWidth" Value="100"></Setter>
|
||||
<Setter Property="CornerRadius" Value="45"></Setter>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"></Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="Button#ImportButton">
|
||||
<Setter Property="CornerRadius" Value="45"></Setter>
|
||||
<Setter Property="Width" Value="200"></Setter>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"></Setter>
|
||||
<Setter Property="HorizontalAlignment" Value="Center"></Setter>
|
||||
</Style>
|
||||
<!-- Add Styles Here -->
|
||||
</Styles>
|
|
@ -0,0 +1,49 @@
|
|||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Design.PreviewWith>
|
||||
<Border Padding="20">
|
||||
<!-- Add Controls for Previewer Here -->
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
|
||||
<Style Selector="DataValidationErrors">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<DockPanel LastChildFill="True">
|
||||
<ContentControl DockPanel.Dock="Right"
|
||||
ContentTemplate="{TemplateBinding ErrorTemplate}"
|
||||
DataContext="{TemplateBinding Owner}"
|
||||
Content="{Binding (DataValidationErrors.Errors)}"
|
||||
IsVisible="{Binding (DataValidationErrors.HasErrors)}"/>
|
||||
<ContentPresenter Name="PART_ContentPresenter"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
Content="{TemplateBinding Content}"
|
||||
Padding="{TemplateBinding Padding}"/>
|
||||
</DockPanel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Setter Property="ErrorTemplate">
|
||||
<DataTemplate>
|
||||
<Canvas Width="14" Height="14" Margin="4 0 1 0"
|
||||
Background="Transparent">
|
||||
<Canvas.Styles>
|
||||
<Style Selector="ToolTip">
|
||||
<Setter Property="Background" Value="LightCoral"/>
|
||||
<Setter Property="BorderBrush" Value="Red"/>
|
||||
</Style>
|
||||
</Canvas.Styles>
|
||||
<ToolTip.Tip>
|
||||
<!-- <ItemsControl Items="{Binding}"/> -->
|
||||
</ToolTip.Tip>
|
||||
<Path Data="M14,7 A7,7 0 0,0 0,7 M0,7 A7,7 0 1,0 14,7 M7,3l0,5 M7,9l0,2"
|
||||
Stroke="Red"
|
||||
StrokeThickness="2"/>
|
||||
</Canvas>
|
||||
</DataTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Styles>
|
|
@ -0,0 +1,43 @@
|
|||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Design.PreviewWith>
|
||||
<Border Padding="20">
|
||||
<!-- Add Controls for Previewer Here -->
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
|
||||
<!-- simulate view -->
|
||||
<Style Selector="Grid TextBox">
|
||||
<Setter Property="Margin" Value="15"></Setter>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"></Setter>
|
||||
<Setter Property="Width" Value="240"></Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="Grid NumericUpDown">
|
||||
<Setter Property="Margin" Value="15"></Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="TextBox.Path">
|
||||
<Setter Property="Margin" Value="15"></Setter>
|
||||
<Setter Property="Width" Value="760"></Setter>
|
||||
<Setter Property="MaxWidth" Value="760"></Setter>
|
||||
<Setter Property="HorizontalAlignment" Value="Left"></Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="Grid Label">
|
||||
<Setter Property="Margin" Value="15"></Setter>
|
||||
<Setter Property="VerticalAlignment" Value="Center"></Setter>
|
||||
</Style>
|
||||
<Style Selector="Grid Button">
|
||||
<Setter Property="HorizontalAlignment" Value="Center"></Setter>
|
||||
<Setter Property="VerticalAlignment" Value="Center"></Setter>
|
||||
</Style>
|
||||
<Style Selector="Grid ComboBox">
|
||||
<Setter Property="Margin" Value="15"></Setter>
|
||||
<Setter Property="VerticalAlignment" Value="Center"></Setter>
|
||||
</Style>
|
||||
<Style Selector="Grid CheckBox">
|
||||
<Setter Property="Margin" Value="15"></Setter>
|
||||
<Setter Property="VerticalAlignment" Value="Center"></Setter>
|
||||
</Style>
|
||||
</Styles>
|
|
@ -0,0 +1,15 @@
|
|||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Design.PreviewWith>
|
||||
<Border Padding="20">
|
||||
<!-- Add Controls for Previewer Here -->
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
|
||||
<!-- Import Logo -->
|
||||
<Style Selector="DockPanel#LogoPanel > Image">
|
||||
<Setter Property="Margin" Value="40 80"></Setter>
|
||||
<Setter Property="Width" Value="128"></Setter>
|
||||
<Setter Property="Height" Value="128"></Setter>
|
||||
</Style>
|
||||
</Styles>
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Media.Fonts;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Nncase.Studio;
|
||||
|
||||
public static class AvaloniaAppBuilderExtensions
|
||||
{
|
||||
public static AppBuilder UseNncaseFontManager(this AppBuilder builder, Action<FontSettings>? configDelegate = default)
|
||||
{
|
||||
var setting = new FontSettings();
|
||||
configDelegate?.Invoke(setting);
|
||||
|
||||
return builder.With(new FontManagerOptions
|
||||
{
|
||||
DefaultFamilyName = setting.DefaultFontFamily,
|
||||
FontFallbacks = new[]
|
||||
{
|
||||
new FontFallback
|
||||
{
|
||||
FontFamily = new FontFamily(setting.DefaultFontFamily),
|
||||
},
|
||||
},
|
||||
}).ConfigureFonts(manager => manager.AddFontCollection(new EmbeddedFontCollection(setting.Key, setting.Source)));
|
||||
}
|
||||
|
||||
public static AppBuilder ConfigureCompiler(this AppBuilder builder)
|
||||
{
|
||||
var host = Host.CreateDefaultBuilder()
|
||||
.ConfigureCompiler()
|
||||
.Build();
|
||||
CompilerServices.Configure(host.Services);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static AppBuilder DisableDBus(this AppBuilder builder)
|
||||
{
|
||||
// https://github.com/AvaloniaUI/Avalonia/issues/9383#issuecomment-1378350456
|
||||
return builder.With(new X11PlatformOptions() { UseDBusFilePicker = false });
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using MsBox.Avalonia;
|
||||
|
||||
namespace Nncase.Studio.Util;
|
||||
|
||||
public class AvaloniaUserDialog
|
||||
{
|
||||
public void ShowDialog(string message) =>
|
||||
MessageBoxManager
|
||||
.GetMessageBoxStandard("Notification", message).ShowAsync();
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices.JavaScript;
|
||||
using Nncase.Diagnostics;
|
||||
using Nncase.Studio.ViewModels;
|
||||
|
||||
namespace Nncase.Studio.Util;
|
||||
|
||||
public class CompileConfig
|
||||
{
|
||||
public CompileConfig()
|
||||
{
|
||||
var dumpDir = Path.Join(Directory.GetCurrentDirectory(), "nncase_dump");
|
||||
CompileOption.DumpDir = dumpDir;
|
||||
CompileOption.InputFile = string.Empty;
|
||||
KmodelPath = Path.Join(dumpDir, "test.kmodel");
|
||||
ResultDir = dumpDir;
|
||||
CompileOption.InputLayout = "NCHW";
|
||||
CompileOption.OutputLayout = "NCHW";
|
||||
CompileOption.ModelLayout = "NCHW";
|
||||
CompileOption.InputShape = new[] { 1, 3, 24, 24 };
|
||||
CompileOption.InputRange = new float[] { -1, 1 };
|
||||
CompileOption.Mean = new[] { 0f };
|
||||
CompileOption.Std = new[] { 0f };
|
||||
CompileOption.LetterBoxValue = 0f;
|
||||
}
|
||||
|
||||
public CompileOptions CompileOption { get; set; } = new();
|
||||
|
||||
public bool MixQuantize { get; set; }
|
||||
|
||||
public bool UseQuantize { get; set; }
|
||||
|
||||
public PreprocessMode PreprocessMode { get; set; }
|
||||
|
||||
public DumpFlags[] DumpFlags { get; set; } = Array.Empty<DumpFlags>();
|
||||
|
||||
public string Target { get; set; } = "cpu";
|
||||
|
||||
public string KmodelPath { get; set; }
|
||||
|
||||
public string ResultDir { get; set; }
|
||||
|
||||
public string[] InputPathList { get; set; } = Array.Empty<string>();
|
||||
|
||||
public bool EnableShapeBucket
|
||||
{
|
||||
get { return CompileOption.ShapeBucketOptions.Enable; }
|
||||
set { CompileOption.ShapeBucketOptions.Enable = value; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Platform.Storage;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Nncase.IR;
|
||||
using Nncase.Quantization;
|
||||
using Nncase.Studio.Views;
|
||||
using NumSharp;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Nncase.Studio.ViewModels;
|
||||
|
||||
public static class DataUtil
|
||||
{
|
||||
public static string TensorTypeToString(TensorType tt)
|
||||
{
|
||||
return $"{tt.DType} {tt.Shape}";
|
||||
}
|
||||
|
||||
public static string VarToString(Var var)
|
||||
{
|
||||
var tt = (TensorType)var.TypeAnnotation;
|
||||
return $"{var.Name} {TensorTypeToString(tt)}";
|
||||
}
|
||||
|
||||
public static (string[] InputFiles, Tensor[] InputList) ReadMultiInputs(List<string> path)
|
||||
{
|
||||
var inputFiles = path.Count == 1 && Directory.Exists(path[0])
|
||||
? Directory.GetFiles(path[0])
|
||||
: path.ToArray();
|
||||
var input = ReadInput(inputFiles).ToArray();
|
||||
return (inputFiles, input);
|
||||
}
|
||||
|
||||
public static List<Tensor> ReadInput(string[] file)
|
||||
{
|
||||
return file
|
||||
.Where(f => Path.GetExtension(f) == ".npy")
|
||||
.Select(f =>
|
||||
{
|
||||
var tensor = np.load(f);
|
||||
return Tensor.FromBytes(new TensorType(DataType.FromType(tensor.dtype), tensor.shape), tensor.ToByteArray());
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public static DataType QuantTypeToDataType(QuantType qt)
|
||||
{
|
||||
return qt switch
|
||||
{
|
||||
QuantType.Uint8 => DataTypes.UInt8,
|
||||
QuantType.Int8 => DataTypes.Int8,
|
||||
QuantType.Int16 => DataTypes.Int16,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(qt), qt, null),
|
||||
};
|
||||
}
|
||||
|
||||
public static bool TryParseFixVarMap(string input, out Dictionary<string, int> map)
|
||||
{
|
||||
map = new();
|
||||
if (input == string.Empty)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
map = input.Trim().Split(",").Select(x => x.Trim().Split(":")).ToDictionary(x => x[0], x => int.Parse(x[1]));
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryParseRangeInfo(string input, out Dictionary<string, (int Min, int Max)> map)
|
||||
{
|
||||
map = new();
|
||||
if (input == string.Empty)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
map = input.Trim()
|
||||
.Split(";")
|
||||
.Select(x => x.Trim().Split(":"))
|
||||
.ToDictionary(x => x[0], x =>
|
||||
{
|
||||
var pair = x[1].Split(",");
|
||||
return (int.Parse(pair[0]), int.Parse(pair[1]));
|
||||
});
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Nncase.Studio;
|
||||
|
||||
public class FontSettings
|
||||
{
|
||||
public string DefaultFontFamily { get; set; } = "fonts:CustomFontFamilies#Nunito";
|
||||
|
||||
public Uri Key { get; set; } = new Uri("fonts:CustomFontFamilies", UriKind.Absolute);
|
||||
|
||||
public Uri Source { get; set; } = new Uri("avares://Nncase.Studio/Assets/Fonts/Nunito", UriKind.Absolute);
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
namespace Nncase.Studio;
|
||||
|
||||
public static class PickerOptions
|
||||
{
|
||||
public static FilePickerOpenOptions DataPickerOptions => new FilePickerOpenOptions
|
||||
{
|
||||
Title = "Select Input File",
|
||||
AllowMultiple = true,
|
||||
FileTypeFilter = new FilePickerFileType[] { new("npy") { Patterns = new[] { "*.npy" } } },
|
||||
};
|
||||
|
||||
public static FilePickerOpenOptions JsonPickerOptions => new FilePickerOpenOptions
|
||||
{
|
||||
Title = "Select Json File",
|
||||
AllowMultiple = true,
|
||||
FileTypeFilter = new FilePickerFileType[] { new("json") { Patterns = new[] { "*.json" } } },
|
||||
};
|
||||
|
||||
public static FilePickerOpenOptions KmodelPickerOptions => new FilePickerOpenOptions
|
||||
{
|
||||
Title = "Select Kmodel",
|
||||
AllowMultiple = true,
|
||||
FileTypeFilter = new FilePickerFileType[] { new("kmodel") { Patterns = new[] { "*.kmodel" } } },
|
||||
};
|
||||
|
||||
public static FilePickerOpenOptions ImporterPickerOptions => new FilePickerOpenOptions
|
||||
{
|
||||
Title = "Open Model File",
|
||||
AllowMultiple = false,
|
||||
FileTypeFilter = new FilePickerFileType[]
|
||||
{
|
||||
new("model") { Patterns = new[] { "*.tflite", "*.onnx", "*.ncnn" } },
|
||||
},
|
||||
};
|
||||
|
||||
public static FilePickerSaveOptions CompileConfPickerSaveOptions => new FilePickerSaveOptions
|
||||
{
|
||||
Title = "Save Conf",
|
||||
SuggestedFileName = "config.json",
|
||||
ShowOverwritePrompt = true,
|
||||
};
|
||||
|
||||
public static FolderPickerOpenOptions FolderPickerOpenOptions => new FolderPickerOpenOptions()
|
||||
{
|
||||
Title = "Select Folder",
|
||||
AllowMultiple = false,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Nncase.Studio.ViewModels;
|
||||
|
||||
namespace Nncase.Studio;
|
||||
|
||||
public static class CustomValidator
|
||||
{
|
||||
public static bool ValidateViewModel<T>(T obj, out ICollection<ValidationResult> results)
|
||||
{
|
||||
results = new List<ValidationResult>();
|
||||
|
||||
return Validator.TryValidateObject(obj!, new ValidationContext(obj!), results, true);
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
|
||||
internal sealed class ValidFloatAttribute : ValidationAttribute
|
||||
{
|
||||
public ValidFloatAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsValid(object? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// value
|
||||
return float.TryParse((string)value, out var _);
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
|
||||
internal sealed class ValidFloatArrayAttribute : ValidationAttribute
|
||||
{
|
||||
public ValidFloatArrayAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsValid(object? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value.GetType() != typeof(string))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var s = (string)value;
|
||||
|
||||
if (s.Contains(",", StringComparison.Ordinal))
|
||||
{
|
||||
var list = s.Split(",");
|
||||
return list.All(s => float.TryParse(s, out var _));
|
||||
}
|
||||
else
|
||||
{
|
||||
return float.TryParse(s, out var _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
|
||||
internal sealed class ValidIntArrayAttribute : ValidationAttribute
|
||||
{
|
||||
public ValidIntArrayAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsValid(object? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value.GetType() != typeof(string))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var s = (string)value;
|
||||
if (s.Contains(",", StringComparison.Ordinal))
|
||||
{
|
||||
var list = s.Split(",");
|
||||
return list.All(s => int.TryParse(s, out var _));
|
||||
}
|
||||
else
|
||||
{
|
||||
return int.TryParse(s, out var _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
|
||||
internal sealed class ValidLayoutAttribute : ValidationAttribute
|
||||
{
|
||||
public ValidLayoutAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsValid(object? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var s = (string)value;
|
||||
if (s.All(c => "NCHW".Contains(c, StringComparison.Ordinal)))
|
||||
{
|
||||
return !HasRepeat(s);
|
||||
}
|
||||
|
||||
if (TryParseNumberList(s, out var numbers))
|
||||
{
|
||||
return !HasRepeat(s) && IsSeqNumber(numbers);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HasRepeat(string s)
|
||||
{
|
||||
var distinct = s.Distinct().ToHashSet();
|
||||
if (distinct.Count != s.Length)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryParseNumberList(string s, out int[] numbers)
|
||||
{
|
||||
if (s.Contains(",", StringComparison.Ordinal))
|
||||
{
|
||||
var charArray = s.Split(",").Select(s => s[0]).ToArray();
|
||||
return IsNumberList(charArray, out numbers);
|
||||
}
|
||||
else
|
||||
{
|
||||
return IsNumberList(s.ToCharArray(), out numbers);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsNumberList(char[] s, out int[] numbers)
|
||||
{
|
||||
if (s.Any(c => !int.TryParse(c.ToString(), out var _)))
|
||||
{
|
||||
numbers = Array.Empty<int>();
|
||||
return false;
|
||||
}
|
||||
|
||||
numbers = s.Select(c => int.Parse(c.ToString())).ToArray();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsSeqNumber(int[] seq)
|
||||
{
|
||||
for (int i = 0; i < seq.Length; i++)
|
||||
{
|
||||
if (seq[i] != i)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
|
||||
internal sealed class ValidBucketVarMapAttribute : ValidationAttribute
|
||||
{
|
||||
public ValidBucketVarMapAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsValid(object? value)
|
||||
{
|
||||
var input = (string)value!;
|
||||
return DataUtil.TryParseFixVarMap(input, out var _);
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
|
||||
internal sealed class ValidBucketRangeInfoAttribute : ValidationAttribute
|
||||
{
|
||||
public ValidBucketRangeInfoAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsValid(object? value)
|
||||
{
|
||||
var input = (string)value!;
|
||||
return DataUtil.TryParseRangeInfo(input, out var _);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Nncase.IR;
|
||||
using Nncase.Quantization;
|
||||
using Nncase.Studio.Util;
|
||||
using Nncase.Studio.ViewModels;
|
||||
|
||||
namespace Nncase.Studio;
|
||||
|
||||
public class ViewModelContext
|
||||
{
|
||||
private readonly MainWindowViewModel _mainWindowView;
|
||||
|
||||
public ViewModelContext(MainWindowViewModel windowViewModel)
|
||||
{
|
||||
_mainWindowView = windowViewModel;
|
||||
}
|
||||
|
||||
public CompileConfig CompileConfig { get; set; } = new();
|
||||
|
||||
public bool CustomPreprocessMode => CompileConfig.PreprocessMode == PreprocessMode.Custom;
|
||||
|
||||
public NavigatorViewModel? Navigator { get; set; }
|
||||
|
||||
public ViewModelBase[] ViewModelBases { get; set; } = Array.Empty<ViewModelBase>();
|
||||
|
||||
public Function? Entry { get; set; }
|
||||
|
||||
public async Task<List<string>> OpenFile(FilePickerOpenOptions options)
|
||||
{
|
||||
return await _mainWindowView.ShowOpenFilePicker.Handle(options);
|
||||
}
|
||||
|
||||
public async Task<string> SaveFile(FilePickerSaveOptions options)
|
||||
{
|
||||
return await _mainWindowView.ShowSaveFilePicker.Handle(options);
|
||||
}
|
||||
|
||||
public async Task<string> OpenFolder(FolderPickerOpenOptions options)
|
||||
{
|
||||
return await _mainWindowView.ShowFolderPicker.Handle(options);
|
||||
}
|
||||
|
||||
public void OpenDialog(string prompt, PromptDialogLevel level = PromptDialogLevel.Error)
|
||||
{
|
||||
_mainWindowView.ShowDialog(prompt, level);
|
||||
}
|
||||
|
||||
public void SwitchToPage(Type page)
|
||||
{
|
||||
var viewModel = ViewModelLookup(page);
|
||||
Navigator?.SwitchToPage(viewModel);
|
||||
}
|
||||
|
||||
public void SwitchNext()
|
||||
{
|
||||
Navigator?.SwitchNext();
|
||||
}
|
||||
|
||||
public ViewModelBase ViewModelLookup(Type type)
|
||||
{
|
||||
foreach (var viewModelBase in ViewModelBases)
|
||||
{
|
||||
if (viewModelBase.GetType() == type)
|
||||
{
|
||||
return viewModelBase;
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"{type} Not Found");
|
||||
}
|
||||
|
||||
public string[] CheckViewModel()
|
||||
{
|
||||
return Navigator!.ContentViewModelList.SelectMany(x => x.CheckViewModel()).ToArray();
|
||||
}
|
||||
|
||||
public CompileConfig ExportConfig()
|
||||
{
|
||||
return CompileConfig;
|
||||
}
|
||||
|
||||
public void ImportConfig(CompileConfig conf)
|
||||
{
|
||||
CompileConfig = conf;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Nncase.Studio.ViewModels;
|
||||
|
||||
namespace Nncase.Studio;
|
||||
|
||||
public class ViewLocator : IDataTemplate
|
||||
{
|
||||
public Control Build(object? data)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
return new TextBlock { Text = "Not Found" };
|
||||
}
|
||||
|
||||
var name = data!.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
|
||||
var type = Type.GetType(name);
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
return (Control)Activator.CreateInstance(type)!;
|
||||
}
|
||||
|
||||
return new TextBlock { Text = "Not Found: " + name };
|
||||
}
|
||||
|
||||
public bool Match(object? data)
|
||||
{
|
||||
return data is ViewModelBase;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using NetFabric.Hyperlinq;
|
||||
using Nncase.Diagnostics;
|
||||
using Nncase.Quantization;
|
||||
using Nncase.Studio.Util;
|
||||
|
||||
namespace Nncase.Studio.ViewModels;
|
||||
|
||||
public enum PreprocessMode
|
||||
{
|
||||
Custom,
|
||||
}
|
||||
|
||||
public partial class CompileOptionViewModel : ViewModelBase
|
||||
{
|
||||
[Required]
|
||||
[ObservableProperty]
|
||||
private string _inputFile = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _dumpDir = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _preprocess;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _quantize = true;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _shapeBucket;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _mixQuantize = false;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _inputFormat = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _target;
|
||||
|
||||
[ObservableProperty]
|
||||
private PreprocessMode _preprocessMode = PreprocessMode.Custom;
|
||||
|
||||
public CompileOptionViewModel(ViewModelContext context)
|
||||
{
|
||||
// skip None
|
||||
DumpFlagsList = new ObservableCollection<DumpFlags>(System.Enum.GetValues<DumpFlags>().Skip(1).ToList());
|
||||
TargetList = new ObservableCollection<string>(new[] { "cpu", "k230" });
|
||||
|
||||
_target = TargetList[0];
|
||||
Context = context;
|
||||
var list = new[] { PreprocessMode.Custom };
|
||||
PreprocessModeList = new(list);
|
||||
}
|
||||
|
||||
public ObservableCollection<DumpFlags> DumpFlagSelected { get; set; } = new();
|
||||
|
||||
public ObservableCollection<DumpFlags> DumpFlagsList { get; set; }
|
||||
|
||||
public ObservableCollection<string> TargetList { get; set; }
|
||||
|
||||
public ObservableCollection<PreprocessMode> PreprocessModeList { get; set; }
|
||||
|
||||
[RelayCommand]
|
||||
public async Task SetDumpDir()
|
||||
{
|
||||
var folder = await Context.OpenFolder(PickerOptions.FolderPickerOpenOptions);
|
||||
if (folder != string.Empty)
|
||||
{
|
||||
DumpDir = folder;
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateViewModelCore(CompileConfig config)
|
||||
{
|
||||
InputFile = config.CompileOption.InputFile;
|
||||
InputFormat = config.CompileOption.InputFormat;
|
||||
DumpDir = config.CompileOption.DumpDir;
|
||||
Target = config.Target;
|
||||
Preprocess = config.CompileOption.PreProcess;
|
||||
MixQuantize = config.MixQuantize;
|
||||
ShapeBucket = config.EnableShapeBucket;
|
||||
Quantize = config.UseQuantize;
|
||||
|
||||
PreprocessMode = config.PreprocessMode;
|
||||
DumpFlagSelected = new(config.DumpFlags.ToArray());
|
||||
}
|
||||
|
||||
public override void UpdateConfig(CompileConfig config)
|
||||
{
|
||||
config.CompileOption.DumpDir = DumpDir;
|
||||
config.DumpFlags = DumpFlagSelected.ToArray();
|
||||
config.CompileOption.DumpFlags = DumpFlagSelected.Aggregate(DumpFlags.None, (flag, sum) => flag | sum);
|
||||
config.Target = Target;
|
||||
config.CompileOption.PreProcess = Preprocess;
|
||||
config.MixQuantize = MixQuantize;
|
||||
config.EnableShapeBucket = ShapeBucket;
|
||||
config.UseQuantize = Quantize;
|
||||
config.PreprocessMode = PreprocessMode;
|
||||
if (Quantize == false)
|
||||
{
|
||||
config.CompileOption.QuantizeOptions.ModelQuantMode = ModelQuantMode.NoQuant;
|
||||
}
|
||||
}
|
||||
|
||||
public override List<string> CheckViewModel()
|
||||
{
|
||||
var list = new List<string>();
|
||||
if (DumpDir == string.Empty)
|
||||
{
|
||||
list.Add("DumpDir can't be empty");
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Nncase.IR;
|
||||
using Nncase.Quantization;
|
||||
using Nncase.Studio.Util;
|
||||
using Nncase.Studio.Views;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Nncase.Studio.ViewModels;
|
||||
|
||||
public partial class CompileViewModel : ViewModelBase
|
||||
{
|
||||
private CancellationTokenSource _cts = new();
|
||||
|
||||
[ObservableProperty]
|
||||
private int _progressBarMax = 9;
|
||||
|
||||
[ObservableProperty]
|
||||
private int _progressBarValue;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _kmodelPath = "test.kmodel";
|
||||
|
||||
public CompileViewModel(ViewModelContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public Task CancelCompile()
|
||||
{
|
||||
_cts.Cancel();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public async Task Compile()
|
||||
{
|
||||
var info = Context.CheckViewModel();
|
||||
if (info.Length != 0)
|
||||
{
|
||||
Context.OpenDialog($"Error List:\n{string.Join("\n", info)}");
|
||||
return;
|
||||
}
|
||||
|
||||
var conf = Context.CompileConfig;
|
||||
var options = conf.CompileOption;
|
||||
if (!Directory.Exists(options.DumpDir))
|
||||
{
|
||||
Directory.CreateDirectory(options.DumpDir);
|
||||
}
|
||||
|
||||
ITarget target;
|
||||
try
|
||||
{
|
||||
target = CompilerServices.GetTarget(conf.Target);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Context.OpenDialog(e.Message, PromptDialogLevel.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
var compileSession = CompileSession.Create(target, options);
|
||||
var compiler = compileSession.Compiler;
|
||||
var module = await compiler.ImportModuleAsync(options.InputFormat, options.InputFile, options.IsBenchmarkOnly);
|
||||
Context.Entry = (Function)module.Entry!;
|
||||
if (options.QuantizeOptions.ModelQuantMode != ModelQuantMode.NoQuant)
|
||||
{
|
||||
var calib = ((QuantizeViewModel)Context.ViewModelLookup(typeof(QuantizeViewModel))).LoadCalibFiles();
|
||||
if (calib == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
options.QuantizeOptions.CalibrationDataset = calib;
|
||||
}
|
||||
|
||||
_cts = new();
|
||||
|
||||
ProgressBarMax = 9;
|
||||
var progress = new Progress<int>(percent =>
|
||||
{
|
||||
ProgressBarValue = percent;
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
await compiler.CompileWithReportAsync(progress, _cts.Token);
|
||||
}).ContinueWith(_ => Task.CompletedTask, _cts.Token);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Context.OpenDialog("Compile has been cancel");
|
||||
ProgressBarValue = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
using (var os = File.OpenWrite(KmodelPath))
|
||||
{
|
||||
compiler.Gencode(os);
|
||||
}
|
||||
|
||||
Context.SwitchNext();
|
||||
Context.OpenDialog($"Compile Finish, kmodel in {KmodelPath}", PromptDialogLevel.Normal);
|
||||
}
|
||||
|
||||
public override void UpdateConfig(CompileConfig config)
|
||||
{
|
||||
config.KmodelPath = KmodelPath;
|
||||
}
|
||||
|
||||
public override void UpdateViewModelCore(CompileConfig config)
|
||||
{
|
||||
KmodelPath = config.KmodelPath;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Nncase.Studio.Util;
|
||||
|
||||
namespace Nncase.Studio.ViewModels;
|
||||
|
||||
public partial class ImportViewModel : ViewModelBase
|
||||
{
|
||||
private string _inputFile = string.Empty;
|
||||
|
||||
private string _inputFormat = string.Empty;
|
||||
|
||||
public ImportViewModel(ViewModelContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public async Task Import()
|
||||
{
|
||||
var path = await Context.OpenFile(PickerOptions.ImporterPickerOptions);
|
||||
if (path == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var ext = Path.GetExtension(path[0]).Trim('.');
|
||||
if (!new[] { "onnx", "tflite", "ncnn" }.Contains(ext))
|
||||
{
|
||||
Context.OpenDialog($"Not Support {ext}");
|
||||
return;
|
||||
}
|
||||
|
||||
_inputFormat = ext;
|
||||
_inputFile = path[0];
|
||||
Context.SwitchNext();
|
||||
}
|
||||
|
||||
public override void UpdateViewModelCore(CompileConfig config)
|
||||
{
|
||||
_inputFile = config.CompileOption.InputFile;
|
||||
_inputFormat = config.CompileOption.InputFormat;
|
||||
}
|
||||
|
||||
public override void UpdateConfig(CompileConfig config)
|
||||
{
|
||||
config.CompileOption.InputFile = _inputFile;
|
||||
config.CompileOption.InputFormat = _inputFormat;
|
||||
}
|
||||
|
||||
public override List<string> CheckViewModel()
|
||||
{
|
||||
var list = new List<string>();
|
||||
if (_inputFile == string.Empty)
|
||||
{
|
||||
list.Add("model path is empty");
|
||||
}
|
||||
else if (!File.Exists(_inputFile))
|
||||
{
|
||||
list.Add($"model path {_inputFile} Not Exist");
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.Rendering.Composition;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Newtonsoft.Json;
|
||||
using Nncase.Diagnostics;
|
||||
using Nncase.IR;
|
||||
using Nncase.Passes.Mutators;
|
||||
using Nncase.Quantization;
|
||||
using Nncase.Runtime.Interop;
|
||||
using Nncase.Studio.Util;
|
||||
using Nncase.Studio.ViewModels;
|
||||
using Nncase.Studio.Views;
|
||||
using Nncase.Utilities;
|
||||
using NumSharp;
|
||||
using ReactiveUI;
|
||||
using static Nncase.Studio.ViewModels.DataUtil;
|
||||
|
||||
namespace Nncase.Studio.ViewModels;
|
||||
|
||||
public enum PromptDialogLevel
|
||||
{
|
||||
Normal,
|
||||
Error,
|
||||
}
|
||||
|
||||
public partial class MainWindowViewModel : WindowViewModelBase
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string _title;
|
||||
|
||||
[ObservableProperty]
|
||||
private ViewModelBase _contentViewModel;
|
||||
|
||||
public MainWindowViewModel()
|
||||
{
|
||||
Context = new ViewModelContext(this);
|
||||
var studioModeViewModel = new StudioModeViewModel(Context);
|
||||
var importViewModel = new ImportViewModel(Context);
|
||||
var compileOptionViewModel = new CompileOptionViewModel(Context);
|
||||
var preprocessViewModel = new PreprocessViewModel(Context);
|
||||
var quantizeViewModel = new QuantizeViewModel(Context);
|
||||
var shapeBucketViewModel = new ShapeBucketViewModel(Context);
|
||||
var compileViewModel = new CompileViewModel(Context);
|
||||
|
||||
// var SimulateInputViewModel = new SimulateInputViewModel(Context);
|
||||
var simulateViewModel = new SimulateViewModel(Context);
|
||||
var contentViewModelList = new ObservableCollection<ViewModelBase>(
|
||||
new ViewModelBase[]
|
||||
{
|
||||
studioModeViewModel,
|
||||
importViewModel,
|
||||
compileOptionViewModel,
|
||||
preprocessViewModel,
|
||||
quantizeViewModel,
|
||||
shapeBucketViewModel,
|
||||
compileViewModel,
|
||||
simulateViewModel,
|
||||
});
|
||||
|
||||
Title = string.Empty;
|
||||
ContentViewModel = contentViewModelList.First();
|
||||
Context.ViewModelBases = contentViewModelList.ToArray();
|
||||
NavigatorViewModelValue = new NavigatorViewModel(contentViewModelList, ShowDialog, UpdateTitle);
|
||||
Context.Navigator = NavigatorViewModelValue;
|
||||
NavigatorViewModelValue.UpdateContentViewModel();
|
||||
}
|
||||
|
||||
public Interaction<FilePickerOpenOptions, List<string>> ShowOpenFilePicker { get; } = new();
|
||||
|
||||
public Interaction<FilePickerSaveOptions, string> ShowSaveFilePicker { get; } = new();
|
||||
|
||||
public Interaction<FolderPickerOpenOptions, string> ShowFolderPicker { get; } = new();
|
||||
|
||||
public NavigatorViewModel NavigatorViewModelValue { get; set; }
|
||||
|
||||
protected ViewModelContext Context { get; set; }
|
||||
|
||||
[RelayCommand]
|
||||
public async Task ExportStudioConfig()
|
||||
{
|
||||
NavigatorViewModelValue.ContentViewModel!.UpdateContext();
|
||||
var quantScheme = Context.ExportConfig();
|
||||
var json = JsonConvert.SerializeObject(quantScheme, Newtonsoft.Json.Formatting.Indented);
|
||||
var path = await Context.SaveFile(PickerOptions.CompileConfPickerSaveOptions);
|
||||
if (path == string.Empty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using var f = new StreamWriter(path);
|
||||
await f.WriteAsync(json);
|
||||
Context.OpenDialog($"export successful {path}");
|
||||
}
|
||||
|
||||
public void UpdateTitle(ViewModelBase contenViewModel)
|
||||
{
|
||||
ContentViewModel = contenViewModel;
|
||||
Title = ContentViewModel.GetType().Name.Split("ViewModel")[0];
|
||||
}
|
||||
|
||||
public void ShowDialog(string prompt, PromptDialogLevel level = PromptDialogLevel.Error)
|
||||
{
|
||||
new AvaloniaUserDialog().ShowDialog(prompt);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using MsBox.Avalonia;
|
||||
|
||||
namespace Nncase.Studio.ViewModels;
|
||||
|
||||
public partial class NavigatorViewModel : ViewModelBase
|
||||
{
|
||||
private readonly Action<ViewModelBase> _windowUpdater;
|
||||
|
||||
private readonly Action<string, PromptDialogLevel> _showDialog;
|
||||
|
||||
[ObservableProperty]
|
||||
private ViewModelBase? _contentViewModel;
|
||||
|
||||
[ObservableProperty]
|
||||
private int _pageIndex = 0;
|
||||
|
||||
[ObservableProperty]
|
||||
private int _pageMaxIndex;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isLast;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _pageIndexString = string.Empty;
|
||||
|
||||
public NavigatorViewModel(ObservableCollection<ViewModelBase> content, Action<string, PromptDialogLevel> showDialog, Action<ViewModelBase> windowUpdater)
|
||||
{
|
||||
ContentViewModelList = content;
|
||||
_windowUpdater = windowUpdater;
|
||||
_showDialog = showDialog;
|
||||
}
|
||||
|
||||
public ObservableCollection<ViewModelBase> ContentViewModelList { get; set; } = new();
|
||||
|
||||
public int PageCount => ContentViewModelList.Count;
|
||||
|
||||
public void SwitchToPage(ViewModelBase page)
|
||||
{
|
||||
UpdateContentViewModel(() =>
|
||||
{
|
||||
var index = ContentViewModelList.IndexOf(page);
|
||||
PageIndex = index;
|
||||
});
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public void SwitchPrev()
|
||||
{
|
||||
UpdateContentViewModel(() =>
|
||||
{
|
||||
do
|
||||
{
|
||||
PageIndex -= 1;
|
||||
} while (!ContentViewModelList[PageIndex].IsVisible());
|
||||
});
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public void SwitchNext()
|
||||
{
|
||||
var check = ContentViewModel!.CheckViewModel();
|
||||
|
||||
if (check.Count != 0)
|
||||
{
|
||||
_showDialog("Err:\n" + string.Join("\n", check), PromptDialogLevel.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateContentViewModel(() =>
|
||||
{
|
||||
do
|
||||
{
|
||||
PageIndex += 1;
|
||||
} while (!ContentViewModelList[PageIndex].IsVisible());
|
||||
});
|
||||
}
|
||||
|
||||
public void UpdateContentViewModel()
|
||||
{
|
||||
UpdateContentViewModel(() => { });
|
||||
}
|
||||
|
||||
public void UpdateContentViewModel(Action updateIndex)
|
||||
{
|
||||
ContentViewModel?.UpdateContext();
|
||||
updateIndex();
|
||||
PageMaxIndex = ContentViewModelList.Count - 1;
|
||||
ContentViewModel = ContentViewModelList[PageIndex];
|
||||
ContentViewModel.UpdateViewModel();
|
||||
_windowUpdater(ContentViewModel);
|
||||
PageIndexString = $"{PageIndex + 1} / {PageCount}";
|
||||
IsLast = PageIndex == PageMaxIndex;
|
||||
}
|
||||
|
||||
public void InsertPageAfter(ViewModelBase page, ViewModelBase pagePosition, int offset = 0)
|
||||
{
|
||||
var i = ContentViewModelList.IndexOf(page);
|
||||
if (i == -1)
|
||||
{
|
||||
var optionIndex = ContentViewModelList.IndexOf(pagePosition);
|
||||
|
||||
// insert after OptionView
|
||||
ContentViewModelList.Insert(optionIndex + offset, page);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemovePage(ViewModelBase page)
|
||||
{
|
||||
var i = ContentViewModelList.IndexOf(page);
|
||||
if (i != -1)
|
||||
{
|
||||
ContentViewModelList.Remove(page);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Nncase.Studio.ViewModels;
|
||||
|
||||
public class OptionViewModel : ViewModelBase
|
||||
{
|
||||
public string? OptName => "Name";
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Nncase.Studio.Util;
|
||||
using Nncase.Studio.Views;
|
||||
|
||||
namespace Nncase.Studio.ViewModels;
|
||||
|
||||
public partial class PreprocessViewModel : ViewModelBase
|
||||
{
|
||||
[ObservableProperty]
|
||||
[ValidIntArray]
|
||||
private string _inputShape = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private InputType _inputTypeValue;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _inputTypeString = string.Empty;
|
||||
|
||||
public PreprocessViewModel(ViewModelContext context)
|
||||
{
|
||||
Context = context;
|
||||
RangeMax = "1";
|
||||
RangeMin = "-1";
|
||||
Mean = "1";
|
||||
Std = "1";
|
||||
LetterBoxValue = "0";
|
||||
InputShape = "1, 3, 24, 24";
|
||||
InputTypeValue = InputType.Float32;
|
||||
}
|
||||
|
||||
public string LayoutWatermark { get; set; } = "e.g. NHWC or NCHW or 0,2,3,1";
|
||||
|
||||
public string ShapeWaterMark { get; set; } = "e.g. 1,3,224,224";
|
||||
|
||||
public string ListNumberWaterMark { get; set; } = "e.g. 2.9,3,5";
|
||||
|
||||
[ValidLayout]
|
||||
public string InputLayout { get; set; } = "NCHW";
|
||||
|
||||
[ValidLayout]
|
||||
public string OutputLayout { get; set; } = "NCHW";
|
||||
|
||||
[ValidLayout]
|
||||
public string ModelLayout { get; set; } = "NCHW";
|
||||
|
||||
public bool SwapRB { get; set; }
|
||||
|
||||
[ValidFloat]
|
||||
public string RangeMin { get; set; }
|
||||
|
||||
[ValidFloat]
|
||||
public string RangeMax { get; set; }
|
||||
|
||||
[ValidFloat]
|
||||
public string LetterBoxValue { get; set; }
|
||||
|
||||
[ValidFloatArray]
|
||||
public string Mean { get; set; }
|
||||
|
||||
[ValidFloatArray]
|
||||
public string Std { get; set; }
|
||||
|
||||
[RelayCommand]
|
||||
public void ShowPreprocessOrder()
|
||||
{
|
||||
new PreprocessWindow().Show();
|
||||
}
|
||||
|
||||
public override void UpdateConfig(CompileConfig config)
|
||||
{
|
||||
var mean = Mean.Split(",").Select(float.Parse).ToArray();
|
||||
var std = Std.Split(",").Select(float.Parse).ToArray();
|
||||
var inShape = Std.Split(",").Select(int.Parse).ToArray();
|
||||
var rangeMin = float.Parse(RangeMin);
|
||||
var rangeMax = float.Parse(RangeMax);
|
||||
var letterBoxValue = float.Parse(LetterBoxValue);
|
||||
|
||||
config.CompileOption.InputLayout = InputLayout;
|
||||
config.CompileOption.OutputLayout = OutputLayout;
|
||||
config.CompileOption.InputType = InputTypeValue;
|
||||
config.CompileOption.InputShape = inShape;
|
||||
config.CompileOption.InputRange = new[] { rangeMin, rangeMax };
|
||||
config.CompileOption.Mean = mean;
|
||||
config.CompileOption.Std = std;
|
||||
config.CompileOption.SwapRB = SwapRB;
|
||||
config.CompileOption.ModelLayout = ModelLayout;
|
||||
config.CompileOption.LetterBoxValue = letterBoxValue;
|
||||
}
|
||||
|
||||
public override void UpdateViewModelCore(CompileConfig config)
|
||||
{
|
||||
InputLayout = config.CompileOption.InputLayout;
|
||||
OutputLayout = config.CompileOption.OutputLayout;
|
||||
InputTypeValue = config.CompileOption.InputType;
|
||||
InputShape = string.Join(",", config.CompileOption.InputShape);
|
||||
var range = config.CompileOption.InputRange;
|
||||
if (range.Length == 2)
|
||||
{
|
||||
RangeMin = range[0].ToString();
|
||||
RangeMax = range[1].ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
RangeMin = string.Empty;
|
||||
RangeMax = string.Empty;
|
||||
}
|
||||
|
||||
Mean = string.Join(",", config.CompileOption.Mean);
|
||||
Std = string.Join(",", config.CompileOption.Std);
|
||||
SwapRB = config.CompileOption.SwapRB;
|
||||
ModelLayout = config.CompileOption.ModelLayout;
|
||||
LetterBoxValue = config.CompileOption.LetterBoxValue.ToString();
|
||||
}
|
||||
|
||||
public override List<string> CheckViewModel()
|
||||
{
|
||||
var l = new List<string>();
|
||||
if (!CustomValidator.ValidateViewModel(this, out var results))
|
||||
{
|
||||
l = l.Concat(results.Select(x => x.ErrorMessage!)).ToList();
|
||||
}
|
||||
|
||||
if (float.TryParse(RangeMin, out var min) && float.TryParse(RangeMax, out var max))
|
||||
{
|
||||
if (max < min)
|
||||
{
|
||||
l.Add("Invalid Range");
|
||||
}
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
public override bool IsVisible()
|
||||
{
|
||||
return Context.CompileConfig.CompileOption.PreProcess && Context.CustomPreprocessMode;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Nncase.Studio.ViewModels;
|
||||
|
||||
public class ProfileViewModel : ViewModelBase
|
||||
{
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Windows.Input;
|
||||
using Avalonia.Controls;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace Nncase.Studio.ViewModels;
|
||||
|
||||
public partial class PromptDialogViewModel : ViewModelBase
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string _dialogContent = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private int _windowWidth = 500;
|
||||
|
||||
[ObservableProperty]
|
||||
private PromptDialogLevel _dialogLevel;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isError;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _title = string.Empty;
|
||||
|
||||
public PromptDialogViewModel(string content, PromptDialogLevel level)
|
||||
{
|
||||
DialogContent = content;
|
||||
DialogLevel = level;
|
||||
IsError = level == PromptDialogLevel.Error;
|
||||
if (IsError)
|
||||
{
|
||||
Title = "错误";
|
||||
}
|
||||
else
|
||||
{
|
||||
Title = "提示";
|
||||
}
|
||||
|
||||
CloseWindowCommand = new RelayCommand<Window>(CloseWindow);
|
||||
WindowWidth = (content.Length * 20) + 60;
|
||||
}
|
||||
|
||||
public RelayCommand<Window> CloseWindowCommand { get; private set; }
|
||||
|
||||
private void CloseWindow(Window? window)
|
||||
{
|
||||
if (window != null)
|
||||
{
|
||||
window.Close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Media.Fonts;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Nncase.IR;
|
||||
using Nncase.Quantization;
|
||||
using Nncase.Studio.Util;
|
||||
using Nncase.Studio.Views;
|
||||
|
||||
namespace Nncase.Studio.ViewModels;
|
||||
|
||||
public partial class QuantizeViewModel : ViewModelBase
|
||||
{
|
||||
[ObservableProperty]
|
||||
private QuantizeOptions _quantizeOptionsValue;
|
||||
|
||||
[ObservableProperty]
|
||||
private CalibMethod _calibMethodValue;
|
||||
|
||||
[ObservableProperty]
|
||||
private QuantType _quantTypeValue;
|
||||
|
||||
[ObservableProperty]
|
||||
private QuantType _wQuantTypeValue;
|
||||
|
||||
[ObservableProperty]
|
||||
private ModelQuantMode _modelQuantModeValue;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _mixQuantize;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _exportQuantScheme;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _quantSchemePath = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _exportQuantSchemePath = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _calibDir = string.Empty;
|
||||
|
||||
private string[] _inputFiles = Array.Empty<string>();
|
||||
|
||||
public QuantizeViewModel(ViewModelContext context)
|
||||
{
|
||||
ModelQuantModeList = new ObservableCollection<ModelQuantMode>(Enum.GetValues<ModelQuantMode>().Skip(1).ToList());
|
||||
ModelQuantModeValue = ModelQuantMode.UsePTQ;
|
||||
QuantizeOptionsValue = new();
|
||||
Context = context;
|
||||
}
|
||||
|
||||
public ObservableCollection<ModelQuantMode> ModelQuantModeList { get; set; }
|
||||
|
||||
[RelayCommand]
|
||||
public async Task SelectQuantScheme()
|
||||
{
|
||||
var path = await Context.OpenFile(PickerOptions.JsonPickerOptions);
|
||||
if (path.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var json = path[0];
|
||||
if (Path.GetExtension(json) != ".json")
|
||||
{
|
||||
Context.OpenDialog("QuantScheme Should use .json");
|
||||
return;
|
||||
}
|
||||
|
||||
QuantSchemePath = json;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public async Task SelectCalibrationDataSet()
|
||||
{
|
||||
var path = await Context.OpenFolder(PickerOptions.FolderPickerOpenOptions);
|
||||
if (path == string.Empty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var inputFiles = Directory.GetFiles(path);
|
||||
if (inputFiles.Length == 0)
|
||||
{
|
||||
Context.OpenDialog("empty dir");
|
||||
return;
|
||||
}
|
||||
|
||||
CalibDir = path;
|
||||
_inputFiles = inputFiles;
|
||||
}
|
||||
|
||||
public ICalibrationDatasetProvider? LoadCalibFiles()
|
||||
{
|
||||
Tensor[] input;
|
||||
try
|
||||
{
|
||||
input = DataUtil.ReadInput(_inputFiles).ToArray();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Context.OpenDialog(e.Message);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (input.Length == 0)
|
||||
{
|
||||
Context.OpenDialog("no file is loaded, only support .npy");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Context.Entry == null)
|
||||
{
|
||||
Context.OpenDialog("Should Import Model first");
|
||||
return null;
|
||||
}
|
||||
|
||||
var samples = Context.Entry!.Parameters.ToArray().Zip(input)
|
||||
.ToDictionary(pair => pair.First, pair => (IValue)Value.FromTensor(pair.Second));
|
||||
return new SelfInputCalibrationDatasetProvider(samples);
|
||||
}
|
||||
|
||||
public override void UpdateViewModelCore(CompileConfig config)
|
||||
{
|
||||
QuantizeOptionsValue = config.CompileOption.QuantizeOptions;
|
||||
if (ExportQuantSchemePath == string.Empty)
|
||||
{
|
||||
ExportQuantSchemePath = Path.Join(config.CompileOption.DumpDir, "QuantScheme.json");
|
||||
}
|
||||
|
||||
MixQuantize = config.MixQuantize;
|
||||
}
|
||||
|
||||
public override void UpdateConfig(CompileConfig config)
|
||||
{
|
||||
QuantizeOptionsValue.CalibrationMethod = CalibMethodValue;
|
||||
QuantizeOptionsValue.QuantType = DataUtil.QuantTypeToDataType(QuantTypeValue);
|
||||
QuantizeOptionsValue.WQuantType = DataUtil.QuantTypeToDataType(WQuantTypeValue);
|
||||
QuantizeOptionsValue.ModelQuantMode = ModelQuantModeValue;
|
||||
QuantizeOptionsValue.QuantScheme = QuantSchemePath;
|
||||
QuantizeOptionsValue.ExportQuantScheme = ExportQuantScheme;
|
||||
QuantizeOptionsValue.ExportQuantSchemePath = ExportQuantSchemePath;
|
||||
config.CompileOption.QuantizeOptions = QuantizeOptionsValue;
|
||||
}
|
||||
|
||||
public override List<string> CheckViewModel()
|
||||
{
|
||||
var list = new List<string>();
|
||||
if (Context.CompileConfig.MixQuantize)
|
||||
{
|
||||
if (QuantSchemePath == string.Empty)
|
||||
{
|
||||
list.Add("QuantSchemePath should not be empty");
|
||||
}
|
||||
else if (!File.Exists(QuantSchemePath))
|
||||
{
|
||||
list.Add("QuantSchemePath not exist, please check file and path");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Directory.Exists(CalibDir))
|
||||
{
|
||||
if (_inputFiles.Length == 0)
|
||||
{
|
||||
list.Add("CalibDir don't exist any .npy file");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add($"CalibDir {CalibDir} not exist");
|
||||
}
|
||||
|
||||
if (QuantTypeValue == QuantType.Int16 && WQuantTypeValue == QuantType.Int16 &&
|
||||
string.Equals(Context.CompileConfig.Target, "k230", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
list.Add("k230 not support QuantType and WeightsQuantType are int16");
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public override bool IsVisible() => Context.CompileConfig.UseQuantize;
|
||||
}
|
||||
|
||||
public sealed class SelfInputCalibrationDatasetProvider : ICalibrationDatasetProvider
|
||||
{
|
||||
private readonly int _count = 1;
|
||||
|
||||
private readonly IAsyncEnumerable<IReadOnlyDictionary<Var, IValue>> _samples;
|
||||
|
||||
public SelfInputCalibrationDatasetProvider(IReadOnlyDictionary<Var, IValue> sample)
|
||||
{
|
||||
_samples = new[] { sample }.ToAsyncEnumerable();
|
||||
}
|
||||
|
||||
public int? Count => _count;
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyDictionary<Var, IValue>> Samples => _samples;
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using NetFabric.Hyperlinq;
|
||||
using Nncase.Studio.Util;
|
||||
|
||||
namespace Nncase.Studio.ViewModels;
|
||||
|
||||
public partial class ShapeBucketViewModel : ViewModelBase
|
||||
{
|
||||
[ObservableProperty]
|
||||
private int _segmentCount = 5;
|
||||
|
||||
[ValidBucketVarMap]
|
||||
[ObservableProperty]
|
||||
private string _fixVarMap = string.Empty;
|
||||
|
||||
[ValidBucketRangeInfo]
|
||||
[ObservableProperty]
|
||||
private string _varRangeInfo = string.Empty;
|
||||
|
||||
public ShapeBucketViewModel(ViewModelContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
public override void UpdateConfig(CompileConfig config)
|
||||
{
|
||||
var options = new ShapeBucketOptions();
|
||||
options.Enable = true;
|
||||
options.SegmentsCount = SegmentCount;
|
||||
|
||||
if (DataUtil.TryParseFixVarMap(FixVarMap, out var fixVarMap))
|
||||
{
|
||||
options.FixVarMap = fixVarMap;
|
||||
}
|
||||
|
||||
if (DataUtil.TryParseRangeInfo(VarRangeInfo, out var rangeInfo))
|
||||
{
|
||||
options.RangeInfo = rangeInfo;
|
||||
}
|
||||
|
||||
config.CompileOption.ShapeBucketOptions = options;
|
||||
}
|
||||
|
||||
public override void UpdateViewModelCore(CompileConfig config)
|
||||
{
|
||||
var option = config.CompileOption.ShapeBucketOptions;
|
||||
SegmentCount = option.SegmentsCount;
|
||||
VarRangeInfo = string.Join(",", option.FixVarMap.Select(pair => $"{pair.Key}:{pair.Value}"));
|
||||
FixVarMap = string.Join(",", option.RangeInfo.Select(pair => $"{pair.Key}:({pair.Value.Min}, {pair.Value.Max})"));
|
||||
}
|
||||
|
||||
public override bool IsVisible() => Context.CompileConfig.EnableShapeBucket;
|
||||
|
||||
public override List<string> CheckViewModel()
|
||||
{
|
||||
if (!CustomValidator.ValidateViewModel(this, out var results))
|
||||
{
|
||||
return results.Select(x => x.ErrorMessage!).ToList();
|
||||
}
|
||||
|
||||
return new();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Nncase.Studio.ViewModels;
|
||||
|
||||
public class SimulateInputViewModel : ViewModelBase
|
||||
{
|
||||
}
|
|
@ -0,0 +1,325 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Nncase.IR;
|
||||
using Nncase.Studio.Util;
|
||||
using NumSharp;
|
||||
|
||||
namespace Nncase.Studio.ViewModels;
|
||||
|
||||
public partial class SimulateViewModel : ViewModelBase
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string _resultDir = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _kmodelPath = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _status = "未运行";
|
||||
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<Tensor> _runtimeInput = new();
|
||||
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<string> _inputPath = new();
|
||||
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<string> _mainParamStr = new();
|
||||
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<string> _inputTypeStr = new();
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _runSimulate;
|
||||
|
||||
public SimulateViewModel(ViewModelContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public async Task SetRuntimeInput()
|
||||
{
|
||||
var path = await Context.OpenFile(PickerOptions.DataPickerOptions);
|
||||
if (path.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Tensor[] input;
|
||||
string[] inputFiles;
|
||||
try
|
||||
{
|
||||
(inputFiles, input) = DataUtil.ReadMultiInputs(path);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Context.OpenDialog(e.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateRuntimeInputUI(input, inputFiles);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public async Task SetResultDir()
|
||||
{
|
||||
var folder = await Context.OpenFolder(PickerOptions.FolderPickerOpenOptions);
|
||||
if (folder != string.Empty)
|
||||
{
|
||||
ResultDir = folder;
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public async Task Simulate()
|
||||
{
|
||||
if (!File.Exists(KmodelPath))
|
||||
{
|
||||
Context.OpenDialog("Kmodel Not Exist");
|
||||
return;
|
||||
}
|
||||
|
||||
if (RuntimeInput.Count == 0)
|
||||
{
|
||||
Context.OpenDialog("Not Set Input");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CheckInput())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var cts = new CancellationTokenSource();
|
||||
|
||||
try
|
||||
{
|
||||
using (var interp = Runtime.Interop.RTInterpreter.Create())
|
||||
{
|
||||
var kmodel = File.ReadAllBytes(KmodelPath);
|
||||
interp.SetDumpRoot(Context.CompileConfig.CompileOption.DumpDir);
|
||||
interp.LoadModel(kmodel);
|
||||
var entry = interp.Entry!;
|
||||
var rtInputs = RuntimeInput.Select(Runtime.Interop.RTTensor.FromTensor).ToArray();
|
||||
|
||||
var start = System.DateTime.Now;
|
||||
Status = "Running";
|
||||
RunSimulate = true;
|
||||
|
||||
var task = Task.Run(
|
||||
() =>
|
||||
{
|
||||
UpdateTime(cts, start);
|
||||
},
|
||||
cts.Token);
|
||||
await Task.Run(() =>
|
||||
{
|
||||
var result = entry.Invoke(rtInputs).ToValue().AsTensors();
|
||||
SaveResult(result);
|
||||
}).ContinueWith(t => t, cts.Token);
|
||||
|
||||
SimulateFinish(cts);
|
||||
Context.OpenDialog($"Simulate Finish, spent time:{Status}\n result in {ResultDir}", PromptDialogLevel.Normal);
|
||||
Status = "Finish";
|
||||
}
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
Context.OpenDialog("libNncase.Native.so not found");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var msg = ExceptionMessageProcess(e);
|
||||
Context.OpenDialog(msg);
|
||||
}
|
||||
finally
|
||||
{
|
||||
SimulateFinish(cts);
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateViewModelCore(CompileConfig config)
|
||||
{
|
||||
ResultDir = config.ResultDir;
|
||||
KmodelPath = config.KmodelPath;
|
||||
InputPath = new(config.InputPathList);
|
||||
}
|
||||
|
||||
public override void UpdateConfig(CompileConfig config)
|
||||
{
|
||||
config.ResultDir = ResultDir;
|
||||
config.InputPathList = InputPath.ToArray();
|
||||
}
|
||||
|
||||
private bool CheckInput()
|
||||
{
|
||||
if (Context.Entry == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var paramList = Context.Entry!.Parameters.ToArray();
|
||||
foreach ((var tensor, var param) in RuntimeInput.Zip(paramList))
|
||||
{
|
||||
var tt = (TensorType)param.TypeAnnotation;
|
||||
if (tensor.ElementType != tt.DType)
|
||||
{
|
||||
Context.OpenDialog($"{param.Name} input datatype mismatch");
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (tt.Shape.Count != tensor.Shape.Count || tt.Shape.Zip(tensor.Shape)
|
||||
.Any(pair => pair.First.IsFixed && pair.First != pair.Second))
|
||||
{
|
||||
Context.OpenDialog($"{param.Name} input shape mismatch");
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task SetKmodelPath()
|
||||
{
|
||||
var kmodel = await Context.OpenFile(PickerOptions.KmodelPickerOptions);
|
||||
if (kmodel.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
KmodelPath = kmodel[0];
|
||||
}
|
||||
|
||||
private void SaveResult(Tensor[] result)
|
||||
{
|
||||
var list = result
|
||||
.Select(t =>
|
||||
np.frombuffer(t.BytesBuffer.ToArray(), t.ElementType.CLRType)
|
||||
.reshape(t.Shape.ToValueArray()))
|
||||
.ToArray();
|
||||
|
||||
for (int i = 0; i < list.Length; i++)
|
||||
{
|
||||
np.save(Path.Join(ResultDir, $"nncase_result_{i}.npy"), list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTime(CancellationTokenSource cts, DateTime start)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Thread.Sleep(20);
|
||||
if (cts.Token.IsCancellationRequested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var now = System.DateTime.Now;
|
||||
var timeStr = (now - start).ToString();
|
||||
Status = timeStr.Substring(3, timeStr.Length - 8);
|
||||
}
|
||||
}
|
||||
|
||||
private void SimulateFinish(CancellationTokenSource cts)
|
||||
{
|
||||
cts.Cancel();
|
||||
RunSimulate = false;
|
||||
}
|
||||
|
||||
private string ExceptionMessageProcess(Exception exception)
|
||||
{
|
||||
var msg = exception.Message;
|
||||
if (msg.Contains("Status code", StringComparison.Ordinal))
|
||||
{
|
||||
if (int.TryParse(msg.Split(":")[1].Trim(), out var errc))
|
||||
{
|
||||
return ErrcToString(errc);
|
||||
}
|
||||
|
||||
return exception.ToString();
|
||||
}
|
||||
|
||||
return exception.ToString();
|
||||
}
|
||||
|
||||
private string ErrcToString(int errc)
|
||||
{
|
||||
string errcStr;
|
||||
switch (-errc)
|
||||
{
|
||||
case 0x01:
|
||||
errcStr = "invalid model indentifier";
|
||||
break;
|
||||
case 0x02:
|
||||
errcStr = "invalid model checksum";
|
||||
break;
|
||||
case 0x03:
|
||||
errcStr = "invalid model version";
|
||||
break;
|
||||
case 0x04:
|
||||
errcStr = "runtime not found";
|
||||
break;
|
||||
case 0x05:
|
||||
errcStr = "datatype mismatch";
|
||||
break;
|
||||
case 0x06:
|
||||
errcStr = "shape mismatch";
|
||||
break;
|
||||
case 0x07:
|
||||
errcStr = "invalid memory location";
|
||||
break;
|
||||
case 0x08:
|
||||
errcStr = "runtime register not found";
|
||||
break;
|
||||
case 0x0100:
|
||||
errcStr = "stackvm illegal instruction";
|
||||
break;
|
||||
case 0x0101:
|
||||
errcStr = "stackvm illegal target";
|
||||
break;
|
||||
case 0x0102:
|
||||
errcStr = "stackvm stack overflow";
|
||||
break;
|
||||
case 0x0103:
|
||||
errcStr = "stackvm stack underflow";
|
||||
break;
|
||||
case 0x0104:
|
||||
errcStr = "stackvm unknow custom call";
|
||||
break;
|
||||
case 0x0105:
|
||||
errcStr = "stackvm duplicate custom call";
|
||||
break;
|
||||
case 0x0200:
|
||||
errcStr = "nnil illegal instruction";
|
||||
break;
|
||||
default:
|
||||
errcStr = $"Unknown Status code: {errc}";
|
||||
break;
|
||||
}
|
||||
|
||||
return errcStr;
|
||||
}
|
||||
|
||||
private void UpdateRuntimeInputUI(Tensor[] input, string[] inputFiles)
|
||||
{
|
||||
RuntimeInput = new ObservableCollection<Tensor>(input);
|
||||
InputPath = new ObservableCollection<string>(inputFiles);
|
||||
InputTypeStr = new ObservableCollection<string>(RuntimeInput
|
||||
.Select(x => DataUtil.TensorTypeToString(new TensorType(x.ElementType, x.Shape))).ToList());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Newtonsoft.Json;
|
||||
using Nncase.Studio.Util;
|
||||
using Nncase.Studio.Views;
|
||||
|
||||
namespace Nncase.Studio.ViewModels;
|
||||
|
||||
public partial class StudioModeViewModel : ViewModelBase
|
||||
{
|
||||
public StudioModeViewModel(ViewModelContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public async Task ImportStudioConfig()
|
||||
{
|
||||
var selectFiles = await Context.OpenFile(PickerOptions.JsonPickerOptions);
|
||||
if (selectFiles.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
var configFile = selectFiles[0];
|
||||
var conf = JsonConvert.DeserializeObject<CompileConfig>(File.ReadAllText(configFile));
|
||||
Context.ImportConfig(conf!);
|
||||
}
|
||||
|
||||
Context.SwitchToPage(typeof(CompileOptionViewModel));
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void SwitchToImportView()
|
||||
{
|
||||
Context.SwitchToPage(typeof(ImportViewModel));
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void SwitchToSimulateView()
|
||||
{
|
||||
Context.SwitchToPage(typeof(SimulateViewModel));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Nncase.Studio.Util;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Nncase.Studio.ViewModels;
|
||||
|
||||
public class WindowViewModelBase : ObservableValidator
|
||||
{
|
||||
}
|
||||
|
||||
public class ViewModelBase : ObservableValidator
|
||||
{
|
||||
private ViewModelContext? _context;
|
||||
|
||||
protected ViewModelContext Context
|
||||
{
|
||||
get { return _context!; }
|
||||
set { _context = value; }
|
||||
}
|
||||
|
||||
public void UpdateContext()
|
||||
{
|
||||
UpdateConfig(Context.CompileConfig);
|
||||
}
|
||||
|
||||
public void UpdateViewModel()
|
||||
{
|
||||
UpdateViewModelCore(Context.CompileConfig);
|
||||
}
|
||||
|
||||
public virtual List<string> CheckViewModel()
|
||||
{
|
||||
return new();
|
||||
}
|
||||
|
||||
public virtual void UpdateConfig(CompileConfig config)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void UpdateViewModelCore(CompileConfig config)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual bool IsVisible()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="clr-namespace:Nncase.Studio.ViewModels"
|
||||
xmlns:quantization="clr-namespace:Nncase.Quantization;assembly=Nncase.Core"
|
||||
xmlns:views="clr-namespace:Nncase.Studio.Views"
|
||||
xmlns:studio="clr-namespace:Nncase.Studio"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Nncase.Studio.Views.CompileOptionView"
|
||||
x:DataType="viewModels:CompileOptionViewModel">
|
||||
|
||||
<UserControl.Resources>
|
||||
<studio:EnumConverter x:Key="EnumConverter" />
|
||||
</UserControl.Resources>
|
||||
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="0" Content="模型文件路径"/>
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Classes="Path" Text="{Binding InputFile}" IsReadOnly="True"/>
|
||||
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="模型格式"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" Margin="15" Text="{Binding InputFormat, Mode=TwoWay}"/>
|
||||
|
||||
<Label Grid.Row="2" Grid.Column="0" Content="Dump选项"/>
|
||||
<SplitButton Margin="3" Grid.Row="2" Grid.Column="1" Content="DumpFlags" >
|
||||
<SplitButton.Flyout>
|
||||
<Flyout Placement="Bottom">
|
||||
<ListBox
|
||||
SelectionMode="Multiple,Toggle"
|
||||
SelectedItems="{Binding DumpFlagSelected}"
|
||||
ItemsSource="{Binding DumpFlagsList}">
|
||||
</ListBox>
|
||||
</Flyout>
|
||||
</SplitButton.Flyout>
|
||||
</SplitButton>
|
||||
|
||||
<Label Grid.Row="3" Grid.Column="0" Content="Dump路径"/>
|
||||
<DockPanel Grid.Row="3" Grid.Column="1">
|
||||
<TextBox Classes="Path" Text="{Binding DumpDir}"/>
|
||||
<Button
|
||||
Content="选择"
|
||||
Command="{Binding SetDumpDirCommand}">
|
||||
</Button>
|
||||
</DockPanel>
|
||||
|
||||
<Label Grid.Row="4" Grid.Column="0" Content="目标平台"/>
|
||||
<DockPanel Grid.Row="4" Grid.Column="1">
|
||||
<ComboBox ItemsSource="{Binding TargetList}" SelectedItem="{Binding Target}" Width="100"/>
|
||||
<Label Content="Nncase Studio 目前只支持 CPU, K230这两个平台"/>
|
||||
</DockPanel>
|
||||
|
||||
<Label Grid.Row="5" Grid.Column="0" Content="开启量化"/>
|
||||
<DockPanel Grid.Row="5" Grid.Column="1">
|
||||
<CheckBox IsChecked="{Binding Quantize}"/>
|
||||
<Label IsVisible="{Binding Quantize}" Content="是否使用混合量化"></Label>
|
||||
<CheckBox IsVisible="{Binding Quantize}"
|
||||
IsChecked="{Binding MixQuantize}"></CheckBox>
|
||||
</DockPanel>
|
||||
|
||||
<Label Grid.Row="6" Grid.Column="0" Content="开启前后处理"/>
|
||||
<DockPanel Grid.Row="6" Grid.Column="1">
|
||||
<CheckBox IsChecked="{Binding Preprocess}"/>
|
||||
<!-- <Label Content="前后处理模式" IsVisible="{Binding Preprocess}"></Label> -->
|
||||
<!-- <ComboBox IsVisible="{Binding Preprocess}" ItemsSource="{Binding PreprocessModeList}" SelectedValue="{Binding PreprocessMode}"></ComboBox> -->
|
||||
</DockPanel>
|
||||
|
||||
|
||||
<Label Grid.Row="7" Grid.Column="0" Content="开启ShapeBucket"/>
|
||||
<CheckBox Grid.Row="7" Grid.Column="1" IsChecked="{Binding ShapeBucket}"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Nncase.Studio.Views
|
||||
{
|
||||
public partial class CompileOptionView : UserControl
|
||||
{
|
||||
public CompileOptionView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="clr-namespace:Nncase.Studio.ViewModels"
|
||||
xmlns:views="clr-namespace:Nncase.Studio.Views"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Nncase.Studio.Views.CompileView"
|
||||
x:DataType="viewModels:CompileViewModel">
|
||||
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<Grid Margin="30">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Grid.Row="0" Grid.Column="0" Content="Kmodel路径" VerticalAlignment="Center"></Label>
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Classes="Path" Text="{Binding KmodelPath}" Watermark="Path or Name"></TextBox>
|
||||
</Grid>
|
||||
<DockPanel HorizontalAlignment="Center" Margin="4">
|
||||
<Button Margin= "25"
|
||||
Content="编译"
|
||||
Command="{Binding CompileCommand}">
|
||||
</Button>
|
||||
<Button Margin="25"
|
||||
Content="停止"
|
||||
Command="{Binding CancelCompileCommand}">
|
||||
</Button>
|
||||
</DockPanel>
|
||||
<ProgressBar Minimum="0" Maximum="{Binding ProgressBarMax}" Value="{Binding ProgressBarValue}" Height="20"></ProgressBar>
|
||||
</StackPanel>
|
||||
|
||||
</UserControl>
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Nncase.Studio.Views
|
||||
{
|
||||
public partial class CompileView : UserControl
|
||||
{
|
||||
public CompileView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:studio="clr-namespace:Nncase.Studio"
|
||||
xmlns:viewModels="clr-namespace:Nncase.Studio.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Nncase.Studio.Views.EnumComboBox">
|
||||
|
||||
<UserControl.Resources>
|
||||
<studio:EnumConverter x:Key="EnumConverter" />
|
||||
</UserControl.Resources>
|
||||
|
||||
<DockPanel>
|
||||
<Label x:Name="Label"></Label>
|
||||
<ComboBox x:Name="ComboBoxList"></ComboBox></DockPanel>
|
||||
</UserControl>
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using GiGraph.Dot.Entities.Html.Font.Styles;
|
||||
|
||||
namespace Nncase.Studio.Views
|
||||
{
|
||||
public partial class EnumComboBox : ComboBox
|
||||
{
|
||||
public static readonly StyledProperty<Type> TypeNameProperty =
|
||||
AvaloniaProperty.Register<EnumComboBox, Type>(nameof(TypeName));
|
||||
|
||||
public Type TypeName
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetValue(TypeNameProperty);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetValue(TypeNameProperty, value);
|
||||
var names = Enum.GetNames(TypeName);
|
||||
foreach (string name in names)
|
||||
{
|
||||
Items.Add(name);
|
||||
}
|
||||
|
||||
SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(Avalonia.Controls.ComboBox);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:views="clr-namespace:Nncase.Studio.Views"
|
||||
xmlns:viewModels="clr-namespace:Nncase.Studio.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Nncase.Studio.Views.ImportView"
|
||||
x:DataType="viewModels:ImportViewModel"
|
||||
FontSize="32">
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<!-- 插入三种模型的logo -->
|
||||
<Label HorizontalAlignment="Center" Content="支持的模型格式:NCNN ONNX TFLite"></Label>
|
||||
<DockPanel HorizontalAlignment="Center" Name="LogoPanel">
|
||||
<Image Source="/Assets/ncnn-logo.png"></Image>
|
||||
<Image Source="/Assets/ONNX-logo.png"></Image>
|
||||
<Image Source="/Assets/tflite-logo.png"></Image>
|
||||
</DockPanel>
|
||||
|
||||
<Button Name="ImportButton"
|
||||
Content="Import"
|
||||
FontSize="40"
|
||||
Command="{Binding ImportCommand}">
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</UserControl>
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Nncase.Studio.Views
|
||||
{
|
||||
public partial class ImportView : UserControl
|
||||
{
|
||||
public ImportView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:Nncase.Studio.ViewModels"
|
||||
xmlns:flg="using:Nncase.Diagnostics"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:global="clr-namespace:"
|
||||
xmlns:studio="clr-namespace:Nncase.Studio"
|
||||
xmlns:views="clr-namespace:Nncase.Studio.Views"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
MinHeight="880"
|
||||
MinWidth="1400"
|
||||
x:Class="Nncase.Studio.Views.MainWindow"
|
||||
x:DataType="vm:MainWindowViewModel"
|
||||
Icon="/Assets/nncase-logo.png"
|
||||
Title="Nncase.Studio">
|
||||
|
||||
<Window.Resources>
|
||||
<x:Double x:Key="ControlContentThemeFontSize">24</x:Double>
|
||||
<studio:EnumConverter x:Key="EnumConverter"/>
|
||||
</Window.Resources>
|
||||
|
||||
<Design.DataContext>
|
||||
<!-- This only sets the DataContext for the previewer in an IDE,
|
||||
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
|
||||
<vm:MainWindowViewModel/>
|
||||
</Design.DataContext>
|
||||
|
||||
<!-- bind data contenxt -->
|
||||
<!-- <Border Background="MediumPurple" -->
|
||||
<Border Background="White"
|
||||
BorderBrush="Black"
|
||||
BorderThickness="0"
|
||||
CornerRadius="3"
|
||||
Padding="100 0">
|
||||
<StackPanel>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image Grid.Column="0" Source="/Assets/canaan-logo.png" Width="250" Height="90" HorizontalAlignment="Left"></Image>
|
||||
<Label Grid.Column="1" FontWeight="Bold" FontSize="54" Content="{Binding Title}" HorizontalAlignment="Center" VerticalAlignment="Center"></Label>
|
||||
<Image Grid.Column="2" Source="/Assets/nncase-full-logo.png" Width="180" Height="90" HorizontalAlignment="Right"></Image>
|
||||
</Grid>
|
||||
|
||||
<Border Background="White"
|
||||
BorderBrush="Black"
|
||||
BorderThickness="3"
|
||||
CornerRadius="3"
|
||||
Padding="4">
|
||||
<Label
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
MinHeight="640"
|
||||
Content="{Binding ContentViewModel}"></Label>
|
||||
</Border>
|
||||
<Border Background="White"
|
||||
BorderBrush="Black"
|
||||
BorderThickness="0"
|
||||
CornerRadius="3"
|
||||
Padding="4">
|
||||
<DockPanel HorizontalAlignment="Center">
|
||||
<views:NavigatorView HorizontalAlignment="Center" DataContext="{Binding NavigatorViewModelValue}"></views:NavigatorView>
|
||||
<Button Content="导出编译配置" Command="{Binding ExportStudioConfigCommand}"></Button>
|
||||
</DockPanel>
|
||||
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Window>
|
|
@ -0,0 +1,86 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Nncase.Diagnostics;
|
||||
using Nncase.Studio.ViewModels;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Nncase.Studio.Views;
|
||||
|
||||
public partial class MainWindow : ReactiveWindow<MainWindowViewModel>
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(action =>
|
||||
{
|
||||
action(ViewModel!.ShowOpenFilePicker.RegisterHandler(OpenFileButtonClicked));
|
||||
action(ViewModel!.ShowSaveFilePicker.RegisterHandler(SaveFileButtonClicked));
|
||||
action(ViewModel!.ShowFolderPicker.RegisterHandler(OpenFolderButtonClicked));
|
||||
});
|
||||
}
|
||||
|
||||
public async Task OpenFolderButtonClicked(InteractionContext<FolderPickerOpenOptions, string> interaction)
|
||||
{
|
||||
// Get top level from the current control. Alternatively, you can use Window reference instead.
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
|
||||
// Start async operation to open the dialog.
|
||||
var folder = await topLevel!.StorageProvider.OpenFolderPickerAsync(interaction.Input);
|
||||
if (folder.Count == 0)
|
||||
{
|
||||
interaction.SetOutput(string.Empty);
|
||||
return;
|
||||
}
|
||||
|
||||
interaction.SetOutput(folder[0].Path.LocalPath);
|
||||
}
|
||||
|
||||
public async Task OpenFileButtonClicked(InteractionContext<FilePickerOpenOptions, List<string>> interaction)
|
||||
{
|
||||
// Get top level from the current control. Alternatively, you can use Window reference instead.
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
|
||||
// Start async operation to open the dialog.
|
||||
var files = await topLevel!.StorageProvider.OpenFilePickerAsync(interaction.Input);
|
||||
|
||||
if (files.Count >= 1)
|
||||
{
|
||||
var path = files.Select(f => f.Path.LocalPath).ToList();
|
||||
interaction.SetOutput(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
interaction.SetOutput(new List<string>());
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SaveFileButtonClicked(InteractionContext<FilePickerSaveOptions, string> interaction)
|
||||
{
|
||||
// Get top level from the current control. Alternatively, you can use Window reference instead.
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
|
||||
// Start async operation to open the dialog.
|
||||
var res = await topLevel!.StorageProvider.SaveFilePickerAsync(interaction.Input);
|
||||
if (res != null)
|
||||
{
|
||||
interaction.SetOutput(res.Path.LocalPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
interaction.SetOutput(string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="clr-namespace:Nncase.Studio.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Nncase.Studio.Views.NavigatorView"
|
||||
x:DataType="viewModels:NavigatorViewModel">
|
||||
|
||||
<DockPanel Margin="10">
|
||||
<Border Background="White"
|
||||
BorderBrush="Black"
|
||||
BorderThickness="0"
|
||||
CornerRadius="3"
|
||||
Padding="4">
|
||||
<Grid Width="260">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button
|
||||
Grid.Row="0" Grid.Column="0"
|
||||
Content="上一步"
|
||||
IsVisible="{Binding PageIndex}"
|
||||
Command="{Binding SwitchPrevCommand}">
|
||||
</Button>
|
||||
<Button
|
||||
Grid.Row="0" Grid.Column="1"
|
||||
Content="下一步"
|
||||
IsVisible="{Binding !IsLast}"
|
||||
Command="{Binding SwitchNextCommand}">
|
||||
</Button>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Label
|
||||
Width="60"
|
||||
Margin="10"
|
||||
VerticalAlignment="Center"
|
||||
Content="{Binding PageIndexString}">
|
||||
</Label>
|
||||
|
||||
<ProgressBar
|
||||
Margin="10"
|
||||
VerticalAlignment="Center"
|
||||
Minimum="0"
|
||||
Maximum="{Binding PageMaxIndex}"
|
||||
Value="{Binding PageIndex}"></ProgressBar>
|
||||
</DockPanel>
|
||||
|
||||
</UserControl>
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Nncase.Studio.Views
|
||||
{
|
||||
public partial class NavigatorView : UserControl
|
||||
{
|
||||
public NavigatorView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:views="clr-namespace:Nncase.Studio.Views"
|
||||
xmlns:viewModels="clr-namespace:Nncase.Studio.ViewModels"
|
||||
xmlns:nncase="clr-namespace:Nncase;assembly=Nncase.Core"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Nncase.Studio.Views.PreprocessView"
|
||||
x:DataType="viewModels:PreprocessViewModel">
|
||||
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="0" Content="InputLayout" />
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding InputLayout}"
|
||||
Watermark="{Binding LayoutWatermark}" />
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="2" Content="OutputLayout" />
|
||||
<TextBox Grid.Row="0" Grid.Column="3" Text="{Binding OutputLayout}"
|
||||
Watermark="{Binding LayoutWatermark}" />
|
||||
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="InputType" />
|
||||
<views:EnumComboBox Grid.Row="1" Grid.Column="1"
|
||||
SelectedValue="{Binding InputTypeValue}" TypeName="nncase:InputType" />
|
||||
|
||||
<Label Grid.Row="1" Grid.Column="2" Content="InputShape" />
|
||||
<TextBox Grid.Row="1" Grid.Column="3" Text="{Binding InputShape}"
|
||||
Watermark="{Binding ShapeWaterMark}" />
|
||||
|
||||
<Label Grid.Row="2" Grid.Column="0" Content="InputRange" />
|
||||
<DockPanel Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3">
|
||||
<Label Content="Min" />
|
||||
<TextBox Text="{Binding RangeMin}" />
|
||||
<Label Content="Max" />
|
||||
<TextBox Text="{Binding RangeMax}" />
|
||||
</DockPanel>
|
||||
|
||||
<Label Grid.Row="3" Grid.Column="0" Content="Mean" />
|
||||
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Mean}"
|
||||
Watermark="{Binding ListNumberWaterMark}" />
|
||||
|
||||
<Label Grid.Row="3" Grid.Column="2" Content="Std" />
|
||||
<TextBox Grid.Row="3" Grid.Column="3" Text="{Binding Std}"
|
||||
Watermark="{Binding ListNumberWaterMark}" />
|
||||
|
||||
<Label Grid.Row="4" Grid.Column="0" Content="SwapRB" />
|
||||
<CheckBox Grid.Row="4" Grid.Column="1" IsChecked="{Binding SwapRB}" />
|
||||
|
||||
<Label Grid.Row="4" Grid.Column="2" Content="Model Layout" />
|
||||
<TextBox Grid.Row="4" Grid.Column="3" Text="{Binding ModelLayout}"
|
||||
Watermark="{Binding LayoutWatermark}" />
|
||||
|
||||
<Label Grid.Row="5" Grid.Column="0" Content="LetterBoxValue" />
|
||||
<TextBox Grid.Row="5" Grid.Column="1" Text="{Binding LetterBoxValue}" />
|
||||
<Button Grid.Row="5" Grid.Column="2" Content="显示前处理顺序" Command="{Binding ShowPreprocessOrderCommand}"></Button>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Nncase.Studio.Views;
|
||||
|
||||
public partial class PreprocessView : UserControl
|
||||
{
|
||||
public PreprocessView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Nncase.Studio.Views.PreprocessWindow"
|
||||
Title="PreprocessWindow"
|
||||
Width="350"
|
||||
Background="#f8f8f8">
|
||||
<ScrollViewer>
|
||||
<Image HorizontalAlignment="Center" Source="/Assets/preprocess.png" Width="284" Height="1805"></Image>
|
||||
</ScrollViewer>
|
||||
</Window>
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Nncase.Studio.Views;
|
||||
|
||||
public partial class PreprocessWindow : Window
|
||||
{
|
||||
public PreprocessWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<Window x:Class="Nncase.Studio.Views.PromptDialog"
|
||||
x:Name="Dialog"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="clr-namespace:Nncase.Studio.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="192" d:DesignHeight="108"
|
||||
x:DataType="viewModels:PromptDialogViewModel"
|
||||
MaxWidth="800"
|
||||
Width="{Binding WindowWidth}"
|
||||
Height="300"
|
||||
Icon="/Assets/nncase-logo.png"
|
||||
Title="{Binding Title}"
|
||||
FontSize="32">
|
||||
|
||||
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<Grid HorizontalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image
|
||||
Name="IconImage"
|
||||
IsVisible="{Binding IsError}"
|
||||
Width="64" Height="64" Source="/Assets/error-icon.png"></Image>
|
||||
<TextBlock Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="30"
|
||||
FontSize="27"
|
||||
Text="{Binding DialogContent}"
|
||||
></TextBlock>
|
||||
</Grid>
|
||||
|
||||
<Button Content="关闭"
|
||||
HorizontalAlignment="Center"
|
||||
IsCancel="True"
|
||||
Command="{Binding CloseWindowCommand, Mode=OneWay}"
|
||||
CommandParameter="{Binding $parent[Window]}"
|
||||
></Button>
|
||||
</StackPanel>
|
||||
</Window>
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Nncase.Studio.ViewModels;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Nncase.Studio.Views;
|
||||
|
||||
public partial class PromptDialog : ReactiveWindow<PromptDialogViewModel>
|
||||
{
|
||||
public PromptDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:qt="clr-namespace:Nncase.Quantization"
|
||||
xmlns:quantization="clr-namespace:Nncase.Quantization;assembly=Nncase.Core"
|
||||
xmlns:quantization1="clr-namespace:Nncase.Quantization;assembly=Nncase.Quantization"
|
||||
xmlns:views="clr-namespace:Nncase.Studio.Views"
|
||||
xmlns:viewModels="clr-namespace:Nncase.Studio.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Nncase.Studio.Views.QuantizeView"
|
||||
x:DataType="viewModels:QuantizeViewModel">
|
||||
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<StackPanel IsVisible="{Binding !MixQuantize}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="150"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Grid.Row="0" Grid.Column="0" Content="数据集"></Label>
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
Width="400"
|
||||
HorizontalAlignment="Left"
|
||||
Text="{Binding CalibDir}"
|
||||
Watermark="数据集所在的文件夹,仅支持npy格式的输入"></TextBox>
|
||||
<Button
|
||||
Grid.Row="0" Grid.Column="3"
|
||||
Content="选择"
|
||||
x:CompileBindings="False"
|
||||
Command="{Binding SelectCalibrationDataSetCommand}"></Button>
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="量化方法"></Label>
|
||||
<views:EnumComboBox Grid.Row="1" Grid.Column="1" TypeName="{x:Type quantization:CalibMethod}" SelectedValue="{Binding CalibMethodValue}"></views:EnumComboBox>
|
||||
|
||||
<Label Grid.Row="1" Grid.Column="2" Content="BindQuantMethod"></Label>
|
||||
<CheckBox Grid.Row="1" Grid.Column="3" IsChecked="{Binding QuantizeOptionsValue.BindQuantMethod}"></CheckBox>
|
||||
<Label Grid.Row="2" Grid.Column="0" Content="开启SQuant"></Label>
|
||||
<CheckBox Grid.Row="2" Grid.Column="1" IsChecked="{Binding QuantizeOptionsValue.UseSquant}"></CheckBox>
|
||||
<Label Grid.Row="2" Grid.Column="2" Content="开启AdaRound"></Label>
|
||||
<CheckBox Grid.Row="2" Grid.Column="3" IsChecked="{Binding QuantizeOptionsValue.UseAdaRound}"></CheckBox>
|
||||
|
||||
<Label Grid.Row="3" Grid.Column="0" Content="输入量化类型"></Label>
|
||||
<views:EnumComboBox Grid.Row="3" Grid.Column="1" TypeName="{x:Type quantization:QuantType}" SelectedValue="{Binding QuantTypeValue}"></views:EnumComboBox>
|
||||
<Label Grid.Row="3" Grid.Column="2" Content="Weights量化类型"></Label>
|
||||
<views:EnumComboBox Grid.Row="3" Grid.Column="3" TypeName="{x:Type quantization:QuantType}" SelectedValue="{Binding WQuantTypeValue}"></views:EnumComboBox>
|
||||
|
||||
<Label Grid.Row="4" Grid.Column="0" Content="模型量化模式"></Label>
|
||||
<ComboBox Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
ItemsSource="{Binding ModelQuantModeList}"
|
||||
SelectedItem="{Binding ModelQuantModeValue}">
|
||||
</ComboBox>
|
||||
|
||||
<Label Grid.Row="5" Grid.Column="0" Content="Dump量化损失"></Label>
|
||||
<CheckBox Grid.Row="5" Grid.Column="1" IsChecked="{Binding QuantizeOptionsValue.DumpQuantError}"></CheckBox>
|
||||
|
||||
<Label Grid.Row="5" Grid.Column="2" Content="Dump对称量化损失"></Label>
|
||||
<CheckBox Grid.Row="5" Grid.Column="3" IsChecked="{Binding QuantizeOptionsValue.DumpQuantErrorSymmetricForSigned}"></CheckBox>
|
||||
|
||||
<Label Grid.Row="6" Grid.Column="0" Content="导出量化配置"></Label>
|
||||
<CheckBox Grid.Row="6" Grid.Column="1" IsChecked="{Binding ExportQuantScheme}"></CheckBox>
|
||||
<Label Grid.Row="6" Grid.Column="2"
|
||||
Content="导出Weights范围"
|
||||
IsVisible="{Binding ExportQuantScheme}">
|
||||
</Label>
|
||||
<CheckBox Grid.Row="6" Grid.Column="3"
|
||||
IsVisible="{Binding ExportQuantScheme}"
|
||||
IsChecked="{Binding QuantizeOptionsValue.ExportWeightRangeByChannel}">
|
||||
</CheckBox>
|
||||
<Label Grid.Row="7" Grid.Column="0"
|
||||
IsVisible="{Binding ExportQuantScheme}"
|
||||
Content="设置导出路径">
|
||||
</Label>
|
||||
<TextBox Grid.Row="7" Grid.Column="1" Grid.ColumnSpan="3"
|
||||
Classes="Path"
|
||||
Width="400"
|
||||
IsVisible="{Binding ExportQuantScheme}"
|
||||
Text="{Binding ExportQuantSchemePath}">
|
||||
</TextBox>
|
||||
<TextBlock Grid.Row="7" Grid.Column="3" Text=" " Margin="22"></TextBlock>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel IsVisible="{Binding MixQuantize}">
|
||||
<Grid Row="2" Column="3">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Grid.Row="0" Grid.Column="0" Content="量化配置文件"></Label>
|
||||
<TextBox Grid.Row="0" Grid.Column="1" HorizontalAlignment="Left" Width="400" Watermark="Path" Text="{Binding QuantSchemePath}"></TextBox>
|
||||
<Button Grid.Row="0" Grid.Column="2"
|
||||
Content="选择"
|
||||
Command="{Binding SelectQuantSchemeCommand}"></Button>
|
||||
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="量化配置严格模式"></Label>
|
||||
<DockPanel Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2">
|
||||
<CheckBox
|
||||
IsChecked="{Binding QuantizeOptionsValue.QuantSchemeStrictMode}"></CheckBox>
|
||||
<Label
|
||||
Content="如果配置文件来自nncase则无需设置"></Label>
|
||||
</DockPanel>
|
||||
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
</StackPanel>
|
||||
</UserControl>
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Nncase.Studio.Views
|
||||
{
|
||||
public partial class QuantizeView : UserControl
|
||||
{
|
||||
public QuantizeView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="clr-namespace:Nncase.Studio.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Nncase.Studio.Views.ShapeBucketView"
|
||||
x:DataType="viewModels:ShapeBucketViewModel">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<Label Grid.Row="0" Grid.Column="0" Content="分段数量"></Label>
|
||||
<NumericUpDown Grid.Row="0" Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Value="{Binding SegmentCount}"
|
||||
FormatString="0"
|
||||
Minimum="2"
|
||||
Increment="1"></NumericUpDown>
|
||||
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="FixVarMap"></Label>
|
||||
<TextBox Grid.Row="1" Grid.Column="1" Width="600" Text="{Binding FixVarMap}" Watermark="example: batch:3, len:24"></TextBox>
|
||||
<Label Grid.Row="2" Grid.Column="0" Content="VarRangeInfo"></Label>
|
||||
<TextBox Grid.Row="2" Grid.Column="1" Width="600" Text="{Binding VarRangeInfo}" Watermark="example: len1:(1, 100); len2:(1, 40)"></TextBox>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Nncase.Studio.Views
|
||||
{
|
||||
public partial class ShapeBucketView : UserControl
|
||||
{
|
||||
public ShapeBucketView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Nncase.Studio.Views.SimulateInputView">
|
||||
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<DockPanel Margin="10" HorizontalAlignment="Center">
|
||||
<StackPanel Margin="10">
|
||||
<TextBlock Text="模型参数信息"></TextBlock>
|
||||
<ListBox
|
||||
x:CompileBindings="False"
|
||||
ItemsSource="{Binding $parent[Window].DataContext.MainParamStr}"></ListBox>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10">
|
||||
<TextBlock Text="输入信息"></TextBlock>
|
||||
<ListBox
|
||||
x:CompileBindings="False"
|
||||
ItemsSource="{Binding $parent[Window].DataContext.InputTypeStr}"></ListBox>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10">
|
||||
<TextBlock Text="输入路径"></TextBlock>
|
||||
<ListBox
|
||||
x:CompileBindings="False"
|
||||
ItemsSource="{Binding $parent[Window].DataContext.InputPath}"></ListBox>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
|
||||
<StackPanel Margin="10" HorizontalAlignment="Center">
|
||||
<StackPanel>
|
||||
<Button Content="设置输入"
|
||||
x:CompileBindings="False"
|
||||
HorizontalAlignment="Center"
|
||||
Command="{Binding $parent[Window].DataContext.SetRuntimeInput}">
|
||||
</Button>
|
||||
<Label Margin="10"
|
||||
HorizontalAlignment="Left"
|
||||
Content="目前支持的输入格式: *.npy"></Label>
|
||||
</StackPanel>
|
||||
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Nncase.Studio.Views
|
||||
{
|
||||
public partial class SimulateInputView : UserControl
|
||||
{
|
||||
public SimulateInputView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:views="clr-namespace:Nncase.Studio.Views"
|
||||
xmlns:viewModels="clr-namespace:Nncase.Studio.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Nncase.Studio.Views.SimulateView"
|
||||
x:DataType="viewModels:SimulateViewModel">
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<Grid HorizontalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Label Grid.Row="0" Grid.Column="0" Content="输入文件"></Label>
|
||||
<SplitButton Margin="5 0" Grid.Row="0" Grid.Column="1" Content="已选择的文件">
|
||||
<SplitButton.Flyout>
|
||||
<Flyout Placement="Bottom">
|
||||
<ListBox
|
||||
ItemsSource="{Binding InputPath}">
|
||||
</ListBox>
|
||||
</Flyout>
|
||||
</SplitButton.Flyout>
|
||||
</SplitButton>
|
||||
<!-- <ComboBox Grid.Row="0" Grid.Column="1" ItemsSource="{Binding InputPath}" ></ComboBox> -->
|
||||
<Button
|
||||
Grid.Row="0" Grid.Column="2"
|
||||
Content="选择"
|
||||
Command="{Binding SetRuntimeInputCommand}">
|
||||
</Button>
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="结果存储位置" VerticalAlignment="Center"></Label>
|
||||
<TextBox Classes="Path" Grid.Row="1" Grid.Column="1" Watermark="Result ResultDir" Text="{Binding ResultDir}"></TextBox>
|
||||
<Button
|
||||
Grid.Row="1" Grid.Column="2"
|
||||
Content="选择"
|
||||
Command="{Binding SetResultDirCommand}">
|
||||
</Button>
|
||||
|
||||
<Label Grid.Row="2" Grid.Column="0" Content="KmodelPath"></Label>
|
||||
<TextBox Classes="Path" Grid.Row="2" Grid.Column="1"
|
||||
Text="{Binding KmodelPath}"
|
||||
Watermark="Kmodel Path"></TextBox>
|
||||
<Button
|
||||
Grid.Row="2" Grid.Column="2"
|
||||
Content="选择"
|
||||
x:CompileBindings="False"
|
||||
Command="{Binding SetKmodelPathCommand}">
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
<DockPanel Margin="0 40" HorizontalAlignment="Center">
|
||||
<Button HorizontalAlignment="Center"
|
||||
Content="推理"
|
||||
Margin="40 0"
|
||||
Command="{Binding SimulateCommand}">
|
||||
</Button>
|
||||
|
||||
<Label Content="{Binding Status}" Width="120"></Label>
|
||||
</DockPanel>
|
||||
|
||||
<ProgressBar Margin="10" ShowProgressText="False" IsIndeterminate="{Binding RunSimulate}"/>
|
||||
</StackPanel>
|
||||
</UserControl>
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace Nncase.Studio.Views;
|
||||
|
||||
public partial class SimulateView : UserControl
|
||||
{
|
||||
public SimulateView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="clr-namespace:Nncase.Studio.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Nncase.Studio.Views.StudioModeView"
|
||||
x:DataType="viewModels:StudioModeViewModel">
|
||||
<StackPanel>
|
||||
<Button Width="300" Margin="30" FontSize="40" Content="常规编译" Command="{Binding SwitchToImportViewCommand}"></Button>
|
||||
<Button Width="300" Margin="30" FontSize="40" Content="直接推理" Command="{Binding SwitchToSimulateViewCommand}"></Button>
|
||||
<Button Width="300" Margin="30" FontSize="40" Content="导入配置" Command="{Binding ImportStudioConfigCommand}"></Button>
|
||||
</StackPanel>
|
||||
</UserControl>
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Canaan Inc. All rights reserved.
|
||||
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Nncase.Studio.Views
|
||||
{
|
||||
public partial class StudioModeView : UserControl
|
||||
{
|
||||
public StudioModeView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<!-- This manifest is used on Windows only.
|
||||
Don't remove it as it might cause problems with window transparency and embeded controls.
|
||||
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
|
||||
<assemblyIdentity version="1.0.0.0" name="Nncase.Studio.Desktop"/>
|
||||
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- A list of the Windows versions that this application has been tested on
|
||||
and is designed to work with. Uncomment the appropriate elements
|
||||
and Windows will automatically select the most compatible environment. -->
|
||||
|
||||
<!-- Windows 10 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
</application>
|
||||
</compatibility>
|
||||
</assembly>
|