From 6ff05da1487146f6be52acd6f2c53e8bf2e5937b Mon Sep 17 00:00:00 2001 From: Hendrik Mennen Date: Thu, 1 Aug 2024 20:55:50 +0200 Subject: [PATCH] searchcombobox improvements + load fpgas from documents directory --- OneWare.sln | 7 + src/OneWare.Cyc5000/Cyc5000Fpga.cs | 2 +- .../Controls/SearchComboBox.axaml | 10 + .../Controls/SearchComboBox.axaml.cs | 107 +- .../Controls/SearchComboBoxItem.cs | 20 + src/OneWare.IceBreaker/IceBreakerFpga.cs | 2 +- src/OneWare.Max10/Max10Fpga.cs | 2 +- src/OneWare.Max1000/Max1000Fpga.cs | 2 +- src/OneWare.TangNano9K/TangNano9kFpga.cs | 2 +- .../Fpga/FpgaBase.cs | 18 +- .../Fpga/FpgaLoader.cs | 9 + .../Fpga/GenericFpga.cs | 9 + .../Models/FpgaModel.cs | 5 + .../Services/FpgaService.cs | 41 + .../UniversalFpgaProjectCompileViewModel.cs | 30 +- .../UniversalFpgaProjectCompileView.axaml | 9 +- .../Assets/Cyc5000/fpga.json | 964 ++++++++++++++++++ .../LoadFpgaTests.cs | 17 + ...re.UniversalFpgaProjectSystem.Tests.csproj | 26 + 19 files changed, 1253 insertions(+), 29 deletions(-) create mode 100644 src/OneWare.Essentials/Controls/SearchComboBoxItem.cs create mode 100644 src/OneWare.UniversalFpgaProjectSystem/Fpga/FpgaLoader.cs create mode 100644 src/OneWare.UniversalFpgaProjectSystem/Fpga/GenericFpga.cs create mode 100644 tests/OneWare.UniversalFpgaProjectSystem.Tests/Assets/Cyc5000/fpga.json create mode 100644 tests/OneWare.UniversalFpgaProjectSystem.Tests/LoadFpgaTests.cs create mode 100644 tests/OneWare.UniversalFpgaProjectSystem.Tests/OneWare.UniversalFpgaProjectSystem.Tests.csproj diff --git a/OneWare.sln b/OneWare.sln index f74fba21..c5c74c16 100644 --- a/OneWare.sln +++ b/OneWare.sln @@ -176,6 +176,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OneWare.Vhdl.UnitTests", "t EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OneWare.WaveFormViewer.Tests", "tests\OneWare.WaveFormViewer.Tests\OneWare.WaveFormViewer.Tests.csproj", "{AAC4D6FA-4F94-4616-93B3-3BB47E4A0BB1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OneWare.UniversalFpgaProjectSystem.Tests", "tests\OneWare.UniversalFpgaProjectSystem.Tests\OneWare.UniversalFpgaProjectSystem.Tests.csproj", "{484F3E48-EF14-4801-B896-41BDB67A54E6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -378,6 +380,10 @@ Global {AAC4D6FA-4F94-4616-93B3-3BB47E4A0BB1}.Debug|Any CPU.Build.0 = Debug|Any CPU {AAC4D6FA-4F94-4616-93B3-3BB47E4A0BB1}.Release|Any CPU.ActiveCfg = Release|Any CPU {AAC4D6FA-4F94-4616-93B3-3BB47E4A0BB1}.Release|Any CPU.Build.0 = Release|Any CPU + {484F3E48-EF14-4801-B896-41BDB67A54E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {484F3E48-EF14-4801-B896-41BDB67A54E6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {484F3E48-EF14-4801-B896-41BDB67A54E6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {484F3E48-EF14-4801-B896-41BDB67A54E6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {F08B36E8-AB80-42CD-BD47-6B05E96DA390} = {0761690C-7DA0-4554-9F6B-211088412DCD} @@ -437,5 +443,6 @@ Global {3174F07C-F96E-4695-B05D-CE91845CF292} = {EB783E04-C3C8-45F8-B810-24798DAE2450} {8EF6E36F-C63A-4F2A-99CF-8F3AE2A5C946} = {EB783E04-C3C8-45F8-B810-24798DAE2450} {AAC4D6FA-4F94-4616-93B3-3BB47E4A0BB1} = {EB783E04-C3C8-45F8-B810-24798DAE2450} + {484F3E48-EF14-4801-B896-41BDB67A54E6} = {EB783E04-C3C8-45F8-B810-24798DAE2450} EndGlobalSection EndGlobal diff --git a/src/OneWare.Cyc5000/Cyc5000Fpga.cs b/src/OneWare.Cyc5000/Cyc5000Fpga.cs index 58c62119..fb6f76bf 100644 --- a/src/OneWare.Cyc5000/Cyc5000Fpga.cs +++ b/src/OneWare.Cyc5000/Cyc5000Fpga.cs @@ -6,6 +6,6 @@ public class Cyc5000Fpga : FpgaBase { public Cyc5000Fpga() { - LoadFromJson("avares://OneWare.Cyc5000/Assets/Cyc5000.json"); + LoadFromJsonAsset("avares://OneWare.Cyc5000/Assets/Cyc5000.json"); } } \ No newline at end of file diff --git a/src/OneWare.Essentials/Controls/SearchComboBox.axaml b/src/OneWare.Essentials/Controls/SearchComboBox.axaml index 4ac1a9e0..88d3a1ee 100644 --- a/src/OneWare.Essentials/Controls/SearchComboBox.axaml +++ b/src/OneWare.Essentials/Controls/SearchComboBox.axaml @@ -86,4 +86,14 @@ + + + + \ No newline at end of file diff --git a/src/OneWare.Essentials/Controls/SearchComboBox.axaml.cs b/src/OneWare.Essentials/Controls/SearchComboBox.axaml.cs index 8dfff4f8..a72690a5 100644 --- a/src/OneWare.Essentials/Controls/SearchComboBox.axaml.cs +++ b/src/OneWare.Essentials/Controls/SearchComboBox.axaml.cs @@ -10,6 +10,50 @@ public class SearchComboBox : ComboBox { private TextBox? _searchBox; + public static readonly StyledProperty IsInteractiveProperty = + AvaloniaProperty.Register(nameof(IsInteractive), true); + + public bool IsInteractive + { + get => GetValue(IsInteractiveProperty); + set => SetValue(IsInteractiveProperty, value); + } + + protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey) + { + return new SearchComboBoxItem(); + } + + private int _resultIndex = -1; + + public int ResultIndex + { + get => _resultIndex; + set + { + _resultIndex = value; + ResultItem = ContainerFromIndex(value) as SearchComboBoxItem; + ScrollIntoView(value); + } + } + + private SearchComboBoxItem? _resultItem; + + public SearchComboBoxItem? ResultItem + { + get => _resultItem; + private set + { + if(_resultItem != null) _resultItem.IsSearchResult = false; + _resultItem = value; + + if (_resultItem != null) + { + _resultItem.IsSearchResult = true; + } + } + } + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); @@ -18,39 +62,82 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) _searchBox!.TextChanged += (sender, args) => { - SelectedItem = Items.FirstOrDefault(x => - x?.ToString()?.StartsWith(_searchBox.Text ?? string.Empty, StringComparison.OrdinalIgnoreCase) ?? false); + var item = Items.FirstOrDefault(x => + x?.ToString()?.StartsWith(_searchBox.Text ?? string.Empty, StringComparison.OrdinalIgnoreCase) + ?? x?.ToString()?.Contains(_searchBox.Text ?? string.Empty, StringComparison.OrdinalIgnoreCase) + ?? false); + + if (IsInteractive) + { + SelectedItem = item; + } + else + { + if (item != null) + { + ResultIndex = Items.IndexOf(item); + } + } _searchBox.Focus(); }; this.DropDownOpened += (sender, args) => { + _searchBox.Text = string.Empty; _searchBox.Focus(); }; } - + protected override void OnKeyDown(KeyEventArgs e) { + if(_searchBox == null) return; + if (e.Key == Key.Down) { - if (SelectedIndex < Items.Count - 1) - SelectedIndex++; + if (IsInteractive) + { + if (SelectedIndex < Items.Count - 1) + SelectedIndex++; + } + else + { + if (ResultIndex < Items.Count - 1) + ResultIndex++; + } + e.Handled = true; - _searchBox?.Focus(); + _searchBox.Focus(); return; } if (e.Key == Key.Up) { - if (SelectedIndex > 0) - SelectedIndex--; + if (IsInteractive) + { + if (SelectedIndex > 0) + SelectedIndex--; + } + else + { + if (ResultIndex > 0) + ResultIndex--; + } + e.Handled = true; - _searchBox?.Focus(); + _searchBox.Focus(); + return; + } + if (e.Key == Key.Enter && !IsInteractive) + { + SelectedIndex = ResultIndex; + _searchBox.Text = string.Empty; + } + if (e.Key == Key.Space && _searchBox.IsFocused) + { return; } - base.OnKeyDown(e); } } \ No newline at end of file diff --git a/src/OneWare.Essentials/Controls/SearchComboBoxItem.cs b/src/OneWare.Essentials/Controls/SearchComboBoxItem.cs new file mode 100644 index 00000000..87df3ed9 --- /dev/null +++ b/src/OneWare.Essentials/Controls/SearchComboBoxItem.cs @@ -0,0 +1,20 @@ +using Avalonia.Controls; + +namespace OneWare.Essentials.Controls; + +public class SearchComboBoxItem : ComboBoxItem +{ + protected override Type StyleKeyOverride => typeof(ComboBoxItem); + + private bool _isSearchResult; + + public bool IsSearchResult + { + get => _isSearchResult; + set + { + _isSearchResult = value; + ((IPseudoClasses)Classes).Set(":searchResult", value); + } + } +} \ No newline at end of file diff --git a/src/OneWare.IceBreaker/IceBreakerFpga.cs b/src/OneWare.IceBreaker/IceBreakerFpga.cs index ff7ab832..ba28768e 100644 --- a/src/OneWare.IceBreaker/IceBreakerFpga.cs +++ b/src/OneWare.IceBreaker/IceBreakerFpga.cs @@ -6,6 +6,6 @@ public class IceBreakerFpga : FpgaBase { public IceBreakerFpga() { - LoadFromJson("avares://OneWare.IceBreaker/Assets/IceBreakerV1.0e.json"); + LoadFromJsonAsset("avares://OneWare.IceBreaker/Assets/IceBreakerV1.0e.json"); } } \ No newline at end of file diff --git a/src/OneWare.Max10/Max10Fpga.cs b/src/OneWare.Max10/Max10Fpga.cs index 9b3c58ee..cd4d38c6 100644 --- a/src/OneWare.Max10/Max10Fpga.cs +++ b/src/OneWare.Max10/Max10Fpga.cs @@ -6,6 +6,6 @@ public class Max10Fpga : FpgaBase { public Max10Fpga() { - LoadFromJson("avares://OneWare.Max10/Assets/Max10.json"); + LoadFromJsonAsset("avares://OneWare.Max10/Assets/Max10.json"); } } \ No newline at end of file diff --git a/src/OneWare.Max1000/Max1000Fpga.cs b/src/OneWare.Max1000/Max1000Fpga.cs index 04370049..3ceca87d 100644 --- a/src/OneWare.Max1000/Max1000Fpga.cs +++ b/src/OneWare.Max1000/Max1000Fpga.cs @@ -6,6 +6,6 @@ public class Max1000Fpga : FpgaBase { public Max1000Fpga() { - LoadFromJson("avares://OneWare.Max1000/Assets/Max1000.json"); + LoadFromJsonAsset("avares://OneWare.Max1000/Assets/Max1000.json"); } } \ No newline at end of file diff --git a/src/OneWare.TangNano9K/TangNano9kFpga.cs b/src/OneWare.TangNano9K/TangNano9kFpga.cs index 0a68785d..58844b47 100644 --- a/src/OneWare.TangNano9K/TangNano9kFpga.cs +++ b/src/OneWare.TangNano9K/TangNano9kFpga.cs @@ -6,6 +6,6 @@ public class TangNano9KFpga : FpgaBase { public TangNano9KFpga() { - LoadFromJson("avares://OneWare.TangNano9K/Assets/TangNano9K.json"); + LoadFromJsonAsset("avares://OneWare.TangNano9K/Assets/TangNano9K.json"); } } \ No newline at end of file diff --git a/src/OneWare.UniversalFpgaProjectSystem/Fpga/FpgaBase.cs b/src/OneWare.UniversalFpgaProjectSystem/Fpga/FpgaBase.cs index 211e97de..f66428b8 100644 --- a/src/OneWare.UniversalFpgaProjectSystem/Fpga/FpgaBase.cs +++ b/src/OneWare.UniversalFpgaProjectSystem/Fpga/FpgaBase.cs @@ -22,11 +22,23 @@ protected FpgaBase(Dictionary? properties = null) public IReadOnlyDictionary Properties { get; } - protected void LoadFromJson(string path) + protected void LoadFromJsonAsset(string path) { - var stream = AssetLoader.Open(new Uri(path)); + using var stream = AssetLoader.Open(new Uri(path)); + using var reader = new StreamReader(stream); + LoadFromJson(reader.ReadToEnd()); + } + + protected void LoadFromJsonFile(string path) + { + using var stream = File.OpenRead(path); + using var reader = new StreamReader(stream); + LoadFromJson(reader.ReadToEnd()); + } - var properties = JsonNode.Parse(stream); + private void LoadFromJson(string json) + { + var properties = JsonNode.Parse(json); if (properties == null) return; diff --git a/src/OneWare.UniversalFpgaProjectSystem/Fpga/FpgaLoader.cs b/src/OneWare.UniversalFpgaProjectSystem/Fpga/FpgaLoader.cs new file mode 100644 index 00000000..08efb8e3 --- /dev/null +++ b/src/OneWare.UniversalFpgaProjectSystem/Fpga/FpgaLoader.cs @@ -0,0 +1,9 @@ +namespace OneWare.UniversalFpgaProjectSystem.Fpga; + +public static class FpgaLoader +{ + public static IFpga LoadFromPath(string path) + { + return new GenericFpga(path); + } +} \ No newline at end of file diff --git a/src/OneWare.UniversalFpgaProjectSystem/Fpga/GenericFpga.cs b/src/OneWare.UniversalFpgaProjectSystem/Fpga/GenericFpga.cs new file mode 100644 index 00000000..9cfb91b0 --- /dev/null +++ b/src/OneWare.UniversalFpgaProjectSystem/Fpga/GenericFpga.cs @@ -0,0 +1,9 @@ +namespace OneWare.UniversalFpgaProjectSystem.Fpga; + +public class GenericFpga : FpgaBase +{ + public GenericFpga(string jsonPath) + { + LoadFromJsonFile(jsonPath); + } +} \ No newline at end of file diff --git a/src/OneWare.UniversalFpgaProjectSystem/Models/FpgaModel.cs b/src/OneWare.UniversalFpgaProjectSystem/Models/FpgaModel.cs index 681c120c..1a76e7d8 100644 --- a/src/OneWare.UniversalFpgaProjectSystem/Models/FpgaModel.cs +++ b/src/OneWare.UniversalFpgaProjectSystem/Models/FpgaModel.cs @@ -187,4 +187,9 @@ private void AddInterface(FpgaInterface fpgaInterface) var model = new FpgaInterfaceModel(fpgaInterface, this); InterfaceModels.Add(fpgaInterface.Name, model); } + + public override string ToString() + { + return Fpga.Name; + } } \ No newline at end of file diff --git a/src/OneWare.UniversalFpgaProjectSystem/Services/FpgaService.cs b/src/OneWare.UniversalFpgaProjectSystem/Services/FpgaService.cs index a22f3daa..30f2f1ee 100644 --- a/src/OneWare.UniversalFpgaProjectSystem/Services/FpgaService.cs +++ b/src/OneWare.UniversalFpgaProjectSystem/Services/FpgaService.cs @@ -1,5 +1,6 @@ using System.Collections.ObjectModel; using OneWare.Essentials.Extensions; +using OneWare.Essentials.Services; using OneWare.UniversalFpgaProjectSystem.Fpga; using OneWare.UniversalFpgaProjectSystem.Models; using Prism.Ioc; @@ -8,6 +9,17 @@ namespace OneWare.UniversalFpgaProjectSystem.Services; public class FpgaService { + private readonly ILogger _logger; + public FpgaService(IPaths paths, ILogger logger) + { + FpgaDirectory = Path.Combine(paths.DocumentsDirectory, "Hardware", "FPGA"); + Directory.CreateDirectory(FpgaDirectory); + + _logger = logger; + } + + public string FpgaDirectory { get; } + public Dictionary CustomFpgaViewModels { get; } = new(); public Dictionary FpgaExtensionViewModels { get; } = new(); @@ -89,4 +101,33 @@ public void RegisterPreCompileStep() where T : IFpgaPreCompileStep if (provider != null) return ContainerLocator.Container.Resolve(provider) as INodeProvider; return null; } + + public void LoadGenericFpgas() + { + foreach (var fpga in Fpgas.ToArray()) + { + if (fpga is GenericFpga) + { + Fpgas.Remove(fpga); + CustomFpgaViewModels.Remove(fpga); + } + } + + try + { + foreach (var directory in Directory.GetDirectories(FpgaDirectory)) + { + var fpgaFile = Path.Combine(directory, "fpga.json"); + if (File.Exists(fpgaFile)) + { + var fpga = FpgaLoader.LoadFromPath(fpgaFile); + RegisterFpga(fpga); + } + } + } + catch (Exception e) + { + _logger.Error(e.Message, e); + } + } } \ No newline at end of file diff --git a/src/OneWare.UniversalFpgaProjectSystem/ViewModels/UniversalFpgaProjectCompileViewModel.cs b/src/OneWare.UniversalFpgaProjectSystem/ViewModels/UniversalFpgaProjectCompileViewModel.cs index af2a4ce4..5f5ff6f6 100644 --- a/src/OneWare.UniversalFpgaProjectSystem/ViewModels/UniversalFpgaProjectCompileViewModel.cs +++ b/src/OneWare.UniversalFpgaProjectSystem/ViewModels/UniversalFpgaProjectCompileViewModel.cs @@ -1,9 +1,11 @@ using System.Collections.ObjectModel; using System.Reactive.Disposables; using System.Reactive.Linq; +using Avalonia.Input; using DynamicData.Binding; using OneWare.Essentials.Controls; using OneWare.Essentials.Enums; +using OneWare.Essentials.Helpers; using OneWare.Essentials.Models; using OneWare.Essentials.Services; using OneWare.Essentials.ViewModels; @@ -37,6 +39,9 @@ public UniversalFpgaProjectCompileViewModel(IWindowService windowService, { Title = $"Connect and Compile - {Project.Header}{(x ? "*" : "")}"; }); + + //Load Fpgas from documents + fpgaService.LoadGenericFpgas(); //Construct FpgaModels foreach (var fpga in fpgaService.Fpgas) @@ -66,6 +71,8 @@ public UniversalFpgaProjectCompileViewModel(IWindowService windowService, IsDirty = false; } + public static KeyGesture SaveGesture => new(Key.S, PlatformHelper.ControlKey); + public ObservableCollection TopRightExtension { get; } public UniversalFpgaProjectRoot Project { get; } @@ -126,13 +133,7 @@ private async Task SafeQuitAsync(FlexibleWindow window) } } - public void SaveAndCompile(FlexibleWindow window) - { - SaveAndClose(window); - if (SelectedFpgaModel != null) _ = Project.RunToolchainAsync(SelectedFpgaModel); - } - - public void SaveAndClose(FlexibleWindow window) + public void Save() { if (SelectedFpgaModel != null) { @@ -140,9 +141,20 @@ public void SaveAndClose(FlexibleWindow window) Project.SetProjectProperty("Fpga", SelectedFpgaModel.Fpga.Name); Project.Toolchain?.SaveConnections(Project, SelectedFpgaModel); _ = _projectExplorerService.SaveProjectAsync(Project); + + IsDirty = false; } - - IsDirty = false; + } + + public void SaveAndClose(FlexibleWindow window) + { + Save(); window.Close(); } + + public void SaveAndCompile(FlexibleWindow window) + { + SaveAndClose(window); + if (SelectedFpgaModel != null) _ = Project.RunToolchainAsync(SelectedFpgaModel); + } } \ No newline at end of file diff --git a/src/OneWare.UniversalFpgaProjectSystem/Views/UniversalFpgaProjectCompileView.axaml b/src/OneWare.UniversalFpgaProjectSystem/Views/UniversalFpgaProjectCompileView.axaml index bbc4ebcb..4fd04c13 100644 --- a/src/OneWare.UniversalFpgaProjectSystem/Views/UniversalFpgaProjectCompileView.axaml +++ b/src/OneWare.UniversalFpgaProjectSystem/Views/UniversalFpgaProjectCompileView.axaml @@ -19,6 +19,11 @@ + + @@ -27,14 +32,14 @@ - - + diff --git a/tests/OneWare.UniversalFpgaProjectSystem.Tests/Assets/Cyc5000/fpga.json b/tests/OneWare.UniversalFpgaProjectSystem.Tests/Assets/Cyc5000/fpga.json new file mode 100644 index 00000000..4bc65f18 --- /dev/null +++ b/tests/OneWare.UniversalFpgaProjectSystem.Tests/Assets/Cyc5000/fpga.json @@ -0,0 +1,964 @@ +{ + "Name": "CYC5000", + "Properties": { + "QuartusToolchain_Family": "Cyclone V", + "QuartusToolchain_Device": "5CEBA2U15C8", + "QuartusProgrammer_ShortTerm_Mode": "JTAG", + "QuartusProgrammer_ShortTerm_Operation": "P", + "QuartusProgrammer_LongTerm_Mode": "JTAG", + "QuartusProgrammer_LongTerm_Format": "JIC", + "QuartusProgrammer_LongTerm_CpfArguments": "-s 5CEBA2 --device EPCQ64A -m ASx4", + "QuartusProgrammer_LongTerm_Operation": "IPV" + }, + "Pins": [ + { + "Description": "CLK", + "Name": "F14" + }, + { + "Description": "LED", + "Name": "P4" + }, + { + "Description": "LED", + "Name": "M4" + }, + { + "Description": "LED", + "Name": "M3" + }, + { + "Description": "LED", + "Name": "N3" + }, + { + "Description": "LED", + "Name": "V2" + }, + { + "Description": "LED", + "Name": "T2" + }, + { + "Description": "LED", + "Name": "L1" + }, + { + "Description": "LED", + "Name": "K1" + }, + { + "Description": "Button", + "Name": "L17" + }, + { + "Description": "USB TX", + "Name": "E18" + }, + { + "Description": "USB RX", + "Name": "F16" + }, + { + "Description": "USB BD2", + "Name": "H17" + }, + { + "Description": "USB BD3", + "Name": "H16" + }, + { + "Description": "USB BD4", + "Name": "J16" + }, + { + "Description": "USB BD5", + "Name": "G15" + }, + { + "Description": "USB BD6", + "Name": "J14" + }, + { + "Description": "USB BD7", + "Name": "L15" + }, + { + "Description": "USB BC0", + "Name": "G13" + }, + { + "Description": "USB BC1", + "Name": "H13" + }, + { + "Description": "USB BC2", + "Name": "J15" + }, + { + "Description": "USB BC3", + "Name": "J13" + }, + { + "Description": "USB BC4", + "Name": "K16" + }, + { + "Description": "USB BC5", + "Name": "K18" + }, + { + "Description": "USB BC6", + "Name": "K17" + }, + { + "Description": "USB BC7", + "Name": "L16" + }, + { + "Description": "CRUVI HS SMB_ALERT", + "Name": "G17" + }, + { + "Description": "CRUVI HS SMB_SDA", + "Name": "H18" + }, + { + "Description": "CRUVI HS SMB_SCL", + "Name": "F17" + }, + { + "Description": "CRUVI HS REFCLK", + "Name": "G14" + }, + { + "Description": "CRUVI HS HSMIO", + "Name": "C16" + }, + { + "Description": "CRUVI HS HSO", + "Name": "B14" + }, + { + "Description": "CRUVI HS HSRST", + "Name": "B15" + }, + { + "Description": "CRUVI HS HSI", + "Name": "D16" + }, + { + "Description": "CRUVI HS Low Speed I/Os", + "Name": "F4" + }, + { + "Description": "CRUVI HS Low Speed I/Os", + "Name": "J3" + }, + { + "Description": "CRUVI HS Low Speed I/Os", + "Name": "E3" + }, + { + "Description": "CRUVI HS Low Speed I/Os", + "Name": "J4" + }, + { + "Description": "CRUVI HS Low Speed I/Os", + "Name": "E2" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "B17" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "B18" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "A7" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "A6" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "C13" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "C12" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "E8" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "F7" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "G6" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "F6" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "B4" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "B5" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "A12" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "B12" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "A11" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "A10" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "A14" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "A15" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "A16" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "A17" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "F9" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "F10" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "B7" + }, + { + "Description": "CRUVI HS Differential I/Os", + "Name": "B8" + }, + { + "Description": "VSEL", + "Name": "N10" + }, + { + "Description": "Low Speed I/Os", + "Name": "V17" + }, + { + "Description": "Low Speed I/Os", + "Name": "U17" + }, + { + "Description": "Low Speed I/Os", + "Name": "T17" + }, + { + "Description": "Low Speed I/Os", + "Name": "U18" + }, + { + "Description": "Low Speed I/Os", + "Name": "R17" + }, + { + "Description": "Low Speed I/Os", + "Name": "R18" + }, + { + "Description": "Low Speed I/Os", + "Name": "P18" + }, + { + "Description": "Low Speed I/Os", + "Name": "N17" + }, + { + "Description": "Low Speed I/Os", + "Name": "N18" + }, + { + "Description": "Low Speed I/Os", + "Name": "M18" + }, + { + "Description": "Low Speed I/Os", + "Name": "J18" + }, + { + "Description": "Low Speed I/Os", + "Name": "G18" + }, + { + "Description": "Low Speed I/Os", + "Name": "D18" + }, + { + "Description": "Low Speed I/Os", + "Name": "C18" + }, + { + "Description": "Low Speed I/Os", + "Name": "T1" + }, + { + "Description": "Low Speed I/Os", + "Name": "R2" + }, + { + "Description": "Low Speed I/Os", + "Name": "R1" + }, + { + "Description": "Low Speed I/Os", + "Name": "N2" + }, + { + "Description": "Low Speed I/Os", + "Name": "L2" + }, + { + "Description": "Low Speed I/Os", + "Name": "J1" + }, + { + "Description": "Low Speed I/Os", + "Name": "F1" + }, + { + "Description": "Low Speed I/Os", + "Name": "E1" + }, + { + "Description": "Low Speed I/Os", + "Name": "D1" + }, + { + "Description": "Low Speed I/Os", + "Name": "M2" + }, + { + "Description": "Low Speed I/Os", + "Name": "P1" + }, + { + "Description": "SPI Flash", + "Name": "P3" + }, + { + "Description": "SPI Flash", + "Name": "K6" + }, + { + "Description": "SPI Flash", + "Name": "V1" + }, + { + "Description": "SPI Flash", + "Name": "U2" + }, + { + "Description": "SPI Flash", + "Name": "U3" + }, + { + "Description": "SPI Flash", + "Name": "M5" + }, + { + "Description": "SDRAM Address", + "Name": "R13" + }, + { + "Description": "SDRAM Address", + "Name": "U12" + }, + { + "Description": "SDRAM Address", + "Name": "V12" + }, + { + "Description": "SDRAM Address", + "Name": "V13" + }, + { + "Description": "SDRAM Address", + "Name": "V15" + }, + { + "Description": "SDRAM Address", + "Name": "V16" + }, + { + "Description": "SDRAM Address", + "Name": "T16" + }, + { + "Description": "SDRAM Address", + "Name": "U15" + }, + { + "Description": "SDRAM Address", + "Name": "P14" + }, + { + "Description": "SDRAM Address", + "Name": "T15" + }, + { + "Description": "SDRAM Address", + "Name": "M13" + }, + { + "Description": "SDRAM Address", + "Name": "P15" + }, + { + "Description": "SDRAM Address", + "Name": "N16" + }, + { + "Description": "SDRAM Address", + "Name": "R16," + }, + { + "Description": "SDRAM Bank Select", + "Name": "T12" + }, + { + "Description": "SDRAM Bank Select", + "Name": "N13" + }, + { + "Description": "SDRAM Data", + "Name": "U4" + }, + { + "Description": "SDRAM Data", + "Name": "T4" + }, + { + "Description": "SDRAM Data", + "Name": "V6" + }, + { + "Description": "SDRAM Data", + "Name": "U5" + }, + { + "Description": "SDRAM Data", + "Name": "V7" + }, + { + "Description": "SDRAM Data", + "Name": "T5" + }, + { + "Description": "SDRAM Data", + "Name": "V8" + }, + { + "Description": "SDRAM Data", + "Name": "U8" + }, + { + "Description": "SDRAM Data", + "Name": "P10" + }, + { + "Description": "SDRAM Data", + "Name": "P9" + }, + { + "Description": "SDRAM Data", + "Name": "T11" + }, + { + "Description": "SDRAM Data", + "Name": "R9" + }, + { + "Description": "SDRAM Data", + "Name": "R11" + }, + { + "Description": "SDRAM Data", + "Name": "T9" + }, + { + "Description": "SDRAM Data", + "Name": "V10" + }, + { + "Description": "SDRAM Data", + "Name": "U9" + }, + { + "Description": "SDRAM I/O Mask", + "Name": "U13" + }, + { + "Description": "SDRAM I/O Mask", + "Name": "U14" + }, + { + "Description": "SDRAM Row Address Strobe", + "Name": "P13" + }, + { + "Description": "SDRAM Column Address Strobe", + "Name": "M14" + }, + { + "Description": "SDRAM Write Enable", + "Name": "N12" + }, + { + "Description": "SDRAM Clock", + "Name": "P16" + }, + { + "Description": "SDRAM Clock Enable", + "Name": "T14" + }, + { + "Description": "SDRAM Chip Select", + "Name": "L13" + } + ], + "Interfaces": [ + { + "Name": "CRUVIHS_1", + "Connector": "CruviHS", + "Pins": [ + { + "Name": "HS_Dif_1", + "Pin": "B17" + }, + { + "Name": "HS_Dif_2", + "Pin": "B18" + }, + { + "Name": "HS_Dif_3", + "Pin": "A7" + }, + { + "Name": "HS_Dif_4", + "Pin": "A6" + }, + { + "Name": "HS_Dif_5", + "Pin": "C13" + }, + { + "Name": "HS_Dif_6", + "Pin": "C12" + }, + { + "Name": "HS_Dif_7", + "Pin": "E8" + }, + { + "Name": "HS_Dif_8", + "Pin": "F7" + }, + { + "Name": "HS_Dif_9", + "Pin": "G6" + }, + { + "Name": "HS_Dif_10", + "Pin": "F6" + }, + { + "Name": "HS_Dif_11", + "Pin": "B4" + }, + { + "Name": "HS_Dif_12", + "Pin": "B5" + }, + { + "Name": "HS_Dif_13", + "Pin": "A12" + }, + { + "Name": "HS_Dif_14", + "Pin": "B12" + }, + { + "Name": "HS_Dif_15", + "Pin": "A11" + }, + { + "Name": "HS_Dif_16", + "Pin": "A10" + }, + { + "Name": "HS_Dif_17", + "Pin": "A14" + }, + { + "Name": "HS_Dif_18", + "Pin": "A15" + }, + { + "Name": "HS_Dif_19", + "Pin": "A16" + }, + { + "Name": "HS_Dif_20", + "Pin": "A17" + }, + { + "Name": "HS_Dif_21", + "Pin": "F9" + }, + { + "Name": "HS_Dif_22", + "Pin": "F10" + }, + { + "Name": "HS_Dif_23", + "Pin": "B7" + }, + { + "Name": "HS_Dif_24", + "Pin": "B8" + }, + { + "Name": "HS_Ale", + "Pin": "G17" + }, + { + "Name": "HS_SDA", + "Pin": "H18" + }, + { + "Name": "HS_SCL", + "Pin": "F17" + }, + { + "Name": "HS_Ref", + "Pin": "G14" + }, + { + "Name": "HS_HSM", + "Pin": "C16" + }, + { + "Name": "HS_HSO", + "Pin": "B14" + }, + { + "Name": "HS_HSR", + "Pin": "B15" + }, + { + "Name": "HS_HSI", + "Pin": "D16" + }, + { + "Name": "HS_LOW_,1", + "Pin": "F4" + }, + { + "Name": "HS_LOW_2", + "Pin": "J3" + }, + { + "Name": "HS_LOW_3", + "Pin": "E3" + }, + { + "Name": "HS_LOW_4", + "Pin": "J4" + }, + { + "Name": "HS_LOW_5", + "Pin": "E2" + } + ] + }, + { + "Name": "UART", + "Pins": [ + { + "Name": "TXD", + "Pin": "E18" + }, + { + "Name": "RXD", + "Pin": "F16" + } + ] + }, + { + "Name": "SDRAM", + "Pins": [ + { + "Name": "ADD_1", + "Pin": "R13" + }, + { + "Name": "ADD_2", + "Pin": "U12" + }, + { + "Name": "ADD_3", + "Pin": "V12" + }, + { + "Name": "ADD_4", + "Pin": "V13" + }, + { + "Name": "ADD_5", + "Pin": "V15" + }, + { + "Name": "ADD_6", + "Pin": "V16" + }, + { + "Name": "ADD_7", + "Pin": "T16" + }, + { + "Name": "ADD_8", + "Pin": "U15" + }, + { + "Name": "ADD_9", + "Pin": "P14" + }, + { + "Name": "ADD_10", + "Pin": "T15" + }, + { + "Name": "ADD_11", + "Pin": "M13" + }, + { + "Name": "ADD_12", + "Pin": "P15" + }, + { + "Name": "ADD_13", + "Pin": "N16" + }, + { + "Name": "ADD_14", + "Pin": "R16" + }, + { + "Name": "BAN_1", + "Pin": "T12" + }, + { + "Name": "BAN_2", + "Pin": "N13" + }, + { + "Name": "DAT_1", + "Pin": "U4" + }, + { + "Name": "DAT_2", + "Pin": "T4" + }, + { + "Name": "DAT_3", + "Pin": "V6" + }, + { + "Name": "DAT_4", + "Pin": "U5" + }, + { + "Name": "DAT_5", + "Pin": "V7" + }, + { + "Name": "DAT_6", + "Pin": "T5" + }, + { + "Name": "DAT_7", + "Pin": "V8" + }, + { + "Name": "DAT_8", + "Pin": "U8" + }, + { + "Name": "DAT_9", + "Pin": "P10" + }, + { + "Name": "DAT_10", + "Pin": "P9" + }, + { + "Name": "DAT_11", + "Pin": "T11" + }, + { + "Name": "DAT_12", + "Pin": "R9" + }, + { + "Name": "DAT_13", + "Pin": "R11" + }, + { + "Name": "DAT_14", + "Pin": "T9" + }, + { + "Name": "DAT_15", + "Pin": "V10" + }, + { + "Name": "DAT_16", + "Pin": "U9" + }, + { + "Name": "DQM_1", + "Pin": "U13" + }, + { + "Name": "DQM_2", + "Pin": "U14" + }, + { + "Name": "RAS", + "Pin": "P13" + }, + { + "Name": "CAS", + "Pin": "M14" + }, + { + "Name": "WEN", + "Pin": "N12" + }, + { + "Name": "ClK", + "Pin": "P16" + }, + { + "Name": "CKE", + "Pin": "T14" + }, + { + "Name": "CSE", + "Pin": "L13" + } + ] + }, + { + "Name": "FLASH", + "Pins": [ + { + "Name": "1", + "Pin": "K6" + }, + { + "Name": "2", + "Pin": "U2" + }, + { + "Name": "3", + "Pin": "V1" + }, + { + "Name": "4", + "Pin": "P3" + }, + { + "Name": "5", + "Pin": "U3" + }, + { + "Name": "6", + "Pin": "M5" + } + ] + }, + { + "Name": "LED", + "Pins": [ + { + "Name": "1", + "Pin": "P4" + }, + { + "Name": "2", + "Pin": "M4" + }, + { + "Name": "3", + "Pin": "M3" + }, + { + "Name": "4", + "Pin": "N3" + }, + { + "Name": "5", + "Pin": "V2" + }, + { + "Name": "6", + "Pin": "T2" + }, + { + "Name": "7", + "Pin": "L1" + }, + { + "Name": "8", + "Pin": "K1" + } + ] + }, + { + "Name": "CLK", + "Pins": [ + { + "Name": "1", + "Pin": "F14" + } + ] + } + ] +} diff --git a/tests/OneWare.UniversalFpgaProjectSystem.Tests/LoadFpgaTests.cs b/tests/OneWare.UniversalFpgaProjectSystem.Tests/LoadFpgaTests.cs new file mode 100644 index 00000000..b7b77efa --- /dev/null +++ b/tests/OneWare.UniversalFpgaProjectSystem.Tests/LoadFpgaTests.cs @@ -0,0 +1,17 @@ +using System; +using System.IO; +using OneWare.UniversalFpgaProjectSystem.Fpga; +using Xunit; + +namespace OneWare.UniversalFpgaProjectSystem.Tests; + +public class LoadFpgaTests +{ + [Fact] + public void LoadFpgaTest() + { + var fpga = FpgaLoader.LoadFromPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assets/Cyc5000/fpga.json")); + + Assert.Equal("CYC5000", fpga.Name); + } +} \ No newline at end of file diff --git a/tests/OneWare.UniversalFpgaProjectSystem.Tests/OneWare.UniversalFpgaProjectSystem.Tests.csproj b/tests/OneWare.UniversalFpgaProjectSystem.Tests/OneWare.UniversalFpgaProjectSystem.Tests.csproj new file mode 100644 index 00000000..07a81e57 --- /dev/null +++ b/tests/OneWare.UniversalFpgaProjectSystem.Tests/OneWare.UniversalFpgaProjectSystem.Tests.csproj @@ -0,0 +1,26 @@ + + + + + + net8.0 + Library + False + True + False + True + enable + + + + + + + + + + PreserveNewest + + + +