diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 5c76368..e80a719 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -10,7 +10,7 @@ jobs: build: strategy: matrix: - target: ["win-x64", "linux-x64", "osx-x64", "osx-arm64"] + target: ["win-x64", "linux-x64"] runs-on: ubuntu-latest diff --git a/Extension.md b/Extension.md index 666062b..1626020 100644 --- a/Extension.md +++ b/Extension.md @@ -1,5 +1,8 @@ ![Icon](https://raw.githubusercontent.com/one-ware/OneWare.Quartus/main/Icon.png) -### Get Started +### Get Started with Quartus -> This text will be visible in the builtin package manager +1. Install this Extension +2. Download and Install [Quartus for Linux](https://download.altera.com/akdlm/software/acdsinst/18.1std/625/ib_installers/QuartusLiteSetup-18.1.0.625-linux.run) or for [Quartus for Windows](https://download.altera.com/akdlm/software/acdsinst/18.1std/625/ib_installers/QuartusLiteSetup-18.1.0.625-windows.exe) +3. Go to Settings -> Tools and set the correct installation path +4. Select Quartus as your toolchain in the compile drop-down menu or create a new project selecting quartus \ No newline at end of file diff --git a/oneware-extension.json b/oneware-extension.json index 3902eab..89000d1 100644 --- a/oneware-extension.json +++ b/oneware-extension.json @@ -33,14 +33,6 @@ { "target": "linux-x64", "url": "https://github.com/one-ware/OneWare.Quartus/releases/download/0.1/OneWare.QuartusExtension_0.1_linux-x64.zip" - }, - { - "target": "osx-x64", - "url": "https://github.com/one-ware/OneWare.Quartus/releases/download/0.1/OneWare.QuartusExtension_0.1_osx-x64.zip" - }, - { - "target": "osx-arm64", - "url": "https://github.com/one-ware/OneWare.Quartus/releases/download/0.1/OneWare.QuartusExtension_0.1_osx-arm64.zip" } ] } diff --git a/src/OneWare.Quartus/Assets/Quartus_prime.png b/src/OneWare.Quartus/Assets/Quartus_prime.png new file mode 100644 index 0000000..6e894d3 Binary files /dev/null and b/src/OneWare.Quartus/Assets/Quartus_prime.png differ diff --git a/src/OneWare.Quartus/Helper/QsfFile.cs b/src/OneWare.Quartus/Helper/QsfFile.cs new file mode 100644 index 0000000..770be71 --- /dev/null +++ b/src/OneWare.Quartus/Helper/QsfFile.cs @@ -0,0 +1,119 @@ +using System.Text.RegularExpressions; +using OneWare.Essentials.Extensions; +using OneWare.Essentials.Models; + +namespace OneWare.Quartus.Helper; + +public partial class QsfFile(string[] lines) +{ + [GeneratedRegex(@"set_location_assignment\s*PIN_(\w+)\s+-to\s+(\w+)")] + private static partial Regex LocationAssignmentRegex(); + + [GeneratedRegex(@"set_location_assignment\s")] + private static partial Regex RemoveLocationAssignmentRegex(); + + public List Lines { get; private set; } = lines.ToList(); + + public string? GetGlobalAssignment(string propertyName) + { + var regex = new Regex(@"set_global_assignment\s*-name\s" + propertyName + @"\s(.+)"); + foreach (var line in Lines) + { + var match = regex.Match(line); + if (match is { Success: true, Groups.Count: > 1 }) + { + var value = match.Groups[1].Value; + if(value.Length > 0 && value[0] == '"' && value[^1] == '"') return value[1..^1]; + return value; + } + } + return null; + } + + public void SetGlobalAssignment(string name, string value) + { + var regex = new Regex(@"set_global_assignment\s*-name\s*" + name); + var line= Lines.FindIndex(x => regex.IsMatch(x)); + var newAssignment = $"set_global_assignment -name {name} \"{value}\""; + + if(line != -1) + { + Lines[line] = newAssignment; + } + else + { + Lines.Add(newAssignment); + } + } + + public void RemoveGlobalAssignment(string name) + { + var regex = new Regex(@"set_global_assignment\s*-name\s*" + name); + Lines = Lines.Where(x => !regex.IsMatch(x)).ToList(); + } + + public IEnumerable<(string,string)> GetLocationAssignments() + { + foreach (var line in lines) + { + var match = LocationAssignmentRegex().Match(line); + if (!match.Success) continue; + + var pin = match.Groups[1].Value; + var node = match.Groups[2].Value; + + yield return (pin, node); + } + } + + public void AddLocationAssignment(string pin, string node) + { + Lines.Add($"set_location_assignment PIN_{pin} -to {node}"); + } + + public void RemoveLocationAssignments() + { + var regex = RemoveLocationAssignmentRegex(); + Lines = Lines.Where(x => !regex.IsMatch(x)).ToList(); + } + + public void AddFile(IProjectFile file) + { + switch (file.Extension) + { + case ".vhd" or ".vhdl": + Lines.Add($"set_global_assignment -name VHDL_FILE {file.RelativePath.ToLinuxPath()}"); + break; + case ".v": + Lines.Add($"set_global_assignment -name VERILOG_FILE {file.RelativePath.ToLinuxPath()}"); + break; + case ".sv": + Lines.Add($"set_global_assignment -name SYSTEMVERILOG_FILE {file.RelativePath.ToLinuxPath()}"); + break; + case ".qip": + Lines.Add($"set_global_assignment -name QIP_FILE {file.RelativePath.ToLinuxPath()}"); + break; + case ".qsys": + Lines.Add($"set_global_assignment -name QSYS_FILE {file.RelativePath.ToLinuxPath()}"); + break; + case ".bdf": + Lines.Add($"set_global_assignment -name BDF_FILE {file.RelativePath.ToLinuxPath()}"); + break; + case ".ahdl": + Lines.Add($"set_global_assignment -name AHDL_FILE {file.RelativePath.ToLinuxPath()}"); + break; + case ".smf": + Lines.Add($"set_global_assignment -name SMF_FILE {file.RelativePath.ToLinuxPath()}"); + break; + case ".tcl": + Lines.Add($"set_global_assignment -name TCL_SCRIPT_FILE {file.RelativePath.ToLinuxPath()}"); + break; + case ".hex": + Lines.Add($"set_global_assignment -name HEX_FILE {file.RelativePath.ToLinuxPath()}"); + break; + case ".mif": + Lines.Add($"set_global_assignment -name MIF_FILE {file.RelativePath.ToLinuxPath()}"); + break; + } + } +} \ No newline at end of file diff --git a/src/OneWare.Quartus/Helper/QsfHelper.cs b/src/OneWare.Quartus/Helper/QsfHelper.cs new file mode 100644 index 0000000..9c306be --- /dev/null +++ b/src/OneWare.Quartus/Helper/QsfHelper.cs @@ -0,0 +1,24 @@ +using System.Text.RegularExpressions; +using OneWare.UniversalFpgaProjectSystem.Models; + +namespace OneWare.Quartus.Helper; + +public static partial class QsfHelper +{ + public static string GetQsfPath(UniversalFpgaProjectRoot project) + { + return Path.Combine(project.RootFolderPath, Path.GetFileNameWithoutExtension(project.TopEntity?.FullPath ?? throw new Exception("TopEntity not set!")) + ".qsf"); + } + + public static QsfFile ReadQsf(string path) + { + var qsf = File.Exists(path) ? File.ReadAllText(path) : string.Empty; + + return new QsfFile(qsf.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)); + } + + public static void WriteQsf(string path, QsfFile file) + { + File.WriteAllLines(path, file.Lines); + } +} \ No newline at end of file diff --git a/src/OneWare.Quartus/OneWare.Quartus.csproj b/src/OneWare.Quartus/OneWare.Quartus.csproj index 0b0e635..2e1c278 100644 --- a/src/OneWare.Quartus/OneWare.Quartus.csproj +++ b/src/OneWare.Quartus/OneWare.Quartus.csproj @@ -16,12 +16,8 @@ - - - - - - + + diff --git a/src/OneWare.Quartus/QuartusLoader.cs b/src/OneWare.Quartus/QuartusLoader.cs index 410c2b3..664f684 100644 --- a/src/OneWare.Quartus/QuartusLoader.cs +++ b/src/OneWare.Quartus/QuartusLoader.cs @@ -30,8 +30,12 @@ public async Task DownloadAsync(UniversalFpgaProjectRoot project) var fpga = project.Properties["Fpga"]; if (fpga == null) return; var fpgaModel = fpga.ToString(); + + var cableSetting = "Auto"; + var cableName = cableSetting == "Auto" + ? "1" + : "\"" + cableSetting + "\""; - var cableName = "Auto"; var sofFile = Path.GetFileName(FirstFileInPath(project.FullPath, ".sof") ?? ""); if (string.IsNullOrEmpty(sofFile)) @@ -41,6 +45,6 @@ public async Task DownloadAsync(UniversalFpgaProjectRoot project) } await childProcessService.ExecuteShellAsync("quartus_pgm", $"-c {cableName} -m JTAG -o P;{sofFile}", - project.FullPath, "Running OpenFPGALoader"); + project.FullPath, "Running Quartus programmer (Short-Term)..."); } } \ No newline at end of file diff --git a/src/OneWare.Quartus/QuartusToolchain.cs b/src/OneWare.Quartus/QuartusToolchain.cs index 5ba38b3..73ab4b3 100644 --- a/src/OneWare.Quartus/QuartusToolchain.cs +++ b/src/OneWare.Quartus/QuartusToolchain.cs @@ -1,49 +1,29 @@ -using System.Text.RegularExpressions; -using DynamicData; -using OneWare.Essentials.Extensions; -using OneWare.Essentials.Services; +using OneWare.Essentials.Services; +using OneWare.Quartus.Helper; using OneWare.Quartus.Services; using OneWare.UniversalFpgaProjectSystem.Models; using OneWare.UniversalFpgaProjectSystem.Services; namespace OneWare.Quartus; -public partial class QuartusToolchain(QuartusService quartusService, ILogger logger) : IFpgaToolchain +public class QuartusToolchain(QuartusService quartusService, ILogger logger) : IFpgaToolchain { public string Name => "Quartus"; - - - [GeneratedRegex(@"set_location_assignment\s*PIN_(\w+)\s+-to\s+(\w+)")] - private static partial Regex AssignmentRegex(); - - [GeneratedRegex(@"(set_global_assignment\s*-name\s*((VHDL|VERILOG|SYSTEMVERILOG|QIP|QSYS|BDF|AHDL|SMF|TCL_SCRIPT|HEX|MIF)_FILE|FAMILY|DEVICE|TOP_LEVEL_ENTITY)|set_location_assignment)")] - private static partial Regex RemoveLinesFromQsfRegex(); public void LoadConnections(UniversalFpgaProjectRoot project, FpgaModel fpga) { try { - var files = Directory.GetFiles(project.RootFolderPath); - var qsfPath = files.FirstOrDefault(x => Path.GetExtension(x) == ".qsf"); - if (qsfPath != null) + var qsfPath = QsfHelper.GetQsfPath(project); + var qsf = QsfHelper.ReadQsf(qsfPath); + + foreach (var (pin, node) in qsf.GetLocationAssignments()) { - var pcf = File.ReadAllText(qsfPath); - var lines = pcf.Split('\n'); - foreach (var line in lines) - { - var regex = AssignmentRegex(); - - var match = regex.Match(line); - if (!match.Success) continue; - - var pin = match.Groups[1].Value; - var node = match.Groups[2].Value; - if(!fpga.PinModels.TryGetValue(pin, out var pinModel)) return; - if(!fpga.NodeModels.TryGetValue(node, out var nodeModel)) return; + if(!fpga.PinModels.TryGetValue(pin, out var pinModel)) return; + if(!fpga.NodeModels.TryGetValue(node, out var nodeModel)) return; - fpga.Connect(pinModel, nodeModel); - } + fpga.Connect(pinModel, nodeModel); } } catch (Exception e) @@ -58,73 +38,34 @@ public void SaveConnections(UniversalFpgaProjectRoot project, FpgaModel fpga) { var topEntity = project.TopEntity?.Header ?? throw new Exception("No TopEntity set!"); topEntity = Path.GetFileNameWithoutExtension(topEntity); - - var qsfPath = Path.Combine(project.RootFolderPath, topEntity + ".qsf"); - - var qsf = File.Exists(qsfPath) ? File.ReadAllText(qsfPath) : string.Empty; - - var lines = qsf.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) - .Where(x => !RemoveLinesFromQsfRegex().IsMatch(x)) - .ToList(); + + var qsfPath = QsfHelper.GetQsfPath(project); + var qsf = QsfHelper.ReadQsf(qsfPath); //Add Family - lines.Add($"set_global_assignment -name FAMILY \"{fpga.Fpga.Family}\""); + qsf.SetGlobalAssignment("FAMILY", fpga.Fpga.Family); //Add Device - lines.Add($"set_global_assignment -name DEVICE {fpga.Fpga.Model}"); + qsf.SetGlobalAssignment("DEVICE", fpga.Fpga.Model); //Add toplevel - lines.Add($"set_global_assignment -name TOP_LEVEL_ENTITY {topEntity}"); + qsf.SetGlobalAssignment("TOP_LEVEL_ENTITY", topEntity); //Add Files foreach (var file in project.Files) { - switch (file.Extension) - { - case ".vhd" or ".vhdl": - lines.Add($"set_global_assignment -name VHDL_FILE {file.RelativePath.ToLinuxPath()}"); - break; - case ".v": - lines.Add($"set_global_assignment -name VERILOG_FILE {file.RelativePath.ToLinuxPath()}"); - break; - case ".sv": - lines.Add($"set_global_assignment -name SYSTEMVERILOG_FILE {file.RelativePath.ToLinuxPath()}"); - break; - case ".qip": - lines.Add($"set_global_assignment -name QIP_FILE {file.RelativePath.ToLinuxPath()}"); - break; - case ".qsys": - lines.Add($"set_global_assignment -name QSYS_FILE {file.RelativePath.ToLinuxPath()}"); - break; - case ".bdf": - lines.Add($"set_global_assignment -name BDF_FILE {file.RelativePath.ToLinuxPath()}"); - break; - case ".ahdl": - lines.Add($"set_global_assignment -name AHDL_FILE {file.RelativePath.ToLinuxPath()}"); - break; - case ".smf": - lines.Add($"set_global_assignment -name SMF_FILE {file.RelativePath.ToLinuxPath()}"); - break; - case ".tcl": - lines.Add($"set_global_assignment -name TCL_SCRIPT_FILE {file.RelativePath.ToLinuxPath()}"); - break; - case ".hex": - lines.Add($"set_global_assignment -name HEX_FILE {file.RelativePath.ToLinuxPath()}"); - break; - case ".mif": - lines.Add($"set_global_assignment -name MIF_FILE {file.RelativePath.ToLinuxPath()}"); - break; - } + qsf.AddFile(file); } - foreach (var (key, pinModel) in fpga.PinModels) + qsf.RemoveLocationAssignments(); + foreach (var (_, pinModel) in fpga.PinModels) { if(pinModel.Connection == null) continue; - - lines.Add($"set_location_assignment PIN_{pinModel.Pin.Name} -to {pinModel.Connection.Node.Name}"); + + qsf.AddLocationAssignment(pinModel.Pin.Name, pinModel.Connection.Node.Name); } - File.WriteAllLines(qsfPath, lines); + QsfHelper.WriteQsf(qsfPath, qsf); } catch (Exception e) { @@ -134,6 +75,6 @@ public void SaveConnections(UniversalFpgaProjectRoot project, FpgaModel fpga) public void StartCompile(UniversalFpgaProjectRoot project, FpgaModel fpga) { - _ = quartusService.SynthAsync(project, fpga); + _ = quartusService.CompileAsync(project, fpga); } } \ No newline at end of file diff --git a/src/OneWare.Quartus/Services/QuartusService.cs b/src/OneWare.Quartus/Services/QuartusService.cs index aff8676..045940f 100644 --- a/src/OneWare.Quartus/Services/QuartusService.cs +++ b/src/OneWare.Quartus/Services/QuartusService.cs @@ -1,21 +1,40 @@ -using OneWare.Essentials.Models; +using Avalonia.Media; +using Avalonia.Threading; +using OneWare.Essentials.Enums; +using OneWare.Essentials.Models; using OneWare.Essentials.Services; using OneWare.UniversalFpgaProjectSystem.Models; namespace OneWare.Quartus.Services; -public class QuartusService(IChildProcessService childProcessService, ILogger logger) +public class QuartusService(IChildProcessService childProcessService, ILogger logger, IOutputService outputService) { - public async Task SynthAsync(UniversalFpgaProjectRoot project, FpgaModel fpga) + public async Task CompileAsync(UniversalFpgaProjectRoot project, FpgaModel fpga) { if (project.TopEntity == null) { logger.Error("No TopEntity set"); return; } + + var start = DateTime.Now; + outputService.WriteLine("Compiling...\n==================", Brushes.CornflowerBlue); await childProcessService.ExecuteShellAsync("quartus_sh", $"--flow compile {Path.GetFileNameWithoutExtension(project.TopEntity.Header)}", - project.FullPath, "Starting Quartus Prime Shell..."); + project.FullPath, "Running Quartus Prime Shell...", AppState.Loading, true, (x) => + { + var output = x.TrimStart(); + Dispatcher.UIThread.Post(() => + { + if(output.StartsWith("Error (")) outputService.WriteLine(x, Brushes.Red); + else if(output.StartsWith("Warning (") || output.StartsWith("Critical Warning (")) outputService.WriteLine(x, Brushes.Orange); + else outputService.WriteLine(x); + }); + }); + + var compileTime = DateTime.Now - start; + + outputService.WriteLine($"==================\n\nCompilation finished after {(int)compileTime.TotalMinutes:D2}:{compileTime.Seconds:D2}\n"); } } \ No newline at end of file diff --git a/src/OneWare.Quartus/ViewModels/QuartusCompileSettingsViewModel.cs b/src/OneWare.Quartus/ViewModels/QuartusCompileSettingsViewModel.cs new file mode 100644 index 0000000..c5d8a2a --- /dev/null +++ b/src/OneWare.Quartus/ViewModels/QuartusCompileSettingsViewModel.cs @@ -0,0 +1,88 @@ +using OneWare.Essentials.Controls; +using OneWare.Essentials.ViewModels; +using OneWare.ProjectSystem.Models; +using OneWare.Quartus.Helper; +using OneWare.Settings; +using OneWare.Settings.ViewModels; +using OneWare.Settings.ViewModels.SettingTypes; +using OneWare.UniversalFpgaProjectSystem.Models; + +namespace OneWare.Quartus.ViewModels; + +public class QuartusCompileSettingsViewModel : FlexibleWindowViewModelBase +{ + private string _qsfPath; + private QsfFile _qsfFile; + + public SettingsCollectionViewModel SettingsCollection { get; } = new("Quartus Settings") + { + ShowTitle = false + }; + + private ComboBoxSetting _processorCountSetting; + private ComboBoxSetting _configurationModeSetting; + private ComboBoxSetting _optimizationModeSetting; + + private Dictionary AvailableConfigurationModes { get; } = new() + { + { "DEFAULT", "Default" }, + { "DUAL IMAGES", "Dual Compressed Images (256Kbits UFM)" }, + { "SINGLE COMP IMAGE", "Single Compressed Image (1376Kbits UFM)" }, + { "SINGLE COMP IMAGE WITH ERAM", "Single Compressed Image with Memory Initialization (256Kbits UFM)" }, + { "SINGLE IMAGE", "Single Uncompressed Image (912Kbits UFM)" }, + { "SINGLE IMAGE WITH ERAM", "Single Uncompressed Image with Memory Initialization (256Kbits UFM)" } + }; + + private Dictionary AvailableOptimizationModes { get; } = new() + { + { "BALANCED", "Balanced" }, + { "HIGH PERFORMANCE EFFORT", "Performance (High effort - increases runtime)" }, + { "AGGRESSIVE PERFORMANCE", "Performance (Aggressive - increases runtime and area)" }, + { "HIGH POWER EFFORT", "Power (High effort - increases runtime)" }, + { "AGGRESSIVE POWER", "Power (Aggressive - increases runtime, reduces performance)" }, + { "AGGRESSIVE AREA", "Area (Aggressive - reduces performance)" } + }; + + + public QuartusCompileSettingsViewModel(UniversalFpgaProjectRoot fpgaProjectRoot) + { + Title = "Quartus Compile Settings"; + Id = "QuartusCompileSettings"; + + _qsfPath = QsfHelper.GetQsfPath(fpgaProjectRoot); + _qsfFile = QsfHelper.ReadQsf(_qsfPath); + + _processorCountSetting = new ComboBoxSetting("Parallel Compilation Processors", + "Max processors Quartus will use to compile", + Environment.ProcessorCount, Enumerable.Range(1, Environment.ProcessorCount).Cast()); + + _configurationModeSetting = new ComboBoxSetting("Configuration Mode", "Quartus Configuration Mode", + AvailableConfigurationModes["DEFAULT"], AvailableConfigurationModes.Values); + + _optimizationModeSetting = new ComboBoxSetting("Optimization Mode", "Quartus Optimization Mode", + AvailableOptimizationModes["BALANCED"], AvailableOptimizationModes.Values); + + SettingsCollection.SettingModels.Add(new ComboBoxSettingViewModel(_processorCountSetting)); + SettingsCollection.SettingModels.Add(new ComboBoxSettingViewModel(_configurationModeSetting)); + SettingsCollection.SettingModels.Add(new ComboBoxSettingViewModel(_optimizationModeSetting)); + + var processorCount = _qsfFile.GetGlobalAssignment("NUM_PARALLEL_PROCESSORS"); + if(!string.IsNullOrWhiteSpace(processorCount) && int.TryParse(processorCount, out var processorCountInt)) _processorCountSetting.Value = processorCountInt; + + var configurationMode = _qsfFile.GetGlobalAssignment("INTERNAL_FLASH_UPDATE_MODE"); + if(!string.IsNullOrWhiteSpace(configurationMode)) _configurationModeSetting.Value = configurationMode; + + var optimizationMode = _qsfFile.GetGlobalAssignment("OPTIMIZATION_MODE"); + if(!string.IsNullOrWhiteSpace(optimizationMode)) _optimizationModeSetting.Value = optimizationMode; + } + + public void Save(FlexibleWindow flexibleWindow) + { + _qsfFile.SetGlobalAssignment("NUM_PARALLEL_PROCESSORS", _processorCountSetting.Value.ToString()!); + _qsfFile.SetGlobalAssignment("INTERNAL_FLASH_UPDATE_MODE", _configurationModeSetting.Value.ToString()!); + _qsfFile.SetGlobalAssignment("OPTIMIZATION_MODE", _optimizationModeSetting.Value.ToString()!); + + QsfHelper.WriteQsf(_qsfPath, _qsfFile); + Close(flexibleWindow); + } +} \ No newline at end of file diff --git a/src/OneWare.Quartus/ViewModels/QuartusCompileWindowExtensionViewModel.cs b/src/OneWare.Quartus/ViewModels/QuartusCompileWindowExtensionViewModel.cs index 8e0adda..f544aa7 100644 --- a/src/OneWare.Quartus/ViewModels/QuartusCompileWindowExtensionViewModel.cs +++ b/src/OneWare.Quartus/ViewModels/QuartusCompileWindowExtensionViewModel.cs @@ -1,12 +1,18 @@ -using CommunityToolkit.Mvvm.ComponentModel; +using Avalonia.Threading; +using CommunityToolkit.Mvvm.ComponentModel; using DynamicData.Binding; using OneWare.Essentials.Services; +using OneWare.Quartus.Views; using OneWare.UniversalFpgaProjectSystem.Models; +using Prism.Ioc; namespace OneWare.Quartus.ViewModels; public class QuartusCompileWindowExtensionViewModel : ObservableObject { + private readonly IWindowService _windowService; + private readonly IProjectExplorerService _projectExplorerService; + private bool _isVisible = false; public bool IsVisible @@ -15,8 +21,11 @@ public bool IsVisible set => SetProperty(ref _isVisible, value); } - public QuartusCompileWindowExtensionViewModel(IProjectExplorerService projectExplorerService) + public QuartusCompileWindowExtensionViewModel(IProjectExplorerService projectExplorerService, IWindowService windowService) { + _windowService = windowService; + _projectExplorerService = projectExplorerService; + IDisposable? disposable = null; projectExplorerService.WhenValueChanged(x => x.ActiveProject).Subscribe(x => { @@ -28,4 +37,23 @@ public QuartusCompileWindowExtensionViewModel(IProjectExplorerService projectExp }); }); } + + public async Task OpenCompileSettingsAsync() + { + await Dispatcher.UIThread.InvokeAsync(async () => + { + try + { + if (_projectExplorerService.ActiveProject is UniversalFpgaProjectRoot fpgaProjectRoot) + { + await _windowService.ShowDialogAsync(new QuartusCompileSettingsView() + { DataContext = new QuartusCompileSettingsViewModel(fpgaProjectRoot) }); + } + } + catch (Exception e) + { + ContainerLocator.Container.Resolve().Error(e.Message, e); + } + }); + } } \ No newline at end of file diff --git a/src/OneWare.Quartus/Views/QuartusCompileSettingsView.axaml b/src/OneWare.Quartus/Views/QuartusCompileSettingsView.axaml new file mode 100644 index 0000000..a65242d --- /dev/null +++ b/src/OneWare.Quartus/Views/QuartusCompileSettingsView.axaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + diff --git a/src/OneWare.Quartus/Views/QuartusCompileSettingsView.axaml.cs b/src/OneWare.Quartus/Views/QuartusCompileSettingsView.axaml.cs new file mode 100644 index 0000000..4fdeded --- /dev/null +++ b/src/OneWare.Quartus/Views/QuartusCompileSettingsView.axaml.cs @@ -0,0 +1,14 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using OneWare.Essentials.Controls; + +namespace OneWare.Quartus.Views; + +public partial class QuartusCompileSettingsView : FlexibleWindow +{ + public QuartusCompileSettingsView() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/src/OneWare.Quartus/Views/QuartusCompileWindowExtensionView.axaml b/src/OneWare.Quartus/Views/QuartusCompileWindowExtensionView.axaml index 87b68fb..5fda7b3 100644 --- a/src/OneWare.Quartus/Views/QuartusCompileWindowExtensionView.axaml +++ b/src/OneWare.Quartus/Views/QuartusCompileWindowExtensionView.axaml @@ -7,7 +7,15 @@ x:Class="OneWare.Quartus.Views.QuartusCompileWindowExtensionView" x:DataType="viewModels:QuartusCompileWindowExtensionViewModel" IsVisible="{Binding IsVisible}"> - - - - + + + + + + \ No newline at end of file diff --git a/src/OneWare.Quartus/oneware.json b/src/OneWare.Quartus/oneware.json index 8d2f251..d6bc0b2 100644 --- a/src/OneWare.Quartus/oneware.json +++ b/src/OneWare.Quartus/oneware.json @@ -2,13 +2,13 @@ "Dependencies": [ { "Name": "OneWare.Essentials", - "MinVersion": "0.2.0.0", - "MaxVersion": "0.2.0.0" + "MinVersion": "0.3.0.0", + "MaxVersion": "0.3.0.0" }, { "Name": "OneWare.UniversalFpgaProjectSystem", - "MinVersion": "0.15.0.0", - "MaxVersion": "0.15.0.0" + "MinVersion": "0.15.1.0", + "MaxVersion": "0.15.1.0" } ] } \ No newline at end of file