From 424088dc44ecba9e07c98f9fafa8eddefcd58736 Mon Sep 17 00:00:00 2001 From: Hendrik Mennen Date: Fri, 22 Mar 2024 01:24:24 +0100 Subject: [PATCH] long term programming --- src/OneWare.Quartus/OneWare.Quartus.csproj | 4 +- src/OneWare.Quartus/QuartusLoader.cs | 111 ++++++++++++++++++--- src/OneWare.Quartus/oneware.json | 8 +- 3 files changed, 101 insertions(+), 22 deletions(-) diff --git a/src/OneWare.Quartus/OneWare.Quartus.csproj b/src/OneWare.Quartus/OneWare.Quartus.csproj index efdea56..f3eb449 100644 --- a/src/OneWare.Quartus/OneWare.Quartus.csproj +++ b/src/OneWare.Quartus/OneWare.Quartus.csproj @@ -16,8 +16,8 @@ - - + + diff --git a/src/OneWare.Quartus/QuartusLoader.cs b/src/OneWare.Quartus/QuartusLoader.cs index 8ac1a42..e221f31 100644 --- a/src/OneWare.Quartus/QuartusLoader.cs +++ b/src/OneWare.Quartus/QuartusLoader.cs @@ -1,12 +1,17 @@ -using Microsoft.Extensions.Logging; +using AvaloniaEdit.Utils; +using DynamicData; +using Microsoft.Extensions.Logging; +using OneWare.Essentials.Enums; using OneWare.Essentials.Services; using OneWare.UniversalFpgaProjectSystem.Models; +using OneWare.UniversalFpgaProjectSystem.Parser; using OneWare.UniversalFpgaProjectSystem.Services; using ILogger = OneWare.Essentials.Services.ILogger; namespace OneWare.Quartus; -public class QuartusLoader(IChildProcessService childProcessService, ILogger logger) : IFpgaLoader +public class QuartusLoader(IChildProcessService childProcessService, ISettingsService settingsService, ILogger logger) + : IFpgaLoader { public string Name => "Quartus"; @@ -19,33 +24,107 @@ public class QuartusLoader(IChildProcessService childProcessService, ILogger log .FirstOrDefault(x => Path.GetExtension(x).Equals(extension, StringComparison.OrdinalIgnoreCase)); } catch (Exception e) - { + { logger.Error(e.Message, e); return null; } } - + public async Task DownloadAsync(UniversalFpgaProjectRoot project) { - var fpga = project.Properties["Fpga"]; + var fpga = project.GetProjectProperty("Fpga"); if (fpga == null) return; - var fpgaModel = fpga.ToString(); - var mode = "JTAG"; + + var longTerm = settingsService.GetSettingValue("UniversalFpgaProjectSystem_LongTermProgramming"); + + var properties = FpgaSettingsParser.LoadSettings(project, fpga); var cableSetting = "Auto"; var cableName = cableSetting == "Auto" ? "1" : "\"" + cableSetting + "\""; - - var sofFile = Path.GetFileName(FirstFileInPath(project.FullPath, ".sof") ?? ""); - - if (string.IsNullOrEmpty(sofFile)) + + if (!longTerm) { - logger.Error("no .sof found! compile Design first!"); - return; + var sofFile = Path.GetFileName(FirstFileInPath(project.FullPath, ".sof") ?? ""); + + if (string.IsNullOrEmpty(sofFile)) + { + logger.Error("no .sof found! compile Design first!"); + return; + } + + var shortTermMode = properties.GetValueOrDefault("QuartusProgrammer_ShortTermMode") ?? "JTAG"; + var shortTermOperation = properties.GetValueOrDefault("QuartusProgrammer_ShortTermOperation") ?? "P"; + var shortTermArgs = properties.GetValueOrDefault("QuartusProgrammer_ShortTerm_Arguments")?.Split(' ') ?? []; + + List pgmArgs = ["-c", cableName, "-m", shortTermMode]; + pgmArgs.AddRange(shortTermArgs); + pgmArgs.AddRange(["-o", $"p;{sofFile}"]); + + await childProcessService.ExecuteShellAsync("quartus_pgm", pgmArgs, + project.FullPath, "Running Quartus programmer (Short-Term)...", AppState.Loading, true); + } + else + { + var longTermFormat = properties.GetValueOrDefault("QuartusProgrammer_LongTerm_Format") ?? "POF"; + + string programFile; + + if (longTermFormat.Equals("pof", StringComparison.OrdinalIgnoreCase)) + { + var pofFile = Path.GetFileName(FirstFileInPath(project.FullPath, ".pof") ?? ""); + + if (string.IsNullOrEmpty(pofFile)) + { + logger.Error("no .pof found! compile Design first!"); + return; + } + + programFile = pofFile; + } + else + { + //Use CPF to convert SOF in given format + var sofFile = Path.GetFileName(FirstFileInPath(project.FullPath, ".sof") ?? ""); + + if (string.IsNullOrEmpty(sofFile)) + { + logger.Error("no .sof found! compile Design first!"); + return; + } + + var configurationMode = properties.GetValueOrDefault("QuartusProgrammer_LongTerm_CpfArguments"); + + if (configurationMode == null) + { + logger.Error("Cpf Arguments cannot be empty!"); + return; + } + + var convertedFilePath = Path.GetFileNameWithoutExtension(sofFile) + $".{longTermFormat.ToLower()}"; + + var cpfArgs = configurationMode.Split(' ').ToList(); + cpfArgs.AddRange(["-c", sofFile, convertedFilePath]); + + var result = await childProcessService.ExecuteShellAsync("quartus_cpf", cpfArgs, + project.FullPath, $"Converting .sof to .{longTermFormat.ToLower()}..."); + + if (!result.success) return; + + programFile = convertedFilePath; + } + + var longTermMode = properties.GetValueOrDefault("QuartusProgrammer_LongTermMode") ?? "JTAG"; + var longTermOperation = properties.GetValueOrDefault("QuartusProgrammer_LongTermOperation") ?? "P"; + var longTermArgs = properties.GetValueOrDefault("QuartusProgrammer_LongTerm_Arguments")?.Split(' ') ?? []; + + List pgmArgs = ["-c", cableName, "-m", longTermMode]; + pgmArgs.AddRange(longTermArgs); + pgmArgs.AddRange(["-o", $"{longTermOperation};{programFile}"]); + + await childProcessService.ExecuteShellAsync("quartus_pgm", pgmArgs, + project.FullPath, "Running Quartus programmer (Long-Term)...", AppState.Loading, true); } - - await childProcessService.ExecuteShellAsync("quartus_pgm", ["-c", cableName, "-m", mode, "-o", $"p;{sofFile}"], - project.FullPath, "Running Quartus programmer (Short-Term)..."); } } \ No newline at end of file diff --git a/src/OneWare.Quartus/oneware.json b/src/OneWare.Quartus/oneware.json index e48ccb3..c26be7f 100644 --- a/src/OneWare.Quartus/oneware.json +++ b/src/OneWare.Quartus/oneware.json @@ -2,13 +2,13 @@ "Dependencies": [ { "Name": "OneWare.Essentials", - "MinVersion": "0.4.5.0", - "MaxVersion": "0.4.5.0" + "MinVersion": "0.4.6.0", + "MaxVersion": "0.4.6.0" }, { "Name": "OneWare.UniversalFpgaProjectSystem", - "MinVersion": "0.16.7.0", - "MaxVersion": "0.16.7.0" + "MinVersion": "0.16.8.0", + "MaxVersion": "0.16.8.0" } ] } \ No newline at end of file