Skip to content

Commit

Permalink
Feature/streaming (#2)
Browse files Browse the repository at this point in the history
* streaming

* wip

* refactors

* More tests, added materialize

* tidy

* Update license text with actual license

* Bounding box calculatinos

* Change example program

---------

Co-authored-by: Boris <boris@workfloor.com>
  • Loading branch information
BorisGerretzen and Boris authored Nov 8, 2024
1 parent ed33c22 commit d48d5e0
Show file tree
Hide file tree
Showing 50 changed files with 1,063 additions and 979 deletions.
1 change: 1 addition & 0 deletions GdsGenerator/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mine
86 changes: 45 additions & 41 deletions GdsGenerator/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Numerics;
using GdsSharp.Lib;
using GdsSharp.Lib.Builders;
using GdsSharp.Lib.NonTerminals;
using GdsSharp.Lib.NonTerminals.Elements;
Expand All @@ -11,56 +12,53 @@
Version = 600
};

var structure = new GdsStructure
var elements = new List<GdsElement>
{
Name = "Example structure",
Elements =
[
// Generate a line from a Bézier curve with width 20.
// When using BuildPolygon the curve will be a GdsBoundaryElement.
new BezierBuilder()
.AddPoint(0, 0)
.AddPoint(0, 1000)
.AddPoint(1000, 1000)
.AddPoint(1000, 0)
.BuildPolygon(200),
// Generate a line from a Bézier curve with width 20.
// When using BuildPolygon the curve will be a GdsBoundaryElement.
new BezierBuilder()
.AddPoint(0, 0)
.AddPoint(0, 1000)
.AddPoint(1000, 1000)
.AddPoint(1000, 0)
.BuildPolygon(200),

// When using BuildLine the curve will be a GdsPathElement.
new BezierBuilder()
.AddPoint(-3000, 0)
.AddPoint(-3000, 1000)
.AddPoint(-2000, 1000)
.AddPoint(-2000, 0)
.BuildLine(200),
// When using BuildLine the curve will be a GdsPathElement.
new BezierBuilder()
.AddPoint(-3000, 0)
.AddPoint(-3000, 1000)
.AddPoint(-2000, 1000)
.AddPoint(-2000, 0)
.BuildLine(200),

// Create a rectangle
RectBuilder.CreateRect(-3100, -1000, 4200, 1000),
// Create a rectangle
RectBuilder.CreateRect(-3100, -1000, 4200, 1000),

// Create a circle
CircleBuilder.CreateCircle(-1000, 744, 350, 128),
// Create a circle
CircleBuilder.CreateCircle(-1000, 744, 350, 128),

// Create a polygon by manually specifying the points
new GdsElement
// Create a polygon by manually specifying the points
new()
{
Element = new GdsBoundaryElement
{
Element = new GdsBoundaryElement
{
Points =
[
new GdsPoint(-1250, 0),
new GdsPoint(-1250, 500),
new GdsPoint(-1000, 250),
new GdsPoint(-750, 500),
new GdsPoint(-750, 0),
new GdsPoint(-1250, 0)
]
}
Points =
[
new GdsPoint(-1250, 0),
new GdsPoint(-1250, 500),
new GdsPoint(-1000, 250),
new GdsPoint(-750, 500),
new GdsPoint(-750, 0),
new GdsPoint(-1250, 0)
],
NumPoints = 6
}
]
}
};

// Use the path builder to create a path
// Returns an IEnumerable of GdsElement because the path may be split into multiple elements
structure.Elements.AddRange(
elements.AddRange(
new PathBuilder(
100f,
new Vector2(-3100, -3300),
Expand Down Expand Up @@ -98,9 +96,15 @@
// Build the path in sections of 200 vertices
// This is the 'official' maximum number of vertices per element in GDSII
// In practice, the number of vertices per element can be much higher
.Build(maxVertices: 200)
.Build(200)
);

file.Structures.Add(structure);
var structure = new GdsStructure
{
Name = "Example structure",
Elements = elements
};

file.Structures = [structure];
using var write = File.OpenWrite("example.gds");
file.WriteTo(write);
104 changes: 104 additions & 0 deletions GdsSharp.Benchmarks/BufferedStreamBenchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using BenchmarkDotNet.Attributes;
using GdsSharp.Lib;
using GdsSharp.Lib.Builders;
using GdsSharp.Lib.NonTerminals;
using GdsSharp.Lib.NonTerminals.Elements;

namespace GdsSharp.Benchmarks;

public class BufferedStreamBenchmark
{

[GlobalSetup]
public void Setup()
{
var file = new GdsFile
{
LibraryName = "Test",
PhysicalUnits = 1e-6,
UserUnits = 1,
};

var structure = new GdsStructure
{
Name = "My structure",
};

var pb = new PathBuilder(1000f);
for (var i = 0; i < 1000; i++)
{
pb.Straight(1000, vertices: 10000);
}

structure.Elements = pb.Build();
file.Structures = new[] { structure };

using var fs = new FileStream("example.gds", FileMode.Create, FileAccess.Write);
file.WriteTo(fs);
}

[GlobalCleanup]
public void Cleanup()
{
File.Delete("example.gds");
}

private Stream _stream = null!;

[IterationSetup]
public void IterationSetup()
{
_stream = new FileStream("example.gds", FileMode.Open, FileAccess.Read);
}

[IterationCleanup]
public void IterationCleanup()
{
_stream.Dispose();
}

[Benchmark]
public GdsFile NoBuffer()
{
var file = GdsFile.From(_stream);

file.Structures = file.Structures.ToList();
foreach(var structure in file.Structures)
{
structure.Elements = structure.Elements.ToList();
foreach (var element in structure.Elements)
{
if (element is not {Element: GdsBoundaryElement b}) continue;

b.Points = b.Points.ToList();
}
}

return file;
}


[Benchmark]
[Arguments(4*1024)]
[Arguments(32*1024)]
public GdsFile Buffer(int size)
{
var bufferedStream = new BufferedStream(_stream, size);

var file = GdsFile.From(bufferedStream);

file.Structures = file.Structures.ToList();
foreach(var structure in file.Structures)
{
structure.Elements = structure.Elements.ToList();
foreach (var element in structure.Elements)
{
if (element is not {Element: GdsBoundaryElement b}) continue;

b.Points = b.Points.ToList();
}
}

return file;
}
}
59 changes: 59 additions & 0 deletions GdsSharp.Benchmarks/FloatToIntBenchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using BenchmarkDotNet.Attributes;

namespace GdsSharp.Benchmarks;

public class FloatToIntBenchmark
{
private readonly float[] _xs = new float[1000];
private readonly float[] _ys = new float[1000];

[GlobalSetup]
public void Setup()
{
var random = new Random();
for (int i = 0; i < _xs.Length; i++)
{
_xs[i] = (float)random.NextDouble() * 1000;
_ys[i] = (float)random.NextDouble() * 1000;
}
}

[Benchmark]
public IntPoint[] FloatToIntRound()
{
var points = new IntPoint[_xs.Length];
for (int i = 0; i < _xs.Length; i++)
{
points[i] = new IntPoint
{
X = (int)MathF.Round(_xs[i]),
Y = (int)MathF.Round(_ys[i])
};
}

return points;
}

[Benchmark]
public IntPoint[] FloatToIntAdd()
{
var points = new IntPoint[_xs.Length];
for (int i = 0; i < _xs.Length; i++)
{
points[i] = new IntPoint
{
X = (int)(_xs[i] + 0.5f),
Y = (int)(_ys[i] + 0.5f)
};
}

return points;
}


public struct IntPoint
{
public int X;
public int Y;
}
}
38 changes: 38 additions & 0 deletions GdsSharp.Benchmarks/GdsSharp.Benchmarks.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\GdsSharp.Lib\GdsSharp.Lib.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
<PackageReference Include="BenchmarkDotNet.Annotations" Version="0.14.0" />
</ItemGroup>

<ItemGroup>
<Compile Remove="PathBuilder\Implementations\PathBuilderListReverse.cs" />
<Compile Remove="PathBuilder\Implementations\PathBuilderListReverseFactorExtract.cs" />
<Compile Remove="PathBuilder\Implementations\PathBuilderListReversePrealloc.cs" />
<Compile Remove="PathBuilder\Implementations\PathBuilderSpan.cs" />
<Compile Remove="PathBuilder\IPathBuilder.cs" />
<Compile Remove="PathBuilder\PathBuilderBenchmark.cs" />
</ItemGroup>

<ItemGroup>
<Compile Remove="PathBuilder\Implementations\PathBuilderArray.cs" />
<Compile Remove="PathBuilder\Implementations\PathBuilderListReverse.cs" />
<Compile Remove="PathBuilder\Implementations\PathBuilderListReverseFactorExtract.cs" />
<Compile Remove="PathBuilder\Implementations\PathBuilderListReversePrealloc.cs" />
<Compile Remove="PathBuilder\Implementations\PathBuilderListReverseSpan.cs" />
<Compile Remove="PathBuilder\IPathBuilder.cs" />
<Compile Remove="PathBuilder\PathBuilderBase.cs" />
</ItemGroup>

</Project>
3 changes: 3 additions & 0 deletions GdsSharp.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using BenchmarkDotNet.Running;

BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
1 change: 1 addition & 0 deletions GdsSharp.Lib.Test/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[assembly: Parallelizable(ParallelScope.All)]
Binary file added GdsSharp.Lib.Test/Assets/gds3d_example.gds
Binary file not shown.
12 changes: 7 additions & 5 deletions GdsSharp.Lib.Test/GdsParserTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Reflection;
using GdsSharp.Lib.Lexing;
using GdsSharp.Lib.NonTerminals.Elements;

namespace GdsSharp.Lib.Test;

Expand All @@ -8,15 +10,15 @@ public class GdsParserTests
[TestCase("inv.gds2")]
[TestCase("nand2.gds2")]
[TestCase("xor.gds2")]
// [TestCase("osu018_stdcells.gds2")]
[TestCase("gds3d_example.gds")]
public void TestParserDoesntCrash(string manifestFile)
{
var fileStream =
using var fileStream =
Assembly.GetExecutingAssembly().GetManifestResourceStream($"GdsSharp.Lib.Test.Assets.{manifestFile}") ??
throw new NullReferenceException();
var tokenizer = new GdsTokenizer(fileStream);
var tokens = tokenizer.Tokenize();
var parser = new GdsParser(tokens);
using var stream = new GdsTokenStream(fileStream);
var parser = new GdsParser(stream);
var file = parser.Parse();
file.Materialize();
}
}
3 changes: 2 additions & 1 deletion GdsSharp.Lib.Test/GdsSharp.Lib.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
<EmbeddedResource Include="Assets\xor.gds2"/>
<None Remove="Assets\nand2.gds2"/>
<EmbeddedResource Include="Assets\nand2.gds2"/>
<None Remove="Assets\osu018_stdcells.gds2"/>
<None Remove="Assets\gds3d_example.gds" />
<EmbeddedResource Include="Assets\gds3d_example.gds" />
</ItemGroup>

</Project>
Loading

0 comments on commit d48d5e0

Please sign in to comment.