Skip to content

Commit

Permalink
quartus settings
Browse files Browse the repository at this point in the history
  • Loading branch information
HendrikMennen committed Mar 8, 2024
1 parent 6cf0861 commit daf23cb
Show file tree
Hide file tree
Showing 16 changed files with 380 additions and 115 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 5 additions & 2 deletions Extension.md
Original file line number Diff line number Diff line change
@@ -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
8 changes: 0 additions & 8 deletions oneware-extension.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
]
}
Expand Down
Binary file added src/OneWare.Quartus/Assets/Quartus_prime.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
119 changes: 119 additions & 0 deletions src/OneWare.Quartus/Helper/QsfFile.cs
Original file line number Diff line number Diff line change
@@ -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<string> 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;
}
}
}
24 changes: 24 additions & 0 deletions src/OneWare.Quartus/Helper/QsfHelper.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
8 changes: 2 additions & 6 deletions src/OneWare.Quartus/OneWare.Quartus.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,8 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="OneWare.Essentials" Version="0.2" Private="false" ExcludeAssets="runtime;Native"/>
<PackageReference Include="OneWare.UniversalFpgaProjectSystem" Version="0.15.0" Private="false" ExcludeAssets="runtime;Native"/>
</ItemGroup>

<ItemGroup>
<UpToDateCheckInput Remove="Assets\DefaultQSF.qsf" />
<PackageReference Include="OneWare.Essentials" Version="0.3" Private="false" ExcludeAssets="runtime;Native"/>
<PackageReference Include="OneWare.UniversalFpgaProjectSystem" Version="0.15.1" Private="false" ExcludeAssets="runtime;Native"/>
</ItemGroup>

</Project>
8 changes: 6 additions & 2 deletions src/OneWare.Quartus/QuartusLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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)...");
}
}
105 changes: 23 additions & 82 deletions src/OneWare.Quartus/QuartusToolchain.cs
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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)
{
Expand All @@ -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);
}
}
Loading

0 comments on commit daf23cb

Please sign in to comment.