jfreeze-ruby-gdsii 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. data/CHANGELOG.txt +6 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.txt +113 -0
  4. data/Rakefile +30 -0
  5. data/bin/rgds-debug +43 -0
  6. data/bin/rgds-dump +38 -0
  7. data/bin/rgds-join +98 -0
  8. data/bin/rgds-layers +53 -0
  9. data/bin/rgds-sremove +136 -0
  10. data/bin/rgds-ssplit +113 -0
  11. data/bin/rgds-stats +134 -0
  12. data/bin/rgds-structs +41 -0
  13. data/bin/rgds-tree +167 -0
  14. data/bin/rgds2rb +99 -0
  15. data/lib/gdsii.rb +137 -0
  16. data/lib/gdsii/aref.rb +243 -0
  17. data/lib/gdsii/bnf.rb +309 -0
  18. data/lib/gdsii/boundary.rb +53 -0
  19. data/lib/gdsii/box.rb +65 -0
  20. data/lib/gdsii/byte_order.rb +36 -0
  21. data/lib/gdsii/element.rb +172 -0
  22. data/lib/gdsii/group.rb +98 -0
  23. data/lib/gdsii/library.rb +518 -0
  24. data/lib/gdsii/mixins.rb +378 -0
  25. data/lib/gdsii/node.rb +65 -0
  26. data/lib/gdsii/path.rb +169 -0
  27. data/lib/gdsii/property.rb +108 -0
  28. data/lib/gdsii/record.rb +606 -0
  29. data/lib/gdsii/record/consts.rb +384 -0
  30. data/lib/gdsii/record/datatypes/ascii.rb +145 -0
  31. data/lib/gdsii/record/datatypes/bitarray.rb +101 -0
  32. data/lib/gdsii/record/datatypes/data.rb +111 -0
  33. data/lib/gdsii/record/datatypes/int2.rb +67 -0
  34. data/lib/gdsii/record/datatypes/int4.rb +65 -0
  35. data/lib/gdsii/record/datatypes/nodata.rb +60 -0
  36. data/lib/gdsii/record/datatypes/real4.rb +51 -0
  37. data/lib/gdsii/record/datatypes/real8.rb +120 -0
  38. data/lib/gdsii/sref.rb +61 -0
  39. data/lib/gdsii/strans.rb +133 -0
  40. data/lib/gdsii/structure.rb +352 -0
  41. data/lib/gdsii/text.rb +203 -0
  42. data/pkg/ruby-gdsii.gem +46 -0
  43. data/samples/hello.gds +0 -0
  44. data/samples/hello.out.rb +84 -0
  45. data/samples/hello.rb +94 -0
  46. data/test/baseline/dcp1.gds +0 -0
  47. data/test/baseline/h_write.gds +0 -0
  48. data/test/h_pthru.rb +22 -0
  49. data/test/h_write.rb +117 -0
  50. data/test/hs_pthru.rb +31 -0
  51. data/test/l_pthru.rb +23 -0
  52. data/test/test_gds_group.rb +379 -0
  53. data/test/test_gds_record.rb +99 -0
  54. metadata +117 -0
data/test/h_write.rb ADDED
@@ -0,0 +1,117 @@
1
+ ##############################################################################
2
+ #
3
+ # == write.rb
4
+ #
5
+ # Tests the capabilities of writing GDSII using the high-level group objects.
6
+ # This test should cover most of the capabilities of the high-level GDSII
7
+ # methods.
8
+ #
9
+ # === Author
10
+ #
11
+ # James D. Masters (james.d.masters@gmail.com)
12
+ #
13
+ ##############################################################################
14
+
15
+ require 'time'
16
+ require 'gdsii'
17
+
18
+ include Gdsii
19
+
20
+
21
+ # Get arguments / show usage...
22
+ unless (out_file = ARGV[0])
23
+ abort "
24
+ Uses high-level GDSII methods to write out a number of GDSII records using
25
+ many of the available method calls. This can be useful to verify that the
26
+ GDSII library is working and the output file can be compared against the
27
+ file found in ./test/baseline/h_write.gds to ensure that the platform is
28
+ reading and writing GDSII properly.
29
+
30
+ Usage: h_write.rb <out-file>
31
+
32
+ "
33
+ end
34
+
35
+
36
+ # Get a standard time (epoch; 12/31/1969) so we have the same time stamp for
37
+ # comparing GDSII output
38
+ time = Time.utc(2000, 1, 1, 0, 0, 0)
39
+
40
+ # Create a new GDSII library
41
+ lib = Library.new('MYLIB.DB')
42
+ lib.modify_time = time
43
+ lib.access_time = time
44
+
45
+ # Create a top level structure
46
+ top = Structure.new('top')
47
+ top.create_time = time
48
+ top.modify_time = time
49
+
50
+ # Create a box 5u square on layer 1:0 with the center at the origin
51
+ Boundary.new(1, 0, [-2500,-2500, -2500,2500, 2500,2500, 2500,-2500, -2500,-2500]) do |bnd|
52
+ bnd.add Property.new(1, 'testprop1')
53
+ bnd.add Property.new(1, 'testprop2')
54
+ bnd.add Property.new(2, 'testprop3')
55
+ top.add bnd
56
+ end
57
+
58
+ # Create text labels around the 5u box using different text label origins
59
+ top.add Text.new(1, 0, [0,0], 'c', 0, :c )
60
+ top.add Text.new(1, 0, [0,2500], 'n', 0, :n )
61
+ top.add Text.new(1, 0, [2500,2500], 'ne', 0, :ne)
62
+ top.add Text.new(1, 0, [2500,0], 'e', 0, :e )
63
+ top.add Text.new(1, 0, [2500,-2500], 'se', 0, :se)
64
+ top.add Text.new(1, 0, [0,-2500], 's', 0, :s )
65
+ top.add Text.new(1, 0, [-2500,-2500], 'sw', 0, :sw)
66
+ top.add Text.new(1, 0, [-2500,0], 'w', 0, :w )
67
+ top.add Text.new(1, 0, [-2500,2500], 'nw', 0, :nw)
68
+
69
+ # Test different fonts
70
+ 0.upto(3) do |font|
71
+ top.add Text.new(1, 0, [0, -500*font-3000], "font#{font}", font)
72
+ end
73
+
74
+ # Create a via/contact structure
75
+ via = Structure.new('via')
76
+ via.create_time = time
77
+ via.modify_time = time
78
+
79
+ lib.add via
80
+ via.add Boundary.new(1, 0, [-500,-500, -500,500, 500,500, 500,-500, -500,-500])
81
+ via.add Boundary.new(2, 0, [-800,-800, -800,800, 800,800, 800,-800, -800,-800])
82
+ via.add Boundary.new(3, 0, [-600,-600, -600,600, 600,600, 600,-600, -600,-600])
83
+
84
+ # Create a transistor structure - use our via cell for gate and source/drain
85
+ # terminals
86
+ lib.add trans = Structure.new('trans')
87
+ trans.create_time = time
88
+ trans.modify_time = time
89
+
90
+ trans.add Boundary.new(1, 0, [-2500,-5000, -2500,5000, 2500,5000, 2500,-5000, -2500,-5000])
91
+ trans.add Path.new(4, 0, 0, 800, [0,-7000, 0,7000])
92
+ trans.add SRef.new('via', [-1700,0])
93
+ trans.add SRef.new('via', [1700,0])
94
+ trans.add SRef.new('via', [0,7000])
95
+
96
+ # Drop transistor cell down every 1.5u using different rotations and flip/x
97
+ x_offset = 0
98
+ [false, true].each do |reflect_x|
99
+ 0.step(270, 90) do |angle|
100
+ # Create an sref with the reflection and angle
101
+ SRef.new('trans', [x_offset, 12000]) do |sref|
102
+ sref.strans.reflect_x = reflect_x
103
+ sref.strans.angle = angle.to_f
104
+ top.add sref
105
+ end
106
+
107
+ # Add annotation text indicating reflection and angle
108
+ top.add Text.new(1, 0, [x_offset, 20000], "reflect_x=#{reflect_x}", 0, :c)
109
+ top.add Text.new(1, 0, [x_offset, 20500], "angle=#{angle.to_f.to_s}", 0, :c)
110
+
111
+ x_offset += 15000
112
+ end
113
+ end
114
+
115
+ # Write the library to file
116
+ lib.add top
117
+ lib.write(out_file)
data/test/hs_pthru.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'gdsii'
2
+ include Gdsii
3
+
4
+ in_file, out_file = ARGV
5
+ unless in_file and out_file
6
+ abort "
7
+ Uses the GDSII high-level *streamlined* methods to read in a GDSII file and
8
+ write out the contents in one pass. The resulting GDSII file should be
9
+ identical - or at least just have just EOF null-padding differences.
10
+
11
+ hs_pthru.rb <in-file> <out-file>
12
+
13
+ "
14
+ end
15
+
16
+ File.open(in_file, 'rb') do |inf|
17
+ File.open(out_file, 'wb') do |outf|
18
+ puts "Reading from #{in_file}..."
19
+ puts "Writing to #{out_file}..."
20
+ Library.read_header(inf) do |lib|
21
+ lib.write_header(outf) do
22
+ Structure.read_each_header(inf) do |struct|
23
+ struct.write_header(outf) do
24
+ Element.read_each(inf) {|element| element.write(outf)}
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
data/test/l_pthru.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'gdsii/record'
2
+ include Gdsii
3
+
4
+ in_file, out_file = ARGV
5
+ unless in_file and out_file
6
+ abort "
7
+ Uses the GDSII low-level methods to read in a GDSII file and then write out
8
+ the same GDSII file. The file should be identical - or at least just have
9
+ just EOF null-padding differences.
10
+
11
+ l_pthru.rb <in-file> <out-file>
12
+
13
+ "
14
+ end
15
+
16
+ File.open(in_file, 'rb') do |inf|
17
+ File.open(out_file, 'wb') do |outf|
18
+ while (rec = Record.read(inf))
19
+ rec.write(outf)
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,379 @@
1
+ #!/usr/bin/env ruby
2
+ require 'gdsii/boundary'
3
+ require 'gdsii/path'
4
+ require 'gdsii/strans'
5
+ require 'gdsii/text'
6
+ require 'gdsii/box'
7
+ require 'gdsii/node'
8
+ require 'gdsii/sref'
9
+ require 'gdsii/aref'
10
+ require 'gdsii/structure'
11
+ require 'gdsii/library'
12
+ require 'test/unit'
13
+
14
+
15
+ class GdsGroupTest < Test::Unit::TestCase
16
+
17
+ # This is just for Ruby In Steel bug
18
+ include Gdsii
19
+
20
+ # Test a property item
21
+ def test_property()
22
+ p = Property.new(1, 'test')
23
+ assert_equal 1, p.attr
24
+ assert_equal 'test', p.value
25
+ end
26
+
27
+ ############################################################################
28
+
29
+ # Test BOUNDARY items
30
+ def test_boundary()
31
+ b = Boundary.new(0, 1, [2,3])
32
+ assert_equal(0, b.layer)
33
+ assert_equal(1, b.datatype)
34
+ assert_equal([2,3], b.xy)
35
+
36
+ b.xy=[4,5]
37
+ b.layer = 10
38
+ b.datatype = 11
39
+ assert_equal(10, b.layer)
40
+ assert_equal(11, b.datatype)
41
+ assert_equal([4,5], b.xy)
42
+
43
+ # test setting/removing of properties
44
+ b.properties.add Property.new(0, 'test1')
45
+ b.properties.add Property.new(0, 'test2')
46
+ b.properties.add Property.new(1, 'test3')
47
+
48
+ assert_equal(3, b.properties.length)
49
+ assert_equal('test2', b.properties[1].value)
50
+
51
+ # test removing of properties
52
+ b.properties.remove {|p| p.attr == 0}
53
+ assert_equal(1, b.properties.length)
54
+ assert_equal('test3', b.properties[0].value)
55
+ end
56
+
57
+ ############################################################################
58
+
59
+ # Test Strans object
60
+ def test_strans(object=nil)
61
+ if object
62
+ #
63
+ # Test strans on an object
64
+ #
65
+ object.strans.abs_angle = true
66
+ object.strans.abs_mag = true
67
+ object.strans.reflect_x = true
68
+ object.strans.angle=50.0
69
+ object.strans.mag = 10.3
70
+ assert object.strans.abs_angle?
71
+ assert object.strans.abs_mag?
72
+ assert object.strans.reflect_x?
73
+ assert_equal(50.0, object.strans.angle)
74
+ assert_equal(10.3, object.strans.mag)
75
+ else
76
+ #
77
+ # stand alone test
78
+ #
79
+
80
+ s = Strans.new(2.2, 90.0)
81
+ assert_equal 2.2, s.mag
82
+ assert_equal 90.0, s.angle
83
+ assert_equal false, s.reflect_x?
84
+ assert_equal false, s.abs_mag?
85
+ assert_equal false, s.abs_angle?
86
+
87
+ # Tweak x-reflection
88
+ s.reflect_x = true
89
+ assert s.reflect_x?
90
+ s.reflect_x = false
91
+ assert_equal false, s.reflect_x?
92
+
93
+ # Tweak absolute magnification bit
94
+ s.abs_mag = true
95
+ assert s.abs_mag?
96
+ s.abs_mag = false
97
+ assert_equal false, s.abs_mag?
98
+
99
+ # Tweak absolute angle bit
100
+ s.abs_angle = true
101
+ assert s.abs_angle?
102
+ s.abs_angle = false
103
+ assert_equal false, s.abs_angle?
104
+ end
105
+ end
106
+
107
+ ############################################################################
108
+
109
+ # Test PATH items
110
+ def test_path()
111
+ # Create a new path; check properties
112
+ a = Path.new(5, 3, 0, 10, [1,2])
113
+ assert_equal([1,2], a.xy)
114
+ assert_equal(5, a.layer)
115
+ assert_equal(3, a.datatype)
116
+ assert_equal(10, a.width)
117
+ assert_equal(0, a.pathtype)
118
+ assert_equal(nil, a.bgnextn)
119
+ assert_equal(nil, a.endextn)
120
+
121
+ # Change layer, datatype, width, and path type; add begin/end extensions
122
+ # Also change xy coordinates
123
+ a.layer = 1
124
+ a.datatype = 0
125
+ a.width = 100
126
+ a.xy = [9,10]
127
+ a.pathtype = 4
128
+ a.bgnextn = 50
129
+ a.endextn = 25
130
+ assert_equal(1, a.layer)
131
+ assert_equal(0, a.datatype)
132
+ assert_equal(100, a.width)
133
+ assert_equal([9,10], a.xy)
134
+ assert_equal(4, a.pathtype)
135
+ assert_equal(50, a.bgnextn)
136
+ assert_equal(25, a.endextn)
137
+
138
+ # Try to set begin/end extensions for path type 0
139
+ a.pathtype = 0
140
+ assert_raise(TypeError) { a.bgnextn = 100 }
141
+ assert_raise(TypeError) { a.endextn = 100 }
142
+ assert_raise(TypeError) { a.pathtype = 3 }
143
+
144
+ # Create a path of type 4
145
+ b = Path.new4(2, 0, 100, 0, 50, [0,0, 2000,0, 2000,2000, 4000,2000])
146
+ assert_equal(4, b.pathtype)
147
+ assert_equal(0, b.bgnextn)
148
+ assert_equal(50, b.endextn)
149
+ end
150
+
151
+ ############################################################################
152
+
153
+ def test_text()
154
+ a = Text.new(1, 0, [0,0], 'test')
155
+ assert_equal(1, a.layer)
156
+ assert_equal(0, a.texttype)
157
+ assert_equal([0,0], a.xy)
158
+ assert_equal('test', a.string)
159
+
160
+ # Test font numbers
161
+ 0.upto(3) do |i|
162
+ a.font = i
163
+ assert_equal i, a.font
164
+ end
165
+ assert_raise(ArgumentError) { a.font = 4 }
166
+
167
+ # Test compass points
168
+ [:c, :n, :ne, :e, :se, :s, :sw, :w, :nw].each do |point|
169
+ a.origin = point
170
+ assert_equal point, a.origin
171
+ end
172
+ assert_raise(RuntimeError) { a.origin = :foo }
173
+ end
174
+
175
+ ############################################################################
176
+
177
+ # Test BOX items
178
+ def test_box()
179
+ a = Box.new(1, 0, [0,0, 0,10, 10,10, 10,0, 0,0])
180
+ assert_equal 1, a.layer
181
+ assert_equal 0, a.boxtype
182
+ assert_equal [0,0], a.xy[0,2]
183
+
184
+ a.layer = 5
185
+ a.boxtype = 3
186
+ assert_equal(5, a.layer)
187
+ assert_equal(3, a.boxtype)
188
+ end
189
+
190
+ ############################################################################
191
+
192
+ # Test NODE items
193
+ def test_node()
194
+ a = Node.new(1, 0, [0,0])
195
+ assert_equal 1, a.layer
196
+ assert_equal 0, a.nodetype
197
+ assert_equal [0,0], a.xy
198
+
199
+ a.layer = 5
200
+ a.nodetype = 3
201
+ assert_equal(5, a.layer)
202
+ assert_equal(3, a.nodetype)
203
+ end
204
+
205
+ ############################################################################
206
+
207
+ # Test SRef items
208
+ def test_sref()
209
+ a = SRef.new('TestCell', [1,2])
210
+ assert_equal("TestCell", a.sname)
211
+ assert_equal([1,2], a.xy)
212
+
213
+ a.sname = 'Test2'
214
+ a.xy = [8,9]
215
+ assert_equal('Test2', a.sname)
216
+ assert_equal([8,9], a.xy)
217
+
218
+ # run tests on strans of this object
219
+ test_strans(a)
220
+ end
221
+
222
+ ############################################################################
223
+
224
+ # Test AREF items
225
+ def test_aref()
226
+ # basic testing
227
+ a = ARef.new('TestCell', [0,0], [2,8], [200, 300])
228
+ assert_equal([0,0], a.ref_xy)
229
+ assert_equal(2, a.columns)
230
+ assert_equal(8, a.rows)
231
+ assert_equal(200, a.column_space)
232
+ assert_equal(300, a.row_space)
233
+ assert_equal([0,0, 400,0, 0,2400], a.xy)
234
+
235
+ # property change testing
236
+ a.ref_xy = [100, 100]
237
+ a.columns = 4
238
+ a.rows = 2
239
+ a.column_space = 50
240
+ a.row_space = 25
241
+ assert_equal([100,100], a.ref_xy)
242
+ assert_equal(4, a.columns)
243
+ assert_equal(2, a.rows)
244
+ assert_equal(50, a.column_space)
245
+ assert_equal(25, a.row_space)
246
+ assert_equal([100,100, 300,100, 100,150], a.xy)
247
+
248
+ # Test omission of required XY properties
249
+ b = ARef.new('Test2')
250
+ assert_nil b.ref_xy
251
+ assert_nil b.column_space
252
+ assert_nil b.row_space
253
+ assert_nil b.columns
254
+ assert_nil b.rows
255
+
256
+ assert_nil b.xy
257
+ b.ref_xy = [100, 100]
258
+ assert_nil b.xy
259
+ b.columns = 4
260
+ assert_nil b.xy
261
+ b.rows = 2
262
+ assert_nil b.xy
263
+ b.column_space = 50
264
+ assert_nil b.xy
265
+ b.row_space = 25
266
+ assert_equal([100,100, 300,100, 100,150], b.xy)
267
+
268
+ # run tests on strans of this object
269
+ test_strans(a)
270
+ end
271
+
272
+ ############################################################################
273
+
274
+ # Test Structure items
275
+ def test_structure()
276
+ a = Structure.new('MYNAME')
277
+ assert_equal("MYNAME", a.name)
278
+ assert (a.create_time and a.modify_time)
279
+ assert a.elements.empty?
280
+
281
+ # Change the name
282
+ a.name = 'NEWNAME'
283
+ assert_equal 'NEWNAME', a.name
284
+
285
+ # Set the time to an hour ahead
286
+ now = Time.new + 360
287
+ a.create_time = now
288
+ a.modify_time = now
289
+ assert_equal now, a.create_time
290
+ assert_equal now, a.modify_time
291
+
292
+ # Add some elements using the two different add methods
293
+ a.add Boundary.new(1, 0, [0,0, 0,10, 10,10, 10,0, 0,0])
294
+ a.elements.add Boundary.new(2, 0, [0,0, 0,10, 10,10, 10,0, 0,0])
295
+ assert_equal 2, a.elements.length
296
+ assert_equal 1, a.elements[0].layer
297
+
298
+ # Manipulate the strclass bitarray
299
+ a.strclass = 0x0002
300
+ assert_equal(0x0002, a.strclass)
301
+
302
+ # Try adding garbage
303
+ assert_raise(TypeError) { a.add 1234 }
304
+ end
305
+
306
+ ############################################################################
307
+
308
+
309
+ # Test library items
310
+ def test_library()
311
+ lib = Library.new('MYLIB')
312
+ assert_equal 'MYLIB', lib.name
313
+ assert_equal lib.units, DEF_LIB_UNITS
314
+ assert_equal lib.header, DEF_LIB_VERSION
315
+ assert_equal lib.version, DEF_LIB_VERSION
316
+ assert (lib.access_time and lib.modify_time)
317
+ assert lib.structures.empty?
318
+
319
+ # test defaults
320
+ assert_nil lib.fonts
321
+ assert_nil lib.format
322
+ assert_nil lib.generations
323
+ assert_nil lib.secur
324
+ assert_equal [], lib.mask
325
+ assert_nil lib.srfname
326
+
327
+ # test units
328
+ user = lib.user_units
329
+ db = lib.database_units
330
+ assert_equal [user, db], lib.units
331
+ assert_equal 1e-6, lib.m_units
332
+
333
+ # tweak then verify all values
334
+ lib.name = 'LIB2'
335
+ lib.version = 7
336
+ lib.units = [0.001, 2e-9]
337
+ lib.fonts = ["one","two/three", "four","five"]
338
+ lib.generations = 3
339
+ lib.dirsize = 30
340
+ lib.secur = [1,2,7]
341
+ lib.mask = ['0 2-5 6 ; 0-64']
342
+ lib.srfname = "test"
343
+ assert_equal('LIB2', lib.name)
344
+ assert_equal(7, lib.version)
345
+ assert_equal(7, lib.header)
346
+ assert_equal([0.001, 2e-9], lib.units)
347
+ assert_equal(2e-6, lib.m_units)
348
+ assert_equal(["one","two/three", "four","five"], lib.fonts)
349
+ assert_equal(3, lib.generations)
350
+ assert_equal(30, lib.dirsize)
351
+ assert_equal([1,2,7], lib.secur)
352
+ assert_equal(['0 2-5 6 ; 0-64'], lib.mask)
353
+ assert_equal("test", lib.srfname)
354
+
355
+ # mess with the format record
356
+ lib.format = 0
357
+ assert_equal(0, lib.format)
358
+ assert(lib.archive_format?)
359
+ lib.format = 1
360
+ assert_equal(1, lib.format)
361
+ assert(lib.filtered_format?)
362
+
363
+ # mess with the time
364
+ now = Time.new + 360
365
+ lib.access_time = now
366
+ lib.modify_time = now
367
+ assert_equal now, lib.access_time
368
+ assert_equal now, lib.modify_time
369
+
370
+ # test adding structures
371
+ lib.structures << Structure.new("first")
372
+ lib.structures.add(Structure.new("second"))
373
+ lib.add(Structure.new("third"))
374
+ assert_equal("first", lib.structures[0].name)
375
+ assert_equal("second", lib.structures[1].name)
376
+ assert_equal("third", lib.structures[2].name)
377
+ end
378
+
379
+ end