ruby-gdsii 1.0.0

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 (52) hide show
  1. data/LICENSE.txt +20 -0
  2. data/README.txt +113 -0
  3. data/bin/rgds-debug +43 -0
  4. data/bin/rgds-dump +38 -0
  5. data/bin/rgds-join +98 -0
  6. data/bin/rgds-layers +53 -0
  7. data/bin/rgds-sremove +135 -0
  8. data/bin/rgds-ssplit +113 -0
  9. data/bin/rgds-stats +134 -0
  10. data/bin/rgds-structs +41 -0
  11. data/bin/rgds-tree +166 -0
  12. data/bin/rgds2rb +99 -0
  13. data/lib/gdsii.rb +137 -0
  14. data/lib/gdsii/aref.rb +243 -0
  15. data/lib/gdsii/bnf.rb +309 -0
  16. data/lib/gdsii/boundary.rb +53 -0
  17. data/lib/gdsii/box.rb +65 -0
  18. data/lib/gdsii/byte_order.rb +36 -0
  19. data/lib/gdsii/element.rb +172 -0
  20. data/lib/gdsii/group.rb +98 -0
  21. data/lib/gdsii/library.rb +518 -0
  22. data/lib/gdsii/mixins.rb +378 -0
  23. data/lib/gdsii/node.rb +65 -0
  24. data/lib/gdsii/path.rb +169 -0
  25. data/lib/gdsii/property.rb +108 -0
  26. data/lib/gdsii/record.rb +606 -0
  27. data/lib/gdsii/record/consts.rb +384 -0
  28. data/lib/gdsii/record/datatypes/ascii.rb +145 -0
  29. data/lib/gdsii/record/datatypes/bitarray.rb +101 -0
  30. data/lib/gdsii/record/datatypes/data.rb +111 -0
  31. data/lib/gdsii/record/datatypes/int2.rb +67 -0
  32. data/lib/gdsii/record/datatypes/int4.rb +65 -0
  33. data/lib/gdsii/record/datatypes/nodata.rb +60 -0
  34. data/lib/gdsii/record/datatypes/real4.rb +51 -0
  35. data/lib/gdsii/record/datatypes/real8.rb +120 -0
  36. data/lib/gdsii/sref.rb +61 -0
  37. data/lib/gdsii/strans.rb +133 -0
  38. data/lib/gdsii/structure.rb +352 -0
  39. data/lib/gdsii/text.rb +203 -0
  40. data/pkg/ruby-gdsii.gem +23 -0
  41. data/samples/hello.gds +0 -0
  42. data/samples/hello.out.rb +84 -0
  43. data/samples/hello.rb +94 -0
  44. data/test/baseline/dcp1.gds +0 -0
  45. data/test/baseline/h_write.gds +0 -0
  46. data/test/h_pthru.rb +22 -0
  47. data/test/h_write.rb +117 -0
  48. data/test/hs_pthru.rb +31 -0
  49. data/test/l_pthru.rb +23 -0
  50. data/test/test_gds_group.rb +379 -0
  51. data/test/test_gds_record.rb +99 -0
  52. metadata +118 -0
@@ -0,0 +1,203 @@
1
+ require 'gdsii/group'
2
+ require 'gdsii/strans'
3
+ require 'gdsii/element'
4
+
5
+ module Gdsii
6
+
7
+ #
8
+ # Represents a GDSII Text element. Most methods are from Element or from the
9
+ # various included Access module methods.
10
+ #
11
+ class Text < Element
12
+
13
+ # Include various record accessors
14
+ include Access::Layer
15
+ include Access::XY
16
+ include Access::PathType
17
+ include Access::Width
18
+ include Access::ELFlags
19
+ include Access::Plex
20
+ include Access::StransGroup
21
+
22
+ #
23
+ # Text BNF description:
24
+ #
25
+ # <text> ::= TEXT [ELFLAGS] [PLEX] LAYER TEXTTYPE [PRESENTATION]
26
+ # [PATHTYPE] [WIDTH] [<strans>] XY STRING
27
+ #
28
+ self.bnf_spec = BnfSpec.new(
29
+ BnfItem.new(GRT_TEXT),
30
+ BnfItem.new(GRT_ELFLAGS, true),
31
+ BnfItem.new(GRT_PLEX, true),
32
+ BnfItem.new(GRT_LAYER),
33
+ BnfItem.new(GRT_TEXTTYPE),
34
+ BnfItem.new(GRT_PRESENTATION, true),
35
+ BnfItem.new(GRT_PATHTYPE, true),
36
+ BnfItem.new(GRT_WIDTH, true),
37
+ BnfItem.new(Strans, true),
38
+ BnfItem.new(GRT_XY),
39
+ BnfItem.new(GRT_STRING),
40
+ BnfItem.new(Properties, true),
41
+ BnfItem.new(GRT_ENDEL)
42
+ )
43
+
44
+ #
45
+ # Create a simple hash to store compass points and their respective
46
+ # presentation values and vice-versa. This is used in manipulating
47
+ # and querying the text's PRESENTATION record.
48
+ #
49
+ @@pres_lookup = {
50
+ # * bits 0 and 1: x origin; 00 left, 01 center, 10 right
51
+ # * bits 2 and 3: y origin; 00 top, 01, center, 10 bottom
52
+ [0b0000, 0b0000] => :nw,
53
+ [0b0000, 0b0100] => :w,
54
+ [0b0000, 0b1000] => :sw,
55
+ [0b0001, 0b0000] => :n,
56
+ [0b0001, 0b0100] => :c,
57
+ [0b0001, 0b1000] => :s,
58
+ [0b0010, 0b0000] => :ne,
59
+ [0b0010, 0b0100] => :e,
60
+ [0b0010, 0b1000] => :se
61
+ }
62
+ @@pres_lookup.merge!(@@pres_lookup.invert)
63
+
64
+ #
65
+ # Create a text record grouping given a layer, text type, xy coordinate,
66
+ # and a string.
67
+ #
68
+ # text1 = Gdsii::Text.new(1, 0, [0,0], 'hello')
69
+ # text2 = Gdsii::Text.new(1, 0, [100, 0], 'world', 2, :ne)
70
+ #
71
+ def initialize(layer=nil, texttype=nil, xy=nil, string=nil, font=nil, origin=nil)
72
+ super()
73
+ @records[GRT_TEXT] = Record.new(GRT_TEXT)
74
+ self.layer = layer unless layer.nil?
75
+ self.texttype = texttype unless texttype.nil?
76
+ self.xy = xy unless xy.nil?
77
+ self.string = string unless string.nil?
78
+ self.font = font unless font.nil?
79
+ self.origin = origin unless origin.nil?
80
+ yield self if block_given?
81
+ end
82
+
83
+ #
84
+ # Get the texttype record (returns Record).
85
+ #
86
+ def texttype_record() @records.get(GRT_TEXTTYPE); end
87
+
88
+ #
89
+ # Get the texttype number (returns Fixnum).
90
+ #
91
+ def texttype() @records.get_data(GRT_TEXTTYPE); end
92
+
93
+ #
94
+ # Set the texttype number.
95
+ #
96
+ def texttype=(val) @records.set(GRT_TEXTTYPE, val); end
97
+
98
+ #
99
+ # Get the text string record (returns Record).
100
+ #
101
+ def string_record() @records.get(GRT_STRING); end
102
+
103
+ #
104
+ # Get the text string value (returns String).
105
+ #
106
+ def string() @records.get_data(GRT_STRING); end
107
+
108
+ #
109
+ # Set the text string value.
110
+ #
111
+ def string=(val) @records.set(GRT_STRING, val); end
112
+
113
+ #
114
+ # Get the presentation record (returns Record).
115
+ #
116
+ def presentation_record() @records.get(GRT_PRESENTATION); end
117
+
118
+ #
119
+ # Get the presentation bitarray number (returns Fixnum). It is probably
120
+ # easier to use #font and #origin instead.
121
+ #
122
+ def presentation() @records.get_data(GRT_PRESENTATION); end
123
+
124
+ #
125
+ # Set the presentation bitarray number. It is easier to not modify
126
+ # this number directly but to use #font= and #origin= instead.
127
+ #
128
+ # * bits 0 and 1: x origin; 00 left, 01 center, 10 right
129
+ # * bits 2 and 3: y origin; 00 top, 01, center, 10 bottom
130
+ # * bits 4 and 5: font number; 00 font 0, 01 font 1, 10 font 2, 11 font 3
131
+ # * All other bits are reserved
132
+ #
133
+ def presentation=(val)
134
+ @records.set(GRT_PRESENTATION, val);
135
+ end
136
+
137
+ #
138
+ # Specifies the font to use (valid range is 0-3). Calls #presentation=
139
+ # to change the font bits.
140
+ #
141
+ def font=(val)
142
+ if val >= 0 and val <= 3
143
+ # Be sure to clear out old value first...
144
+ # start at 4th bit; 2**4 == 16
145
+ pres = presentation || 0
146
+ self.presentation = (pres & 0xFFCF) | 16*val
147
+ else
148
+ raise ArgumentError, "Font value must be 0-3; given: #{val}"
149
+ end
150
+ end
151
+
152
+ #
153
+ # Returns the font number (Fixnum in range 0-3) according to the font bits
154
+ # in the #presentation record.
155
+ #
156
+ def font()
157
+ # clear all other bits then start at 4th bit; 2**4 == 16
158
+ pres = presentation || 0
159
+ (pres & 0x0030) / 16
160
+ end
161
+
162
+ #
163
+ # Returns the text origin as a symbol containing one of 9 possible
164
+ # values representing compass points:
165
+ #
166
+ # * :c == center (x == center; y == center)
167
+ # * :n == north (x == center; y == top)
168
+ # * :ne == northeast (x == right; y == top)
169
+ # * :e == east (x == right; y == center)
170
+ # * :se == southeast (x == right; y == bottom)
171
+ # * :s == south (x == center; y == bottom)
172
+ # * :sw == southwest (x == left; y == bottom)
173
+ # * :w == west (x == left; y == center)
174
+ # * :nw == northwest (x == left; y == top)
175
+ #
176
+ # The #presentation method is used to extract the bits related to the
177
+ # text origin.
178
+ #
179
+ def origin()
180
+ # origin bits: x == 0-1; y == 2-3
181
+ pres = presentation || 0
182
+ x_num = (pres & 0b0011)
183
+ y_num = (pres & 0b1100)
184
+ @@pres_lookup[[x_num, y_num]]
185
+ end
186
+
187
+ #
188
+ # Sets the text origin based upon one of 9 compass points (see
189
+ # #origin for the list). The #presentation= method is called to manipulate
190
+ # the presentation bits related to the text origin.
191
+ #
192
+ def origin=(point)
193
+ if nums = @@pres_lookup[point]
194
+ # clear origin bits then set to the new value
195
+ pres = presentation || 0
196
+ self.presentation = (pres & 0xFFF0) | nums[0] | nums[1]
197
+ else
198
+ raise "Compass point given: #{point.inspect} is not valid"
199
+ end
200
+ end
201
+
202
+ end
203
+ end
@@ -0,0 +1,23 @@
1
+ require 'rubygems'
2
+
3
+ SPEC = Gem::Specification.new do |s|
4
+ s.name = "ruby-gdsii"
5
+ s.version = "1.0.0"
6
+ s.author = "James Masters, Jim Freeze, et al"
7
+ s.email = "james.d.masters@intel.com"
8
+ s.homepage = "http://rubyforge.org/frs/?group_id=833"
9
+ s.platform = Gem::Platform::RUBY
10
+ #s.rubyforge_project = 'ruby-gdsii'
11
+ s.summary = "GDSII reader and writer with both high-level (easier to use) and low-level (faster performance) methods."
12
+ s.executables = %w(rgds-debug rgds-dump rgds-join rgds-layers rgds-sremove rgds-ssplit rgds-stats rgds-structs rgds-tree rgds2rb)
13
+ candidates = Dir.glob("{bin,lib,pkg,samples,test}/**/*")
14
+ s.files = candidates.delete_if do |item|
15
+ item.include?("CVS") || item.include?("rdoc")
16
+ end
17
+ #s.require_path = "lib"
18
+ s.test_files = ["test/test_gds_group.rb", "test/test_gds_record.rb"]
19
+ s.bindir = "bin"
20
+ s.has_rdoc = true
21
+ s.extra_rdoc_files = ["README.txt", "LICENSE.txt"]
22
+ end
23
+
Binary file
@@ -0,0 +1,84 @@
1
+ require 'gdsii'
2
+
3
+ File.open('hello.out', 'wb') do |outf|
4
+
5
+ Gdsii::Record.new(Gdsii::GRT_HEADER, 5).write(outf)
6
+ Gdsii::Record.new(Gdsii::GRT_BGNLIB, [108, 12, 4, 14, 51, 0, 108, 12, 4, 14, 51, 0]).write(outf)
7
+ Gdsii::Record.new(Gdsii::GRT_LIBNAME, "HELLO.DB").write(outf)
8
+ Gdsii::Record.new(Gdsii::GRT_UNITS, [0.001, 1.0e-09]).write(outf)
9
+
10
+ ############################################################################
11
+ # STRUCTURE: hello
12
+ ############################################################################
13
+
14
+ Gdsii::Record.new(Gdsii::GRT_BGNSTR, [108, 12, 4, 14, 51, 0, 108, 12, 4, 14, 51, 0]).write(outf)
15
+ Gdsii::Record.new(Gdsii::GRT_STRNAME, "hello").write(outf)
16
+
17
+ Gdsii::Record.new(Gdsii::GRT_BOUNDARY, nil).write(outf)
18
+ Gdsii::Record.new(Gdsii::GRT_LAYER, 1).write(outf)
19
+ Gdsii::Record.new(Gdsii::GRT_DATATYPE, 0).write(outf)
20
+ Gdsii::Record.new(Gdsii::GRT_XY, [0, 0, 0, 700, 100, 700, 100, 400, 300, 400, 300, 700, 400, 700, 400, 0, 300, 0, 300, 300, 100, 300, 100, 0, 0, 0]).write(outf)
21
+ Gdsii::Record.new(Gdsii::GRT_ENDEL, nil).write(outf)
22
+
23
+ Gdsii::Record.new(Gdsii::GRT_BOUNDARY, nil).write(outf)
24
+ Gdsii::Record.new(Gdsii::GRT_LAYER, 1).write(outf)
25
+ Gdsii::Record.new(Gdsii::GRT_DATATYPE, 0).write(outf)
26
+ Gdsii::Record.new(Gdsii::GRT_XY, [600, 0, 600, 700, 900, 700, 900, 600, 700, 600, 700, 400, 900, 400, 900, 300, 700, 300, 700, 100, 900, 100, 900, 0, 600, 0]).write(outf)
27
+ Gdsii::Record.new(Gdsii::GRT_ENDEL, nil).write(outf)
28
+
29
+ Gdsii::Record.new(Gdsii::GRT_BOUNDARY, nil).write(outf)
30
+ Gdsii::Record.new(Gdsii::GRT_LAYER, 1).write(outf)
31
+ Gdsii::Record.new(Gdsii::GRT_DATATYPE, 0).write(outf)
32
+ Gdsii::Record.new(Gdsii::GRT_XY, [1100, 0, 1100, 700, 1200, 700, 1200, 100, 1400, 100, 1400, 0, 1100, 0]).write(outf)
33
+ Gdsii::Record.new(Gdsii::GRT_ENDEL, nil).write(outf)
34
+
35
+ Gdsii::Record.new(Gdsii::GRT_BOUNDARY, nil).write(outf)
36
+ Gdsii::Record.new(Gdsii::GRT_LAYER, 1).write(outf)
37
+ Gdsii::Record.new(Gdsii::GRT_DATATYPE, 0).write(outf)
38
+ Gdsii::Record.new(Gdsii::GRT_XY, [1600, 0, 1600, 700, 1700, 700, 1700, 100, 1900, 100, 1900, 0, 1600, 0]).write(outf)
39
+ Gdsii::Record.new(Gdsii::GRT_ENDEL, nil).write(outf)
40
+
41
+ Gdsii::Record.new(Gdsii::GRT_BOUNDARY, nil).write(outf)
42
+ Gdsii::Record.new(Gdsii::GRT_LAYER, 1).write(outf)
43
+ Gdsii::Record.new(Gdsii::GRT_DATATYPE, 0).write(outf)
44
+ Gdsii::Record.new(Gdsii::GRT_XY, [2100, 200, 2100, 600, 2200, 700, 2500, 700, 2600, 600, 2600, 100, 2500, 0, 2200, 0, 2100, 100, 2100, 200, 2200, 200, 2300, 100, 2400, 100, 2500, 200, 2500, 500, 2400, 600, 2300, 600, 2200, 500, 2200, 200, 2100, 200]).write(outf)
45
+ Gdsii::Record.new(Gdsii::GRT_ENDEL, nil).write(outf)
46
+
47
+ Gdsii::Record.new(Gdsii::GRT_ENDSTR, nil).write(outf)
48
+
49
+ ############################################################################
50
+ # STRUCTURE: top
51
+ ############################################################################
52
+
53
+ Gdsii::Record.new(Gdsii::GRT_BGNSTR, [108, 12, 4, 14, 51, 0, 108, 12, 4, 14, 51, 0]).write(outf)
54
+ Gdsii::Record.new(Gdsii::GRT_STRNAME, "top").write(outf)
55
+ Gdsii::Record.new(Gdsii::GRT_SREF, nil).write(outf)
56
+ Gdsii::Record.new(Gdsii::GRT_SNAME, "hello").write(outf)
57
+ Gdsii::Record.new(Gdsii::GRT_STRANS, 0).write(outf)
58
+ Gdsii::Record.new(Gdsii::GRT_ANGLE, 0.0).write(outf)
59
+ Gdsii::Record.new(Gdsii::GRT_XY, [0, 0]).write(outf)
60
+ Gdsii::Record.new(Gdsii::GRT_ENDEL, nil).write(outf)
61
+ Gdsii::Record.new(Gdsii::GRT_SREF, nil).write(outf)
62
+ Gdsii::Record.new(Gdsii::GRT_SNAME, "hello").write(outf)
63
+ Gdsii::Record.new(Gdsii::GRT_STRANS, 0).write(outf)
64
+ Gdsii::Record.new(Gdsii::GRT_ANGLE, 90.0).write(outf)
65
+ Gdsii::Record.new(Gdsii::GRT_XY, [0, 0]).write(outf)
66
+ Gdsii::Record.new(Gdsii::GRT_ENDEL, nil).write(outf)
67
+ Gdsii::Record.new(Gdsii::GRT_SREF, nil).write(outf)
68
+ Gdsii::Record.new(Gdsii::GRT_SNAME, "hello").write(outf)
69
+ Gdsii::Record.new(Gdsii::GRT_STRANS, 0).write(outf)
70
+ Gdsii::Record.new(Gdsii::GRT_ANGLE, 180.0).write(outf)
71
+ Gdsii::Record.new(Gdsii::GRT_XY, [0, 0]).write(outf)
72
+ Gdsii::Record.new(Gdsii::GRT_ENDEL, nil).write(outf)
73
+ Gdsii::Record.new(Gdsii::GRT_SREF, nil).write(outf)
74
+ Gdsii::Record.new(Gdsii::GRT_SNAME, "hello").write(outf)
75
+ Gdsii::Record.new(Gdsii::GRT_STRANS, 0).write(outf)
76
+ Gdsii::Record.new(Gdsii::GRT_ANGLE, 270.0).write(outf)
77
+ Gdsii::Record.new(Gdsii::GRT_XY, [0, 0]).write(outf)
78
+ Gdsii::Record.new(Gdsii::GRT_ENDEL, nil).write(outf)
79
+
80
+ Gdsii::Record.new(Gdsii::GRT_ENDSTR, nil).write(outf)
81
+
82
+ Gdsii::Record.new(Gdsii::GRT_ENDLIB, nil).write(outf)
83
+
84
+ end
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env ruby
2
+ ##############################################################################
3
+ #
4
+ # == hello.rb
5
+ #
6
+ # A simple "Hello World" example of the high-level GDSII classes and method
7
+ # calls. This example will display the words "Hello" in a subcell of four
8
+ # different rotations about the (0,0) origin.
9
+ #
10
+ # === Author
11
+ #
12
+ # James D. Masters (james.d.masters@gmail.com)
13
+ #
14
+ # === History
15
+ #
16
+ # * 03/27/2007 (jdm): Initial version
17
+ #
18
+ #
19
+ ##############################################################################
20
+
21
+
22
+ require 'gdsii/record.rb'
23
+ include Gdsii
24
+
25
+
26
+
27
+ require 'gdsii'
28
+
29
+ include Gdsii
30
+
31
+ lib = Library.new('HELLO.DB')
32
+
33
+
34
+ ########################################
35
+ # Write "HELLO" in a structure on layer 1,0
36
+ ########################################
37
+
38
+ # create hello structure and add to GDSII library
39
+ hello = lib.add Structure.new('hello')
40
+
41
+ # "H"
42
+ hello.add(Boundary.new(1, 0, [ 0, 0, 0, 700,
43
+ 100, 700, 100, 400,
44
+ 300, 400, 300, 700,
45
+ 400, 700, 400, 0,
46
+ 300, 0, 300, 300,
47
+ 100, 300, 100, 0,
48
+ 0, 0 ]))
49
+
50
+ # "E"
51
+ hello.add(Boundary.new(1, 0, [ 600, 0, 600, 700,
52
+ 900, 700, 900, 600,
53
+ 700, 600, 700, 400,
54
+ 900, 400, 900, 300,
55
+ 700, 300, 700, 100,
56
+ 900, 100, 900, 0,
57
+ 600, 0 ]))
58
+
59
+ # "L"
60
+ hello.add(Boundary.new(1, 0, [1100, 0, 1100, 700,
61
+ 1200, 700, 1200, 100,
62
+ 1400, 100, 1400, 0,
63
+ 1100, 0 ]))
64
+
65
+ # "L"
66
+ hello.add(Boundary.new(1, 0, [1600, 0, 1600, 700,
67
+ 1700, 700, 1700, 100,
68
+ 1900, 100, 1900, 0,
69
+ 1600, 0 ]))
70
+
71
+ # "O"
72
+ hello.add(Boundary.new(1, 0, [2100, 200, 2100, 600,
73
+ 2200, 700, 2500, 700,
74
+ 2600, 600, 2600, 100,
75
+ 2500, 0, 2200, 0,
76
+ 2100, 100, 2100, 200,
77
+ 2200, 200, 2300, 100,
78
+ 2400, 100, 2500, 200,
79
+ 2500, 500, 2400, 600,
80
+ 2300, 600, 2200, 500,
81
+ 2200, 200, 2100, 200]))
82
+
83
+ # Create a top structure and add 4 instantiations of rotation for structure
84
+ # "hello"
85
+ top = lib.add Structure.new('top')
86
+
87
+ 0.step(270, 90) do |angle|
88
+ top.add SRef.new('hello', [0,0]).configure {|sref|
89
+ sref.strans.angle = angle.to_f
90
+ }
91
+ end
92
+
93
+ lib.write('hello.gds')
94
+
Binary file
Binary file
@@ -0,0 +1,22 @@
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 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
+ h_pthru.rb <in-file> <out-file>
12
+
13
+ "
14
+ end
15
+
16
+ File.open(in_file, 'rb') do |inf|
17
+ puts "Reading #{in_file}..."
18
+ lib = Library.read(inf)
19
+ puts "Writing #{out_file}..."
20
+ lib.write(out_file)
21
+ end
22
+
@@ -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)