ruby-gdsii 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +20 -0
- data/README.txt +113 -0
- data/bin/rgds-debug +43 -0
- data/bin/rgds-dump +38 -0
- data/bin/rgds-join +98 -0
- data/bin/rgds-layers +53 -0
- data/bin/rgds-sremove +135 -0
- data/bin/rgds-ssplit +113 -0
- data/bin/rgds-stats +134 -0
- data/bin/rgds-structs +41 -0
- data/bin/rgds-tree +166 -0
- data/bin/rgds2rb +99 -0
- data/lib/gdsii.rb +137 -0
- data/lib/gdsii/aref.rb +243 -0
- data/lib/gdsii/bnf.rb +309 -0
- data/lib/gdsii/boundary.rb +53 -0
- data/lib/gdsii/box.rb +65 -0
- data/lib/gdsii/byte_order.rb +36 -0
- data/lib/gdsii/element.rb +172 -0
- data/lib/gdsii/group.rb +98 -0
- data/lib/gdsii/library.rb +518 -0
- data/lib/gdsii/mixins.rb +378 -0
- data/lib/gdsii/node.rb +65 -0
- data/lib/gdsii/path.rb +169 -0
- data/lib/gdsii/property.rb +108 -0
- data/lib/gdsii/record.rb +606 -0
- data/lib/gdsii/record/consts.rb +384 -0
- data/lib/gdsii/record/datatypes/ascii.rb +145 -0
- data/lib/gdsii/record/datatypes/bitarray.rb +101 -0
- data/lib/gdsii/record/datatypes/data.rb +111 -0
- data/lib/gdsii/record/datatypes/int2.rb +67 -0
- data/lib/gdsii/record/datatypes/int4.rb +65 -0
- data/lib/gdsii/record/datatypes/nodata.rb +60 -0
- data/lib/gdsii/record/datatypes/real4.rb +51 -0
- data/lib/gdsii/record/datatypes/real8.rb +120 -0
- data/lib/gdsii/sref.rb +61 -0
- data/lib/gdsii/strans.rb +133 -0
- data/lib/gdsii/structure.rb +352 -0
- data/lib/gdsii/text.rb +203 -0
- data/pkg/ruby-gdsii.gem +23 -0
- data/samples/hello.gds +0 -0
- data/samples/hello.out.rb +84 -0
- data/samples/hello.rb +94 -0
- data/test/baseline/dcp1.gds +0 -0
- data/test/baseline/h_write.gds +0 -0
- data/test/h_pthru.rb +22 -0
- data/test/h_write.rb +117 -0
- data/test/hs_pthru.rb +31 -0
- data/test/l_pthru.rb +23 -0
- data/test/test_gds_group.rb +379 -0
- data/test/test_gds_record.rb +99 -0
- metadata +118 -0
data/bin/rgds-ssplit
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
##############################################################################
|
3
|
+
#
|
4
|
+
# == gdsssplit.rb
|
5
|
+
#
|
6
|
+
# Splits a GDSII file into separate GDSII files. A separate GDSII file will
|
7
|
+
# be created for each structure in the original GDSII file and the new GDSII
|
8
|
+
# files will be named after their structure name. At this time there are
|
9
|
+
# NO sref or aref intelligence (i.e. no hierarchy dependency checking) - so
|
10
|
+
# only one structure will exist per file.
|
11
|
+
#
|
12
|
+
# === Author
|
13
|
+
#
|
14
|
+
# James D. Masters (james.d.masters@gmail.com)
|
15
|
+
#
|
16
|
+
# === History
|
17
|
+
#
|
18
|
+
# * 03/26/2007 (jdm): Initial version
|
19
|
+
#
|
20
|
+
##############################################################################
|
21
|
+
|
22
|
+
|
23
|
+
require 'getoptlong'
|
24
|
+
require 'gdsii'
|
25
|
+
include Gdsii
|
26
|
+
|
27
|
+
# Build usage message
|
28
|
+
usage = "
|
29
|
+
Splits a GDSII file into separate GDSII files. A separate GDSII file will
|
30
|
+
be created for each structure in the original GDSII file and the new GDSII
|
31
|
+
files will be named after their structure name. At this time there are
|
32
|
+
NO sref or aref intelligence (i.e. no hierarchy dependency checking) - so
|
33
|
+
only one structure will exist per file.
|
34
|
+
|
35
|
+
Usage: gdsssplit.rb [options] <gds-file> <output-dir>
|
36
|
+
|
37
|
+
Options:
|
38
|
+
|
39
|
+
-s, --structs Specify structure(s) in a space separated list to extract.
|
40
|
+
The default behavior is to extract all structures.
|
41
|
+
-f, --force Force overwritting of GDSII files in the output directory
|
42
|
+
if a file by the same name exists.
|
43
|
+
-e, --extension Specify the output file GDSII extension to use. Default
|
44
|
+
is 'gds'.
|
45
|
+
-h, --help Displays this usage message.
|
46
|
+
|
47
|
+
"
|
48
|
+
|
49
|
+
# Get command-line arguments
|
50
|
+
force = false
|
51
|
+
structs = []
|
52
|
+
ext = 'gds'
|
53
|
+
|
54
|
+
opts = GetoptLong.new(
|
55
|
+
['--structs', '-s', GetoptLong::OPTIONAL_ARGUMENT],
|
56
|
+
['--force', '-f', GetoptLong::OPTIONAL_ARGUMENT|GetoptLong::NO_ARGUMENT],
|
57
|
+
['--extension', '-e', GetoptLong::OPTIONAL_ARGUMENT|GetoptLong::NO_ARGUMENT],
|
58
|
+
['--help', '-h', GetoptLong::OPTIONAL_ARGUMENT|GetoptLong::NO_ARGUMENT]
|
59
|
+
)
|
60
|
+
|
61
|
+
opts.each do |option, argument|
|
62
|
+
case option
|
63
|
+
when '--help' : abort usage
|
64
|
+
when '--structs' : structs = argument.split(/\s+/)
|
65
|
+
when '--extension' : ext = argument
|
66
|
+
when '--force' : force = true
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Get GDSII file and output directory from command line
|
71
|
+
gds_file, output_dir = ARGV
|
72
|
+
unless gds_file and output_dir
|
73
|
+
abort usage
|
74
|
+
end
|
75
|
+
|
76
|
+
# Check that GDSII file is readable and that output dir is writable
|
77
|
+
unless File.readable? gds_file
|
78
|
+
abort "\nGDSII file does not exist or is not readable: #{gds_file}\n\n" + usage
|
79
|
+
end
|
80
|
+
|
81
|
+
# Check that output directory is writable
|
82
|
+
unless File.directory? output_dir and File.writable? output_dir
|
83
|
+
abort "\nOutput directory is not writable: #{output_dir}\n\n" + usage
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
# Read the GDSII file and write out resulting GDSII files
|
88
|
+
File.open(gds_file, 'rb') do |inf|
|
89
|
+
Library.read_header(inf) do |lib|
|
90
|
+
Structure.read_each_header(inf) do |struct|
|
91
|
+
if structs.empty? or structs.member?(struct.name)
|
92
|
+
# write lib & structure header to file
|
93
|
+
file_name = "#{output_dir}/#{struct.name}.#{ext}"
|
94
|
+
if File.exists? file_name and not force
|
95
|
+
warn "WARNING: #{file_name} already exists; use --force to override"
|
96
|
+
else
|
97
|
+
# open the file
|
98
|
+
File.open(file_name, 'wb') do |outf|
|
99
|
+
lib.write_header(outf)
|
100
|
+
struct.write_header(outf)
|
101
|
+
Element.read_each(inf) {|element| element.write(outf)}
|
102
|
+
struct.write_footer(outf)
|
103
|
+
lib.write_footer(outf)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
else
|
107
|
+
# structure not on list; skip to next
|
108
|
+
Structure.seek_next(inf)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
data/bin/rgds-stats
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
##############################################################################
|
3
|
+
#
|
4
|
+
# == gdsstats.rb
|
5
|
+
#
|
6
|
+
# Dumps statistical information from a GDSII file.
|
7
|
+
#
|
8
|
+
# === Author
|
9
|
+
#
|
10
|
+
# James D. Masters (james.d.masters@gmail.com)
|
11
|
+
#
|
12
|
+
# === History
|
13
|
+
#
|
14
|
+
# * 03/26/2007 (jdm): Initial version
|
15
|
+
#
|
16
|
+
##############################################################################
|
17
|
+
|
18
|
+
|
19
|
+
require 'getoptlong'
|
20
|
+
require 'gdsii/record.rb'
|
21
|
+
include Gdsii
|
22
|
+
|
23
|
+
# Build usage message
|
24
|
+
usage = "
|
25
|
+
Dumps statistical information from a GDSII file.
|
26
|
+
|
27
|
+
Usage: gdsssplit.rb [options] <gds-file>
|
28
|
+
|
29
|
+
Options:
|
30
|
+
|
31
|
+
-s, --structs Specify structure(s) in a space separated list to process.
|
32
|
+
The default behavior is to process all structures.
|
33
|
+
-h, --help Displays this usage message.
|
34
|
+
|
35
|
+
"
|
36
|
+
|
37
|
+
# Get command-line arguments
|
38
|
+
structs = []
|
39
|
+
|
40
|
+
opts = GetoptLong.new(
|
41
|
+
['--structs', '-s', GetoptLong::OPTIONAL_ARGUMENT],
|
42
|
+
['--help', '-h', GetoptLong::OPTIONAL_ARGUMENT|GetoptLong::NO_ARGUMENT]
|
43
|
+
)
|
44
|
+
|
45
|
+
opts.each do |option, argument|
|
46
|
+
case option
|
47
|
+
when '--help' : abort usage
|
48
|
+
when '--structs' : structs = argument.split(/\s+/)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Get GDSII file directory from command line
|
53
|
+
unless (gds_file = ARGV[0])
|
54
|
+
abort usage
|
55
|
+
end
|
56
|
+
|
57
|
+
# Read the GDSII file and write out resulting GDSII files
|
58
|
+
File.open(gds_file, 'rb') do |inf|
|
59
|
+
|
60
|
+
# Set statistics hashes:
|
61
|
+
# lib_stats = Hash.new {|h,k| h[k] = 0}
|
62
|
+
str_stats = Hash.new {|h,k| h[k] = Hash.new {|h2,k2| h2[k2] = 0}}
|
63
|
+
|
64
|
+
# Set parse flags
|
65
|
+
strname = nil
|
66
|
+
dt_cxt = nil
|
67
|
+
layer = nil
|
68
|
+
|
69
|
+
# Read each record in the GDSII file
|
70
|
+
Record.read_each(inf) do |record|
|
71
|
+
|
72
|
+
type = record.type
|
73
|
+
|
74
|
+
case type
|
75
|
+
when GRT_STRNAME
|
76
|
+
# New structure definition... print header
|
77
|
+
strname = record.data_value
|
78
|
+
if structs.empty? or structs.member?(strname)
|
79
|
+
puts
|
80
|
+
puts '#' * 78
|
81
|
+
puts
|
82
|
+
puts "STRUCTURE: #{strname}"
|
83
|
+
# lib_stats[type] += 1
|
84
|
+
end
|
85
|
+
when GRT_SREF, GRT_AREF
|
86
|
+
# increment count for sref, aref, text, node, box
|
87
|
+
str_stats[nil][type] += 1
|
88
|
+
when GRT_BOUNDARY
|
89
|
+
# set datatype context to BOUNDARY
|
90
|
+
dt_cxt = type
|
91
|
+
when GRT_PATH
|
92
|
+
# set datatype context to PATH
|
93
|
+
dt_cxt = type
|
94
|
+
when GRT_LAYER
|
95
|
+
# capture the layer number - record when context is reached
|
96
|
+
layer = record.data_value
|
97
|
+
when GRT_DATATYPE, GRT_TEXTTYPE, GRT_NODETYPE, GRT_BOXTYPE
|
98
|
+
# record the layer for the given layer context
|
99
|
+
datatype = record.data_value
|
100
|
+
rec_num = (dt_cxt) ? dt_cxt : type
|
101
|
+
str_stats[[layer, datatype]][rec_num] += 1
|
102
|
+
dt_cxt = nil
|
103
|
+
when GRT_ENDSTR
|
104
|
+
# end structure definition
|
105
|
+
if structs.empty? or structs.member?(strname)
|
106
|
+
puts
|
107
|
+
printf("SRefs: %-12d\n", str_stats[nil][GRT_SREF])
|
108
|
+
printf("ARefs: %-12d\n", str_stats[nil][GRT_AREF])
|
109
|
+
puts
|
110
|
+
puts "Layer Type # Bnd # Path # Text # Box # Node"
|
111
|
+
puts '-' * 78
|
112
|
+
|
113
|
+
# Show layer information
|
114
|
+
layers = str_stats.keys.compact.sort {|a, b| (a[0] <=> b[0]) <=> (a[1] <=> b[1])}
|
115
|
+
layers.each do |layer|
|
116
|
+
printf("%-6d %-6d %11d %11d %11d %11d %11d\n",
|
117
|
+
layer[0],
|
118
|
+
layer[1],
|
119
|
+
str_stats[layer][GRT_BOUNDARY],
|
120
|
+
str_stats[layer][GRT_PATH],
|
121
|
+
str_stats[layer][GRT_TEXTTYPE],
|
122
|
+
str_stats[layer][GRT_BOXTYPE],
|
123
|
+
str_stats[layer][GRT_NODETYPE]
|
124
|
+
)
|
125
|
+
end
|
126
|
+
puts
|
127
|
+
end
|
128
|
+
str_stats.delete_if {|key,value| true}
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
|
data/bin/rgds-structs
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
##############################################################################
|
3
|
+
#
|
4
|
+
# == gdsstructs.rb
|
5
|
+
#
|
6
|
+
#
|
7
|
+
# === Author
|
8
|
+
#
|
9
|
+
# James D. Masters (james.d.masters@gmail.com)
|
10
|
+
#
|
11
|
+
# === History
|
12
|
+
#
|
13
|
+
# * 03/26/2007 (jdm): Initial version
|
14
|
+
#
|
15
|
+
##############################################################################
|
16
|
+
|
17
|
+
|
18
|
+
require 'getoptlong'
|
19
|
+
require 'gdsii/record.rb'
|
20
|
+
include Gdsii
|
21
|
+
|
22
|
+
# Build usage message
|
23
|
+
if (file_name = ARGV[0]).nil? then
|
24
|
+
abort "
|
25
|
+
Dumps a of structure names defined in the GDSII file.
|
26
|
+
|
27
|
+
Usage: gdsstructs.rb <gds-file>
|
28
|
+
|
29
|
+
"
|
30
|
+
end
|
31
|
+
|
32
|
+
# Extract the structure names from the GDSII file
|
33
|
+
File.open(file_name, 'rb') do |file|
|
34
|
+
while (record = Record.read(file)) do
|
35
|
+
if record.is_strname?
|
36
|
+
puts record.data_value
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
data/bin/rgds-tree
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
##############################################################################
|
3
|
+
#
|
4
|
+
# == gdstree.rb
|
5
|
+
#
|
6
|
+
# Dumps a hierarchy tree of structures used within a given GDSII file.
|
7
|
+
#
|
8
|
+
# === Author
|
9
|
+
#
|
10
|
+
# James D. Masters (james.d.masters@gmail.com)
|
11
|
+
#
|
12
|
+
# === History
|
13
|
+
#
|
14
|
+
# * 03/27/2007 (jdm): Initial version
|
15
|
+
#
|
16
|
+
#
|
17
|
+
##############################################################################
|
18
|
+
|
19
|
+
|
20
|
+
require 'getoptlong'
|
21
|
+
require 'gdsii/record.rb'
|
22
|
+
include Gdsii
|
23
|
+
|
24
|
+
# Build usage message
|
25
|
+
usage = "
|
26
|
+
Dumps a hierarchy tree of structures used within a given GDSII file.
|
27
|
+
|
28
|
+
Usage: gdstree.rb [options] <gds-file>
|
29
|
+
|
30
|
+
Options:
|
31
|
+
|
32
|
+
-t, --top-structs Explicitly specify the top structure name(s) to use in
|
33
|
+
the tree. The default behavior is to identify the top
|
34
|
+
structure(s) in the hierarchy automatically.
|
35
|
+
-c, --inst-counts Include instantiation counts in the tree.
|
36
|
+
-b, --broken-refs Indicate how broken references are handled. Possible values
|
37
|
+
are 'annotate' or 'prune'. The default behavior is to
|
38
|
+
ignore broken references.
|
39
|
+
-d, --delimiter Set hierarchy delimiter (default is '/').
|
40
|
+
-h, --help Displays this usage message.
|
41
|
+
|
42
|
+
Examples:
|
43
|
+
|
44
|
+
ruby gdstree.rb design.gds
|
45
|
+
ruby gdstree.rb --delimiter . design.gds
|
46
|
+
ruby gdstree.rb --inst-counts design.gds
|
47
|
+
ruby gdstree.rb --top-structs 'mytop othertop' --broken-refs annotate
|
48
|
+
|
49
|
+
"
|
50
|
+
|
51
|
+
# Get command-line arguments
|
52
|
+
top_structs = []
|
53
|
+
show_inst_counts = false
|
54
|
+
broken_refs = nil
|
55
|
+
delimiter = '/'
|
56
|
+
|
57
|
+
opts = GetoptLong.new(
|
58
|
+
['--top-structs', '-t', GetoptLong::OPTIONAL_ARGUMENT],
|
59
|
+
['--inst-counts', '-c', GetoptLong::NO_ARGUMENT],
|
60
|
+
['--broken-refs', '-b', GetoptLong::OPTIONAL_ARGUMENT],
|
61
|
+
['--delimiter', '-d', GetoptLong::OPTIONAL_ARGUMENT],
|
62
|
+
['--help', '-h', GetoptLong::NO_ARGUMENT]
|
63
|
+
)
|
64
|
+
|
65
|
+
opts.each do |option, argument|
|
66
|
+
case option
|
67
|
+
when '--top-structs' : top_structs = argument.split(/\s+/)
|
68
|
+
when '--inst-counts' : show_inst_counts = argument
|
69
|
+
when '--broken-refs' : broken_refs = argument
|
70
|
+
when '--delimiter' : delimiter = argument
|
71
|
+
when '--help' : abort usage
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Get GDSII file directory from command line
|
76
|
+
unless (gds_file = ARGV[0])
|
77
|
+
abort usage
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
#
|
82
|
+
# Class to define a structure within the hierarchy
|
83
|
+
#
|
84
|
+
class HierStruct
|
85
|
+
# Make the attributes accessible
|
86
|
+
attr_accessor :name, :children
|
87
|
+
|
88
|
+
# Create a new HierStruct
|
89
|
+
def initialize(name, delimiter, inst_counts, broken_refs)
|
90
|
+
@name = name
|
91
|
+
@delimiter = delimiter
|
92
|
+
@inst_counts = inst_counts
|
93
|
+
@broken_refs = broken_refs.to_sym unless broken_refs.nil?
|
94
|
+
@children = Hash.new {|hash, key| hash[key] = 0}
|
95
|
+
end
|
96
|
+
|
97
|
+
# Display the hierarchy of this HierStruct
|
98
|
+
def puts(structs, prefix='', suffix='')
|
99
|
+
# build the hierarchy string then display it
|
100
|
+
string = prefix + @delimiter + @name + suffix
|
101
|
+
$stdout.puts string
|
102
|
+
|
103
|
+
# display the hierarchy for all children of this struct
|
104
|
+
@children.each_pair do |struct_name, num_placed|
|
105
|
+
|
106
|
+
cnt_suffix = (@inst_counts) ? "(#{num_placed})" : ''
|
107
|
+
|
108
|
+
if (struct = structs[struct_name])
|
109
|
+
# display the child's hierarchy
|
110
|
+
struct.puts(structs, string, cnt_suffix)
|
111
|
+
else
|
112
|
+
# broken reference; deal with appropriately
|
113
|
+
case @broken_refs
|
114
|
+
when :annotate : $stdout.puts string + '(MISSING)'
|
115
|
+
when :prune : nil
|
116
|
+
else
|
117
|
+
$stdout.puts string + @delimiter + struct_name + cnt_suffix
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
#
|
127
|
+
# Main code
|
128
|
+
#
|
129
|
+
|
130
|
+
# get the structure and instance placement from the gdsii file
|
131
|
+
structs = {}
|
132
|
+
has_parent = {}
|
133
|
+
File.open(gds_file, 'rb') do |file|
|
134
|
+
while (rec=Record.read(file)) do
|
135
|
+
if rec.is_strname?
|
136
|
+
# inside a structure definition
|
137
|
+
str = HierStruct.new(rec.data_value, delimiter, show_inst_counts, broken_refs)
|
138
|
+
structs[str.name] = str
|
139
|
+
has_parent[str.name] = false unless has_parent.has_key?(str.name)
|
140
|
+
elsif rec.is_sname?
|
141
|
+
# instance in this structure
|
142
|
+
ref_str = rec.data_value
|
143
|
+
str.children[ref_str] += 1
|
144
|
+
has_parent[ref_str] = true
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
# if the user provides a list of top structure names, then use that list;
|
151
|
+
# otherwise build our own.
|
152
|
+
if top_structs.empty?
|
153
|
+
top_structs = has_parent.delete_if {|key, value| value}.keys.sort
|
154
|
+
end
|
155
|
+
|
156
|
+
# Output hierarch(y/ies)...
|
157
|
+
unless top_structs.empty?
|
158
|
+
top_structs.each do |struct|
|
159
|
+
if structs.has_key?(struct)
|
160
|
+
structs[struct].puts(structs)
|
161
|
+
else
|
162
|
+
warn "WARNING: structure #{struct} not found"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|