From d90aff6719ff9d32a987dffcdc328b55401feef8 Mon Sep 17 00:00:00 2001 From: Sebastian Wittlich Date: Wed, 18 Mar 2026 18:56:58 +0100 Subject: [PATCH 1/2] BugFixes --- .../GhdlExtensionModule.cs | 4 +++ .../GhdlVhdlToVerilogPreCompileStep.cs | 6 ++-- .../GhdlYosysToolchain.cs | 2 +- .../Services/GhdlService.cs | 29 +++++++++++++++++++ 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/OneWare.GhdlExtension/GhdlExtensionModule.cs b/src/OneWare.GhdlExtension/GhdlExtensionModule.cs index afbdeda..c784183 100644 --- a/src/OneWare.GhdlExtension/GhdlExtensionModule.cs +++ b/src/OneWare.GhdlExtension/GhdlExtensionModule.cs @@ -13,6 +13,8 @@ using OneWare.Essentials.Models; using OneWare.Essentials.PackageManager; using OneWare.Essentials.Services; +using OneWare.Essentials.ToolEngine; +using OneWare.Essentials.ToolEngine.Strategies; using OneWare.Essentials.ViewModels; using OneWare.GhdlExtension.Services; using OneWare.GhdlExtension.ViewModels; @@ -396,6 +398,8 @@ public override void Initialize(IServiceProvider serviceProvider) } } })); + + toolService.Register(new ToolContext("ghdl", "Synth Tool", "ghdl"), new NativeStrategy()); serviceProvider.Resolve().RegisterConstructContextMenu(((list, models) => { diff --git a/src/OneWare.GhdlExtension/GhdlVhdlToVerilogPreCompileStep.cs b/src/OneWare.GhdlExtension/GhdlVhdlToVerilogPreCompileStep.cs index 01e0ed2..e9d85da 100644 --- a/src/OneWare.GhdlExtension/GhdlVhdlToVerilogPreCompileStep.cs +++ b/src/OneWare.GhdlExtension/GhdlVhdlToVerilogPreCompileStep.cs @@ -11,11 +11,13 @@ public class GhdlVhdlToVerilogPreCompileStep(GhdlService ghdlService, ILogger lo public string Name => "GHDL Vhdl to Verilog"; public readonly string BuildDir = "build"; - public readonly string GhdlOutputDir = "ghdl-output"; + public readonly string GhdlOutputDir = "gen_verilog"; public string? VerilogFileName; public async Task PerformPreCompileStepAsync(UniversalFpgaProjectRoot project, FpgaModel fpga) { + if (project.TopEntity == null || !project.TopEntity.EndsWith(".vhd")) return false; + try { var buildPath = Path.Combine(project.FullPath, BuildDir); @@ -27,7 +29,7 @@ public async Task PerformPreCompileStepAsync(UniversalFpgaProjectRoot proj var vhdlFile = Path.Combine(project.RootFolderPath, project.TopEntity ?? ""); VerilogFileName = Path.GetFileNameWithoutExtension(vhdlFile)+".v"; - + var success = await ghdlService.SynthAsync(vhdlFile, "verilog", ghdlOutputPath); return success; } diff --git a/src/OneWare.GhdlExtension/GhdlYosysToolchain.cs b/src/OneWare.GhdlExtension/GhdlYosysToolchain.cs index 3ebfaf1..1d4d44a 100644 --- a/src/OneWare.GhdlExtension/GhdlYosysToolchain.cs +++ b/src/OneWare.GhdlExtension/GhdlYosysToolchain.cs @@ -8,7 +8,7 @@ namespace OneWare.GhdlExtension; public class GhdlYosysToolchain(GhdlToolchainService ghdlToolchainService, YosysService yosysService) : YosysToolchain(yosysService) { - public const string ToolchainId = "ghdl_yosys"; + public const string ToolchainId = "GHDL_Yosys"; public override async Task CompileAsync(UniversalFpgaProjectRoot project, FpgaModel fpga) { diff --git a/src/OneWare.GhdlExtension/Services/GhdlService.cs b/src/OneWare.GhdlExtension/Services/GhdlService.cs index d0eedd1..cd9fa5e 100644 --- a/src/OneWare.GhdlExtension/Services/GhdlService.cs +++ b/src/OneWare.GhdlExtension/Services/GhdlService.cs @@ -7,6 +7,7 @@ using OneWare.Essentials.Models; using OneWare.Essentials.PackageManager.Compatibility; using OneWare.Essentials.Services; +using OneWare.Essentials.ToolEngine; using OneWare.Essentials.ViewModels; using OneWare.GhdlExtension.ViewModels; using OneWare.UniversalFpgaProjectSystem.Context; @@ -90,7 +91,35 @@ or PackageStatus.Installing StringBuilder stdoutBuilder = new StringBuilder(); StringBuilder stderrBuilder = new StringBuilder(); + + var command = ToolCommand.FromShellParams(_path, arguments, workingDirectory, + status, state, showTimer, x => + { + if (x.StartsWith("ghdl:error:")) + { + _logger.Error(x); + return false; + } + + _outputService.WriteLine(x); + stdoutBuilder.AppendLine(x); + return true; + }, x => + { + if (x.StartsWith("ghdl:error:")) + { + _logger.Error(x); + return false; + } + + _logger.Warning(x); + stderrBuilder.AppendLine(x); + return true; + }); + + + (bool success, _) = await _childProcessService.ExecuteShellAsync(_path, arguments, workingDirectory, status, state, showTimer, x => { From 824f4e504c84ea1432f3f17b6e10158da1df3159 Mon Sep 17 00:00:00 2001 From: Sebastian Wittlich Date: Wed, 18 Mar 2026 19:22:05 +0100 Subject: [PATCH 2/2] GHDL using ToolEngine --- .../GhdlExtensionModule.cs | 2 +- .../Services/GhdlService.cs | 61 +++++-------------- 2 files changed, 17 insertions(+), 46 deletions(-) diff --git a/src/OneWare.GhdlExtension/GhdlExtensionModule.cs b/src/OneWare.GhdlExtension/GhdlExtensionModule.cs index c784183..e17e89e 100644 --- a/src/OneWare.GhdlExtension/GhdlExtensionModule.cs +++ b/src/OneWare.GhdlExtension/GhdlExtensionModule.cs @@ -452,7 +452,7 @@ public override void Initialize(IServiceProvider serviceProvider) })); - var ghdlPreCompiler = serviceProvider.Resolve(); + // var ghdlPreCompiler = serviceProvider.Resolve(); serviceProvider.Resolve().RegisterUiExtension("UniversalFpgaToolBar_CompileMenuExtension", new OneWareUiExtension(x => { diff --git a/src/OneWare.GhdlExtension/Services/GhdlService.cs b/src/OneWare.GhdlExtension/Services/GhdlService.cs index cd9fa5e..2e18463 100644 --- a/src/OneWare.GhdlExtension/Services/GhdlService.cs +++ b/src/OneWare.GhdlExtension/Services/GhdlService.cs @@ -20,11 +20,11 @@ public class GhdlService private readonly ILogger _logger; private readonly IMainDockService _dockService; private readonly IPackageService _packageService; - private readonly IChildProcessService _childProcessService; private readonly IEnvironmentService _environmentService; private readonly IOutputService _outputService; private readonly ISettingsService _settingsService; private readonly IProjectExplorerService _projectExplorerService; + private readonly IToolExecutionDispatcherService _toolExecutionDispatcherService; public AsyncRelayCommand SimulateCommand { get; } @@ -35,18 +35,19 @@ public class GhdlService private string _path = string.Empty; public GhdlService(ILogger logger, IMainDockService dockService, ISettingsService settingsService, - IPackageService packageService, IChildProcessService childProcessService, + IPackageService packageService, IEnvironmentService environmentService, - IOutputService outputService, IProjectExplorerService projectExplorerService) + IOutputService outputService, IProjectExplorerService projectExplorerService, + IToolExecutionDispatcherService toolExecutionDispatcherService) { _logger = logger; _dockService = dockService; _packageService = packageService; - _childProcessService = childProcessService; _environmentService = environmentService; _outputService = outputService; _settingsService = settingsService; _projectExplorerService = projectExplorerService; + _toolExecutionDispatcherService = toolExecutionDispatcherService; settingsService.GetSettingObservable(GhdlExtensionModule.GhdlPathSetting).Subscribe(x => { @@ -63,7 +64,7 @@ public GhdlService(ILogger logger, IMainDockService dockService, ISettingsServic SynthToVerilogCommand = new AsyncRelayCommand(() => SynthCurrentFileAsync("verilog"), () => Path.GetExtension(_dockService.CurrentDocument?.FullPath) is ".vhd" or ".vhdl"); - _dockService.WhenValueChanged(x => x.CurrentDocument).Subscribe(x => + _dockService.WhenValueChanged(x => x.CurrentDocument).Subscribe(_ => { SimulateCommand.NotifyCanExecuteChanged(); }); @@ -116,35 +117,8 @@ or PackageStatus.Installing stderrBuilder.AppendLine(x); return true; }); - - - - - (bool success, _) = await _childProcessService.ExecuteShellAsync(_path, arguments, workingDirectory, - status, state, showTimer, x => - { - if (x.StartsWith("ghdl:error:")) - { - _logger.Error(x); - return false; - } - - _outputService.WriteLine(x); - stdoutBuilder.AppendLine(x); - return true; - }, x => - { - if (x.StartsWith("ghdl:error:")) - { - _logger.Error(x); - return false; - } - - _logger.Warning(x); - stderrBuilder.AppendLine(x); - return true; - }); + var (success, _) = await _toolExecutionDispatcherService.ExecuteAsync(command); return (success, stdoutBuilder.ToString(), stderrBuilder.ToString()); } @@ -180,7 +154,7 @@ private void SetEnvironment() private Task SynthCurrentFileAsync(string output) { if (_dockService.CurrentDocument?.FullPath is { } fullPath) - return SynthAsync(fullPath, output, Path.GetDirectoryName(fullPath)); + return SynthAsync(fullPath, output, Path.GetDirectoryName(fullPath)!); return Task.CompletedTask; } @@ -188,9 +162,9 @@ private async Task ElaborateAsync(string fullPath, TestBenchContext contex { if (_projectExplorerService.GetRootFromFile(fullPath) is not UniversalFpgaProjectRoot root) return false; - IEnumerable libfiles = GetAllLibraryFiles(root); + var libfiles = GetAllLibraryFiles(root); - IEnumerable? libnames = root.Properties.GetStringArray("GHDL_Libraries"); + var libnames = root.Properties.GetStringArray("GHDL_Libraries"); var vhdlFiles = root.GetFiles("*.vhd").Concat(root.GetFiles("*.vhdl")) .Where(x => !root.IsCompileExcluded(x)) @@ -247,12 +221,12 @@ private async Task ElaborateAsync(string fullPath, TestBenchContext contex "GHDL Init...", AppState.Loading, true); if (!initFiles.success) return false; - + if (libnames is not null) { - foreach (string libname in libnames) + foreach (var libname in libnames) { - bool success = await ImportLibraryAsync(root, context, libname, workingDirectory, ghdlOptions); + var success = await ImportLibraryAsync(root, context, libname, workingDirectory, ghdlOptions); if (!success) { @@ -288,10 +262,9 @@ private async Task ElaborateAsync(string fullPath, TestBenchContext contex private async Task ImportLibraryAsync(UniversalFpgaProjectRoot root, TestBenchContext context, string libname, string workingDirectory, List ghdlOptions) { - string buildDirectory = Path.Combine(workingDirectory, "build"); // Get files contained in library - IEnumerable? libraryFiles = root.Properties.GetStringArray($"GHDL-LIB_{libname}"); + var libraryFiles = root.Properties.GetStringArray($"GHDL-LIB_{libname}"); if (libraryFiles is null) { @@ -300,7 +273,7 @@ private async Task ImportLibraryAsync(UniversalFpgaProjectRoot root, TestB return true; } - IEnumerable vhdlFiles = root.GetFiles("*.vhd").Concat(root.GetFiles("*.vhdl")) + var vhdlFiles = root.GetFiles("*.vhd").Concat(root.GetFiles("*.vhdl")) .Where(x => !root.IsCompileExcluded(x)) .Where(x => libraryFiles.Contains(x.ToUnixPath())); @@ -319,8 +292,6 @@ private async Task ImportLibraryAsync(UniversalFpgaProjectRoot root, TestB private async Task MakeLibraryAsync(UniversalFpgaProjectRoot root, TestBenchContext context, string libname, string workingDirectory, List ghdlOptions) { - string buildDirectory = Path.Combine(workingDirectory, "build"); - if (root.TopEntity == null) { _logger.Error("No toplevel entity has been set"); @@ -353,7 +324,7 @@ private IEnumerable GetAllLibraryFiles(UniversalFpgaProjectRoot root) foreach (string lib in libnames) { - IEnumerable? libfiles = root.Properties.GetStringArray($"GHDL-LIB_{lib}")?.ToArray(); + var libfiles = root.Properties.GetStringArray($"GHDL-LIB_{lib}")?.ToArray(); if (libfiles is null || !libfiles.Any()) {