Skip to content

Commit 8b4cf88

Browse files
committed
Enhancements to compare technology versions
Signed-off-by: Jeff Ng <[email protected]>
1 parent 867bc65 commit 8b4cf88

File tree

11 files changed

+631
-30
lines changed

11 files changed

+631
-30
lines changed

flow/scripts/klayout/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ Copy the following files into ~/.klayout/ruby
1717
- GenericLayerNameMapper.rb
1818
- KLayoutLayerMapGenerator.rb
1919
- KLayoutLayerPropertiesFileGenerator.rb
20+
- LEFViaData.rb
21+
- LEFNamedObject.rb
22+
- LEFVia.rb
23+
- LEFLayer.rb
2024

2125
Also make sure that you have the import_tf.rb file from [tf_import](https://github.com/klayoutmatthias/tf_import) copied there as well. If you follow the instructions at [Guide to Integrate a New Platform into the OpenROAD Flow](https://openroad-flow-scripts.readthedocs.io/en/latest/contrib/PlatformBringUp.html#klayout-properties-file), it will be installed in ~/.klayout/salt/tf_import. Just copy it over to ~/.klayout/ruby, so that the scripts can find it.
2226

flow/scripts/klayout/src/KLayoutTechFileGenerator.rb

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,16 @@ def add_via_connectivity(lef_file, sorted_layer_map)
7272
via_data = LEFViaData.new()
7373
via_data.read_file(lef_file)
7474
connectivity = @tech.component("connectivity")
75-
via_data.get_map().each do | via_name, layer_stack |
76-
lower_layer = layer_stack[0]
77-
via_layer = layer_stack[1]
78-
upper_layer = layer_stack[2]
75+
via_data.get_map().each do | via_name, via |
76+
layer_list = via.get_layer_list()
77+
lower_layer = layer_list[0]
78+
via_layer = layer_list[1]
79+
upper_layer = layer_list[2]
7980
connection = NetTracerConnectivity.new
8081
connection.name = via_name
81-
connection.connection(lower_layer, via_layer, upper_layer)
82+
connection.connection(lower_layer.get_layer().get_name(),
83+
via_layer.get_layer().get_name(),
84+
upper_layer.get_layer().get_name())
8285
connectivity.add(connection)
8386
end
8487
# add symbolic mappings based on layers having multiple mappings
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/env ruby
2+
3+
require 'digest'
4+
require_relative 'LEFNamedObject'
5+
6+
#
7+
# Class to store LEF layer data
8+
#
9+
class LEFLayer < LEFNamedObject
10+
#
11+
# Initializer
12+
#
13+
def initialize(name, num, type=nil)
14+
super(name)
15+
@num = num
16+
@type = type
17+
end
18+
19+
#
20+
# Sets the layer type
21+
#
22+
def set_type(layer_type)
23+
@type = layer_type
24+
end
25+
26+
#
27+
# Sets the layer number (order of layer in the tech LEF, which implies
28+
# layer stacking order
29+
#
30+
def get_number()
31+
return @num
32+
end
33+
34+
#
35+
# Returns the layer type
36+
#
37+
def get_type()
38+
return @type
39+
end
40+
41+
#
42+
# Writes the LEF statement snippet for the layer
43+
#
44+
def write_lef(out)
45+
layer_name = get_name()
46+
out.puts sprintf("LAYER %s", layer_name)
47+
out.puts sprintf(" TYPE %s ;", get_type())
48+
out.puts sprintf("END %s", layer_name)
49+
out.puts
50+
end
51+
52+
#
53+
# Returns the SHA256 for the layer
54+
#
55+
# Layer number is skipped since the layer number could be different between
56+
# tech LEF versions and we'd like to use this to compare across versions
57+
#
58+
def sha256()
59+
if get_type.nil?
60+
return Digest::SHA256.hexdigest(get_name())
61+
end
62+
return Digest::SHA256.hexdigest(get_name() + get_type())
63+
end
64+
end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env ruby
2+
3+
#
4+
# Class for a basic LEF named object
5+
#
6+
class LEFNamedObject
7+
#
8+
# Initializer
9+
#
10+
def initialize(name)
11+
@name = name
12+
end
13+
14+
#
15+
# Returns the name
16+
#
17+
def get_name()
18+
return @name
19+
end
20+
end

flow/scripts/klayout/src/LEFVia.rb

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#!/usr/bin/env ruby
2+
3+
require 'digest'
4+
require 'json'
5+
require_relative 'LEFNamedObject'
6+
7+
#
8+
# Class to store LEF via information
9+
#
10+
class LEFVia < LEFNamedObject
11+
#
12+
# Container class that store information about the and shapes that are part
13+
# of the via that exist on the specified layer. Only RECTs are supported.
14+
#
15+
class LEFViaLayer
16+
#
17+
# Initializer
18+
#
19+
# layer is a ref to a LEFLayer
20+
# shape_list is the list of shapes for the via on the specified layer
21+
#
22+
def initialize(layer)
23+
# make sure this is a LEFLayer
24+
if !layer.is_a?(LEFLayer)
25+
raise ArgumentError, sprintf("LEFViaLayer initialize expects LEFLayer, got %s", layer.class.name)
26+
end
27+
@layer = layer
28+
@shape_list = []
29+
end
30+
31+
#
32+
# Adds a shape to the shape list
33+
#
34+
def add_shape(shape)
35+
@shape_list << shape
36+
end
37+
38+
#
39+
# Returns the LEF layer for the shapes
40+
#
41+
def get_layer()
42+
return @layer
43+
end
44+
45+
#
46+
# Returns the shape list
47+
#
48+
def get_shape_list()
49+
return @shape_list
50+
end
51+
52+
#
53+
# Computes and returns the sha256 for the container
54+
#
55+
def sha256()
56+
layer_sha = get_layer().sha256()
57+
serialized_shapes = JSON.generate(get_shape_list)
58+
shape_list_sha = Digest::SHA256.hexdigest(serialized_shapes)
59+
return Digest::SHA256.hexdigest(layer_sha + shape_list_sha)
60+
end
61+
62+
#
63+
# Writes the LEF snippet for the container
64+
#
65+
def write_lef(outfh)
66+
outfh.puts sprintf(" LAYER %s ;", get_layer().get_name())
67+
get_shape_list.each do | rect |
68+
outfh.puts sprintf(" RECT %5.3f %5.3f %5.3f %5.3f ;", rect[0],
69+
rect[1], rect[2], rect[3])
70+
end
71+
end
72+
end
73+
74+
#
75+
# Initializer
76+
#
77+
# layer_list is a list of LEFViaLayers, which is unsorted. That way whoever
78+
# is creating the via can just add LEFViaLayers without regard for the
79+
# layer stacking order.
80+
#
81+
def initialize(name, is_default=false)
82+
super(name)
83+
@is_default = is_default
84+
85+
# List of LEFViaLayers - unsorted
86+
@layer_list = []
87+
end
88+
89+
#
90+
# Computes and returns the sha256 for the via
91+
#
92+
def sha256()
93+
layer_stack = get_layer_list()
94+
hashes = get_layer_list.map { |layer| layer.sha256 }
95+
concat_hashes = hashes.join
96+
return Digest::SHA256.hexdigest(concat_hashes)
97+
end
98+
99+
#
100+
# Returns the LEFViaLayer list for the via
101+
#
102+
# default is to sort the layers, by the layer number. That way it's returned
103+
# bottom layer to top layer
104+
#
105+
def get_layer_list(sorted=true)
106+
if sorted
107+
return @layer_list.sort_by { |layer| layer.get_layer().get_number }
108+
end
109+
return @layer_list
110+
end
111+
112+
#
113+
# Adds a layer to the layer list
114+
#
115+
def add_layer(layer)
116+
@layer_list << layer
117+
end
118+
119+
#
120+
# Writes the LEF snippet
121+
#
122+
def write_lef(outfh)
123+
via_name = get_name()
124+
if @is_default
125+
default_str = " DEFAULT"
126+
else
127+
default_str = ""
128+
end
129+
outfh.puts sprintf("VIA %s%s", via_name, default_str)
130+
get_layer_list().each do | layer |
131+
layer.write_lef(outfh)
132+
end
133+
outfh.puts sprintf("END %s", via_name)
134+
outfh.puts
135+
end
136+
end

0 commit comments

Comments
 (0)