Skip to content

Commit 64f6220

Browse files
committed
high level functionality changes
1 parent 3c58660 commit 64f6220

File tree

8 files changed

+214
-108
lines changed

8 files changed

+214
-108
lines changed

records.go renamed to decoding.go

Lines changed: 67 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,77 @@ package gds
22

33
import (
44
"bufio"
5+
"bytes"
56
"encoding/binary"
67
"encoding/hex"
78
"fmt"
89
"io"
10+
"math"
11+
"reflect"
912
)
1013

11-
// Wraps a record slice with their start record "{ELEMENTTYPE}" and end record "ENDEL"
12-
func wrapStartEnd(elementType string, records []Record) []Record {
13-
wrappedRecords := []Record{}
14-
if elementType == "BGNSTR" {
15-
return append(records, Record{Size: 4, Datatype: "ENDSTR", Data: []byte{}})
16-
} else if elementType == "BGNLIB" {
17-
return append(records, Record{Size: 4, Datatype: "ENDLIB", Data: []byte{}})
18-
} else {
19-
wrappedRecords = append(wrappedRecords, Record{Size: 4, Datatype: elementType, Data: []byte{}})
20-
wrappedRecords = append(wrappedRecords, records...)
21-
wrappedRecords = append(wrappedRecords, Record{Size: 4, Datatype: "ENDEL", Data: []byte{}})
22-
}
23-
return wrappedRecords
14+
// Convert bits which represents 8-byte real with 1-bit sign, 7-bit exponent and 56-bit mantissa to IEEE754 float64
15+
func decodeReal(bits uint64) float64 {
16+
sign := 1.0
17+
if uint64(bits&0x80_00_00_00_00_00_00_00) > 0 {
18+
sign = -1.0
19+
}
20+
exponent := int8(bits >> 56)
21+
rangingFactor := float64(uint64(0b00000001_00000000_00000000_00000000_00000000_00000000_00000000_00000000))
22+
mantissa := float64(bits&0x00_ff_ff_ff_ff_ff_ff_ff) / rangingFactor
23+
return sign * mantissa * math.Pow(16, math.Abs(float64(exponent))-64)
24+
}
25+
26+
func getRealSlice(data Record) ([]float64, error) {
27+
initSlice := make([]uint64, int((data.Size-HEADERSIZE)/8))
28+
finalSlice := make([]float64, len(initSlice))
29+
30+
reader := bytes.NewReader(data.Data)
31+
err := binary.Read(reader, binary.BigEndian, &initSlice)
32+
if err != nil {
33+
return finalSlice, fmt.Errorf("could not read binary data: %v", err)
34+
}
35+
for i, number := range initSlice {
36+
finalSlice[i] = decodeReal(number)
37+
}
38+
return finalSlice, nil
39+
}
40+
41+
func getDataSlice[T any](data Record) ([]T, error) {
42+
var typeInit T
43+
typeSize := reflect.TypeOf(typeInit).Size()
44+
result := make([]T, int((data.Size-HEADERSIZE)/uint16(typeSize)))
45+
reader := bytes.NewReader(data.Data)
46+
err := binary.Read(reader, binary.BigEndian, &result)
47+
if err != nil {
48+
return result, fmt.Errorf("could not read binary data: %v", err)
49+
}
50+
return result, nil
51+
}
52+
53+
func getRealPoint(data Record) (float64, error) {
54+
var number uint64
55+
56+
reader := bytes.NewReader(data.Data)
57+
err := binary.Read(reader, binary.BigEndian, &number)
58+
if err != nil {
59+
return float64(0), fmt.Errorf("could not read binary data: %v", err)
60+
}
61+
return decodeReal(number), nil
62+
}
63+
64+
func getDataPoint[T any](data Record) (T, error) {
65+
var result T
66+
reader := bytes.NewReader(data.Data)
67+
err := binary.Read(reader, binary.BigEndian, &result)
68+
if err != nil {
69+
return result, fmt.Errorf("could not read binary data. RecordType: %s, %v", data.Datatype, err)
70+
}
71+
return result, nil
72+
}
73+
74+
func getDataString(data Record) (string, error) {
75+
return string(data.Data), nil
2476
}
2577

2678
func decodeRecord(reader *bufio.Reader) (*Record, error) {
@@ -604,7 +656,7 @@ func decodeLibrary(reader *bufio.Reader) (*Library, error) {
604656
BgnLib: []int16{},
605657
LibName: "Unknown",
606658
Units: []float64{},
607-
Structures: []Structure{},
659+
Structures: map[string]*Structure{},
608660
}
609661
OuterLoop:
610662
for {
@@ -644,7 +696,7 @@ OuterLoop:
644696
if err != nil {
645697
return nil, fmt.Errorf("could not decode Library/%s: %v", newRecord.Datatype, err)
646698
}
647-
library.Structures = append(library.Structures, *element)
699+
library.Structures[element.StrName] = element
648700
default:
649701
return nil, fmt.Errorf("could not decode Library/%s: unkown datatype", newRecord.Datatype)
650702
}

records_test.go renamed to decoding_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,8 @@ func TestLibrary(t *testing.T) {
281281
BgnLib: []int16{2, 3},
282282
LibName: "TestLibrary",
283283
Units: []float64{4.0, 5.0},
284-
Structures: []Structure{
285-
{
284+
Structures: map[string]*Structure{
285+
"Test": {
286286
BgnStr: []int16{1, 2},
287287
StrName: "TestStructure",
288288
Elements: TestElements,

encoding.go

Lines changed: 1 addition & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package gds
22

33
import (
4-
"bytes"
5-
"encoding/binary"
64
"fmt"
75
"math"
86
"reflect"
@@ -23,7 +21,7 @@ func fieldsToRecords(data any) ([]Record, error) {
2321
records = append(records, newRecords...)
2422
}
2523
} else if v.Type().Field(i).Name == "Structures" {
26-
for _, structure := range v.Field(i).Interface().([]Structure) {
24+
for _, structure := range v.Field(i).Interface().(map[string]*Structure) {
2725
newRecords, err := structure.Records()
2826
if err != nil {
2927
return []Record{}, err
@@ -126,18 +124,6 @@ func bitsToByteArray(i uint64) []byte {
126124
}
127125
}
128126

129-
// Convert bits which represents 8-byte real with 1-bit sign, 7-bit exponent and 56-bit mantissa to IEEE754 float64
130-
func decodeReal(bits uint64) float64 {
131-
sign := 1.0
132-
if uint64(bits&0x80_00_00_00_00_00_00_00) > 0 {
133-
sign = -1.0
134-
}
135-
exponent := int8(bits >> 56)
136-
rangingFactor := float64(uint64(0b00000001_00000000_00000000_00000000_00000000_00000000_00000000_00000000))
137-
mantissa := float64(bits&0x00_ff_ff_ff_ff_ff_ff_ff) / rangingFactor
138-
return sign * mantissa * math.Pow(16, math.Abs(float64(exponent))-64)
139-
}
140-
141127
// Convert IEEE754 float64 to 8-byte real with 1-bit sign, 7-bit exponent and 56-bit mantissa
142128
func encodeReal(fl float64) (uint64, error) {
143129
if fl == 0.0 {
@@ -169,55 +155,3 @@ func encodeReal(fl float64) (uint64, error) {
169155
newExpUint := uint64(newExp + 64)
170156
return uint64(sign | (factor >> 8) | (newExpUint << 56)), nil
171157
}
172-
173-
func getRealSlice(data Record) ([]float64, error) {
174-
initSlice := make([]uint64, int((data.Size-HEADERSIZE)/8))
175-
finalSlice := make([]float64, len(initSlice))
176-
177-
reader := bytes.NewReader(data.Data)
178-
err := binary.Read(reader, binary.BigEndian, &initSlice)
179-
if err != nil {
180-
return finalSlice, fmt.Errorf("could not read binary data: %v", err)
181-
}
182-
for i, number := range initSlice {
183-
finalSlice[i] = decodeReal(number)
184-
}
185-
return finalSlice, nil
186-
}
187-
188-
func getDataSlice[T any](data Record) ([]T, error) {
189-
var typeInit T
190-
typeSize := reflect.TypeOf(typeInit).Size()
191-
result := make([]T, int((data.Size-HEADERSIZE)/uint16(typeSize)))
192-
reader := bytes.NewReader(data.Data)
193-
err := binary.Read(reader, binary.BigEndian, &result)
194-
if err != nil {
195-
return result, fmt.Errorf("could not read binary data: %v", err)
196-
}
197-
return result, nil
198-
}
199-
200-
func getRealPoint(data Record) (float64, error) {
201-
var number uint64
202-
203-
reader := bytes.NewReader(data.Data)
204-
err := binary.Read(reader, binary.BigEndian, &number)
205-
if err != nil {
206-
return float64(0), fmt.Errorf("could not read binary data: %v", err)
207-
}
208-
return decodeReal(number), nil
209-
}
210-
211-
func getDataPoint[T any](data Record) (T, error) {
212-
var result T
213-
reader := bytes.NewReader(data.Data)
214-
err := binary.Read(reader, binary.BigEndian, &result)
215-
if err != nil {
216-
return result, fmt.Errorf("could not read binary data. RecordType: %s, %v", data.Datatype, err)
217-
}
218-
return result, nil
219-
}
220-
221-
func getDataString(data Record) (string, error) {
222-
return string(data.Data), nil
223-
}

gds.go

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -53,25 +53,19 @@ func WriteGDS(f *os.File, lib *Library) error {
5353
return nil
5454
}
5555

56-
func (l Library) GetLayers() map[string][]Element {
57-
result := map[string][]Element{}
56+
func (l Library) GetLayermapPolygons() map[string]*PolygonLayer {
57+
result := map[string]*PolygonLayer{}
5858
for _, structure := range l.Structures {
5959
for _, element := range structure.Elements {
60-
elementSlice, ok := result[element.GetLayer()]
61-
if ok {
62-
result[element.GetLayer()] = append(elementSlice, element)
63-
} else {
64-
result[element.GetLayer()] = []Element{element}
60+
if element.Type() == PolygonType {
61+
layer, ok := result[element.GetLayer()]
62+
if ok {
63+
layer.appendPolygon(element.(Polygon).GetPoints())
64+
} else {
65+
result[element.GetLayer()] = &PolygonLayer{Enabled: true, Polygons: [][]int32{element.(Polygon).GetPoints()}}
66+
}
6567
}
6668
}
6769
}
6870
return result
6971
}
70-
71-
func (l Library) GetStructures() map[string]Structure {
72-
result := map[string]Structure{}
73-
for _, structure := range l.Structures {
74-
result[structure.StrName] = structure
75-
}
76-
return result
77-
}

gds_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func TestReadGDS(t *testing.T) {
2222
fmt.Print(library)
2323
}
2424

25-
func TestLayers(t *testing.T) {
25+
func TestGetLayerPolygons(t *testing.T) {
2626
testFile := "klayout_test.gds"
2727

2828
fh, err := os.Open(testFile)
@@ -35,7 +35,7 @@ func TestLayers(t *testing.T) {
3535
if err != nil {
3636
t.Fatalf("could not parse gds file: %v", err)
3737
}
38-
fmt.Print(library.GetLayers())
38+
fmt.Print(library.GetLayermapPolygons())
3939
}
4040

4141
func TestReadRecords(t *testing.T) {

helpers.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package gds
2+
3+
import "math"
4+
5+
// Wraps a record slice with their start record "{ELEMENTTYPE}" and end record "ENDEL"
6+
func wrapStartEnd(elementType string, records []Record) []Record {
7+
wrappedRecords := []Record{}
8+
if elementType == "BGNSTR" {
9+
return append(records, Record{Size: 4, Datatype: "ENDSTR", Data: []byte{}})
10+
} else if elementType == "BGNLIB" {
11+
return append(records, Record{Size: 4, Datatype: "ENDLIB", Data: []byte{}})
12+
} else {
13+
wrappedRecords = append(wrappedRecords, Record{Size: 4, Datatype: elementType, Data: []byte{}})
14+
wrappedRecords = append(wrappedRecords, records...)
15+
wrappedRecords = append(wrappedRecords, Record{Size: 4, Datatype: "ENDEL", Data: []byte{}})
16+
}
17+
return wrappedRecords
18+
}
19+
20+
func resolveSRefPolygons(lib *Library, ref SRef) map[string][][]int32 {
21+
result := map[string][][]int32{}
22+
for _, element := range lib.Structures[ref.Sname].Elements {
23+
if element.Type() == PolygonType {
24+
points := transformPoints(element.(Polygon).GetPoints(), ref.XY[0], ref.XY[1], ref.Strans, ref.Mag, ref.Angle)
25+
_, ok := result[element.GetLayer()]
26+
if ok {
27+
result[element.GetLayer()] = append(result[element.GetLayer()], points)
28+
} else {
29+
result[element.GetLayer()] = [][]int32{points}
30+
}
31+
}
32+
}
33+
return result
34+
}
35+
36+
func transformPoints(array []int32, xshift int32, yshift int32, strans uint16, mag float64, angle float64) []int32 {
37+
radians := angle * math.Pi / 180
38+
transformedArray := make([]int32, len(array))
39+
for i := 0; i < len(array); i += 2 {
40+
var x, y int32
41+
// y-Axis mirroring
42+
x = array[i]
43+
y = array[i+1] * int32((0.5-float32((strans>>15)))*2)
44+
// rotation + magnification
45+
x = int32((float64(x)*math.Cos(radians) - float64(x)*math.Sin(radians)) * mag)
46+
y = int32((float64(y)*math.Cos(radians) + float64(y)*math.Sin(radians)) * mag)
47+
// shift
48+
transformedArray[i] = int32(x) + xshift
49+
transformedArray[i+1] = int32(y) + yshift
50+
51+
}
52+
return transformedArray
53+
}

highlevel_types.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package gds
2+
3+
import "fmt"
4+
5+
type PolygonLayer struct {
6+
Enabled bool
7+
Polygons [][]int32
8+
}
9+
10+
type PathLayer struct {
11+
Enabled bool
12+
Polygons []Polygon
13+
}
14+
15+
type LabelLayer struct {
16+
Enabled bool
17+
Polygons []Polygon
18+
}
19+
20+
func (p *PolygonLayer) appendPolygon(poly []int32) [][]int32 {
21+
p.Polygons = append(p.Polygons, poly)
22+
return p.Polygons
23+
}
24+
func (p PolygonLayer) String() string {
25+
return fmt.Sprintf("%v, %v", p.Enabled, p.Polygons)
26+
}
27+
28+
type Polygon interface {
29+
GetPoints() []int32
30+
}
31+
32+
type Reference interface {
33+
GetSname() string
34+
}

0 commit comments

Comments
 (0)