origen_testers 0.8.7 → 0.8.8
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.
- checksums.yaml +4 -4
- data/config/boot.rb +1 -4
- data/config/version.rb +1 -1
- data/lib/origen_testers/igxl_based_tester/ultraflex.rb +17 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/ate_hardware.rb +1 -17
- data/lib/origen_testers/interface.rb +4 -4
- data/lib/origen_testers/program_generators.rb +1 -0
- data/lib/origen_testers/test/dut.rb +11 -0
- data/lib/origen_testers/test/interface.rb +503 -0
- data/program/flow_control.rb +6 -1
- data/program/prb1.rb +1 -1
- data/program/prb1_resources.rb +1 -1
- data/program/prb2.rb +1 -1
- data/program/test.rb +1 -1
- data/program/uflex_resources.rb +1 -1
- metadata +3 -7
- data/lib/origen_testers/test/j750_base_interface.rb +0 -145
- data/lib/origen_testers/test/j750_hpt_interface.rb +0 -8
- data/lib/origen_testers/test/j750_interface.rb +0 -8
- data/lib/origen_testers/test/ultraflex_interface.rb +0 -377
- data/lib/origen_testers/test/v93k_interface.rb +0 -97
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 998b72183aa2ba05c1b7c722f8d5a115a4b3183e
|
4
|
+
data.tar.gz: 170fdc986ae9fe25548971444613839179cbed50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37d879d8076ccb8d116b10b5d412198c5482f548a5be9f9dd24e22eaa89ecd642dd2e7dd71c2e59f366abc9334ed006b373cf4df3ee32dd751f72d19a26c07ef
|
7
|
+
data.tar.gz: 85388069884b1ac81087492cf44e57d18fdba487e05727783e52e8b35d79165ebf90e9dbdfc52fa1181075501c6c45793e9e13fbbc60f41fa075444a43397b27
|
data/config/boot.rb
CHANGED
@@ -7,9 +7,6 @@ require "origen_testers/test/block.rb"
|
|
7
7
|
require "origen_testers/test/dut2.rb"
|
8
8
|
require "origen_testers/test/nvm.rb"
|
9
9
|
|
10
|
-
require "origen_testers/test/
|
11
|
-
require "origen_testers/test/ultraflex_interface"
|
12
|
-
require "origen_testers/test/j750_hpt_interface"
|
13
|
-
require "origen_testers/test/v93k_interface"
|
10
|
+
require "origen_testers/test/interface"
|
14
11
|
require "origen_testers/test/basic_interface"
|
15
12
|
require "origen_testers/test/custom_test_interface"
|
data/config/version.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'origen_testers/igxl_based_tester/ultraflex/ate_hardware'
|
1
2
|
module OrigenTesters
|
2
3
|
module IGXLBasedTester
|
3
4
|
class UltraFLEX < Base
|
@@ -587,6 +588,22 @@ module OrigenTesters
|
|
587
588
|
end
|
588
589
|
end
|
589
590
|
alias_method :store!, :store_next_cycle
|
591
|
+
|
592
|
+
# ate_hardware stores "key" UltraFLEX hardware information needed for test program generation
|
593
|
+
# Instrument types available for ppmu: "HSD-M", "HSD-U", "HSD-4G", and "HSS-6G".
|
594
|
+
# Sample usage: $tester.ate_hardware("HSD-U").ppmu
|
595
|
+
# Instrument types available for supply: "VSM", "VSMx2", "VSMx4", "HexVS", "HexVSx2", "HexVSx4",
|
596
|
+
# "HexVSx6", "HexVS+x2", "HexVS+x4", "HexVS+x6", "HDVS1", "HDVS1x2", "HDVS1x4", "VHDVS",
|
597
|
+
# "VHDVS_HC", "VHDVSx2", "VHDVS_HCx2", "VHDVS_HCx4", "VHDVS_HCx8", "VHDVS+", "VHDVS_HC+",
|
598
|
+
# "VHDVS+x2", "VHDVS_HC+x2", "VHDVS_HC+x4", and "VHDVS_HC+x8".
|
599
|
+
# HDVS1 is also known as HDVS. VHDVS is also known as UVS256.
|
600
|
+
# x2 is Merged2, x4 is Merged4, x6 is Merged6. _HC is High-Current.
|
601
|
+
# + is High-Accuracy.
|
602
|
+
# Sample usage: $tester.ate_hardware("VSM").supply
|
603
|
+
# Sample usage: $tester.ate_hardware("HSD-M").ppmu
|
604
|
+
def ate_hardware(instrumentname = '')
|
605
|
+
@ate_hardware = ATEHardware.new(instrumentname)
|
606
|
+
end
|
590
607
|
end
|
591
608
|
end
|
592
609
|
UltraFLEX = IGXLBasedTester::UltraFLEX
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module OrigenTesters
|
2
2
|
module IGXLBasedTester
|
3
|
-
class UltraFLEX
|
3
|
+
class UltraFLEX < Base
|
4
4
|
class ATEHardware
|
5
5
|
attr_accessor :instrument
|
6
6
|
|
@@ -944,22 +944,6 @@ module OrigenTesters
|
|
944
944
|
end
|
945
945
|
end
|
946
946
|
end
|
947
|
-
|
948
|
-
# ate_hardware stores "key" UltraFLEX hardware information needed for test program generation
|
949
|
-
# Instrument types available for ppmu: "HSD-M", "HSD-U", "HSD-4G", and "HSS-6G".
|
950
|
-
# Sample usage: $tester.ate_hardware("HSD-U").ppmu
|
951
|
-
# Instrument types available for supply: "VSM", "VSMx2", "VSMx4", "HexVS", "HexVSx2", "HexVSx4",
|
952
|
-
# "HexVSx6", "HexVS+x2", "HexVS+x4", "HexVS+x6", "HDVS1", "HDVS1x2", "HDVS1x4", "VHDVS",
|
953
|
-
# "VHDVS_HC", "VHDVSx2", "VHDVS_HCx2", "VHDVS_HCx4", "VHDVS_HCx8", "VHDVS+", "VHDVS_HC+",
|
954
|
-
# "VHDVS+x2", "VHDVS_HC+x2", "VHDVS_HC+x4", and "VHDVS_HC+x8".
|
955
|
-
# HDVS1 is also known as HDVS. VHDVS is also known as UVS256.
|
956
|
-
# x2 is Merged2, x4 is Merged4, x6 is Merged6. _HC is High-Current.
|
957
|
-
# + is High-Accuracy.
|
958
|
-
# Sample usage: $tester.ate_hardware("VSM").supply
|
959
|
-
# Sample usage: $tester.ate_hardware("HSD-M").ppmu
|
960
|
-
def ate_hardware(instrumentname = '')
|
961
|
-
@ate_hardware = ATEHardware.new(instrumentname)
|
962
|
-
end
|
963
947
|
end
|
964
948
|
end
|
965
949
|
end
|
@@ -7,11 +7,11 @@ module OrigenTesters
|
|
7
7
|
|
8
8
|
included do
|
9
9
|
Origen.add_interface(self)
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
12
|
+
(ATP::AST::Builder::CONDITION_KEYS + [:group, :bin, :pass, :fail, :test, :log]).each do |method|
|
13
|
+
define_method method do |*args, &block|
|
14
|
+
flow.send(method, *args, &block)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -41,6 +41,17 @@ module OrigenTesters
|
|
41
41
|
@blocks = [Block.new(0, self), Block.new(1, self), Block.new(2, self)]
|
42
42
|
end
|
43
43
|
|
44
|
+
def on_create
|
45
|
+
if tester && tester.uflex?
|
46
|
+
tester.assign_dc_instr_pins([hv_supply_pin, lv_supply_pin])
|
47
|
+
tester.assign_digsrc_pins(digsrc_pins)
|
48
|
+
tester.apply_digsrc_settings(digsrc_settings)
|
49
|
+
tester.assign_digcap_pins(digcap_pins)
|
50
|
+
tester.apply_digcap_settings(digcap_settings)
|
51
|
+
tester.memory_test_en = true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
44
55
|
def startup(options)
|
45
56
|
$tester.set_timeset('tp0', 60)
|
46
57
|
end
|
@@ -0,0 +1,503 @@
|
|
1
|
+
module OrigenTesters
|
2
|
+
module Test
|
3
|
+
class Interface
|
4
|
+
include OrigenTesters::ProgramGenerators
|
5
|
+
|
6
|
+
# Options passed to Flow.create and Library.create will be passed in here, use as
|
7
|
+
# desired to configure your interface
|
8
|
+
def initialize(options = {})
|
9
|
+
end
|
10
|
+
|
11
|
+
# Test that the block form of flow control methods like this can
|
12
|
+
# be overridden by an interface
|
13
|
+
def if_job(*jobs)
|
14
|
+
jobs = jobs.flatten
|
15
|
+
jobs.delete(:prb9)
|
16
|
+
super
|
17
|
+
end
|
18
|
+
alias_method :if_jobs, :if_job
|
19
|
+
|
20
|
+
def log(msg)
|
21
|
+
if tester.j750? || tester.uflex?
|
22
|
+
flow.logprint(msg)
|
23
|
+
else
|
24
|
+
flow.log(msg)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def func(name, options = {})
|
29
|
+
options = {
|
30
|
+
duration: :static
|
31
|
+
}.merge(options)
|
32
|
+
|
33
|
+
if tester.j750? || tester.uflex?
|
34
|
+
block_loop(name, options) do |block, i, group|
|
35
|
+
ins = test_instances.functional(name)
|
36
|
+
ins.set_wait_flags(:a) if options[:duration] == :dynamic
|
37
|
+
ins.pin_levels = options.delete(:pin_levels) if options[:pin_levels]
|
38
|
+
if group
|
39
|
+
pname = "#{name}_b#{i}_pset"
|
40
|
+
patsets.add(pname, [{ pattern: "#{name}_b#{i}.PAT" },
|
41
|
+
{ pattern: 'nvm_global_subs.PAT', start_label: 'subr' }])
|
42
|
+
ins.pattern = pname
|
43
|
+
flow.test(group, options) if i == 0
|
44
|
+
else
|
45
|
+
pname = "#{name}_pset"
|
46
|
+
patsets.add(pname, [{ pattern: "#{name}.PAT" },
|
47
|
+
{ pattern: 'nvm_global_subs.PAT', start_label: 'subr' }])
|
48
|
+
ins.pattern = pname
|
49
|
+
if options[:cz_setup]
|
50
|
+
flow.cz(ins, options[:cz_setup], options)
|
51
|
+
else
|
52
|
+
flow.test(ins, options)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
elsif tester.v93k?
|
58
|
+
block_loop(name, options) do |block, i|
|
59
|
+
tm = test_methods.ac_tml.ac_test.functional_test
|
60
|
+
ts = test_suites.run(name, options)
|
61
|
+
ts.test_method = tm
|
62
|
+
ts.levels = options.delete(:pin_levels) if options[:pin_levels]
|
63
|
+
if block
|
64
|
+
ts.pattern = "#{name}_b#{i}"
|
65
|
+
else
|
66
|
+
ts.pattern = name.to_s
|
67
|
+
# if options[:cz_setup]
|
68
|
+
# flow.cz(ins, options[:cz_setup], options)
|
69
|
+
# else
|
70
|
+
# end
|
71
|
+
end
|
72
|
+
flow.test ts, options
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def block_loop(name, options)
|
78
|
+
if options[:by_block]
|
79
|
+
if tester.j750? || tester.uflex?
|
80
|
+
test_instances.group do |group|
|
81
|
+
group.name = name
|
82
|
+
$dut.blocks.each_with_index do |block, i|
|
83
|
+
yield block, i, group
|
84
|
+
end
|
85
|
+
end
|
86
|
+
elsif tester.v93k?
|
87
|
+
flow.group name, options do
|
88
|
+
$dut.blocks.each_with_index do |block, i|
|
89
|
+
yield block, i
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
else
|
94
|
+
yield
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def por(options = {})
|
99
|
+
options = {
|
100
|
+
instance_not_available: true
|
101
|
+
}.merge(options)
|
102
|
+
if tester.j750? || tester.uflex?
|
103
|
+
flow.test('por_ins', options)
|
104
|
+
else
|
105
|
+
func('por_ins', options)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def para(name, options = {})
|
110
|
+
options = {
|
111
|
+
high_voltage: false
|
112
|
+
}.merge(options)
|
113
|
+
|
114
|
+
if tester.j750?
|
115
|
+
if options.delete(:high_voltage)
|
116
|
+
ins = test_instances.bpmu(name)
|
117
|
+
else
|
118
|
+
ins = test_instances.ppmu(name)
|
119
|
+
end
|
120
|
+
ins.dc_category = 'NVM_PARA'
|
121
|
+
flow.test(ins, options)
|
122
|
+
patsets.add("#{name}_pset", pattern: "#{name}.PAT")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# OR 2 IDS together into 1 flag
|
127
|
+
def or_ids(options = {})
|
128
|
+
flow.or_flags(options[:id1], options[:id2], options)
|
129
|
+
end
|
130
|
+
|
131
|
+
def nop(options = {})
|
132
|
+
flow.nop options
|
133
|
+
end
|
134
|
+
|
135
|
+
def mto_memory(name, options = {})
|
136
|
+
options = {
|
137
|
+
duration: :static
|
138
|
+
}.merge(options)
|
139
|
+
|
140
|
+
if tester.j750?
|
141
|
+
block_loop(name, options) do |block, i, group|
|
142
|
+
ins = test_instances.mto_memory(name)
|
143
|
+
ins.set_wait_flags(:a) if options[:duration] == :dynamic
|
144
|
+
ins.pin_levels = options.delete(:pin_levels) if options[:pin_levels]
|
145
|
+
if group
|
146
|
+
pname = "#{name}_b#{i}_pset"
|
147
|
+
patsets.add(pname, [{ pattern: "#{name}_b#{i}.PAT" },
|
148
|
+
{ pattern: 'nvm_global_subs.PAT', start_label: 'subr' }])
|
149
|
+
ins.pattern = pname
|
150
|
+
flow.test(group, options) if i == 0
|
151
|
+
else
|
152
|
+
pname = "#{name}_pset"
|
153
|
+
patsets.add(pname, [{ pattern: "#{name}.PAT" },
|
154
|
+
{ pattern: 'nvm_global_subs.PAT', start_label: 'subr' }])
|
155
|
+
ins.pattern = pname
|
156
|
+
if options[:cz_setup]
|
157
|
+
flow.cz(ins, options[:cz_setup], options)
|
158
|
+
else
|
159
|
+
flow.test(ins, options)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def meas(name, options = {})
|
167
|
+
options = {
|
168
|
+
duration: :static
|
169
|
+
}.merge(options)
|
170
|
+
|
171
|
+
name = "meas_#{name}" unless name.to_s =~ /meas/
|
172
|
+
|
173
|
+
if tester.j750? || tester.uflex?
|
174
|
+
if tester.uflex?
|
175
|
+
ins = test_instances.functional(name)
|
176
|
+
ins.set_wait_flags(:a) if options[:duration] == :dynamic
|
177
|
+
ins.pin_levels = options.delete(:pin_levels) if options[:pin_levels]
|
178
|
+
ins.lo_limit = options[:lo_limit]
|
179
|
+
ins.hi_limit = options[:hi_limit]
|
180
|
+
ins.scale = options[:scale]
|
181
|
+
ins.units = options[:units]
|
182
|
+
ins.defer_limits = options[:defer_limits]
|
183
|
+
else
|
184
|
+
if options[:pins] == :hi_v
|
185
|
+
ins = test_instances.board_pmu(name)
|
186
|
+
elsif options[:pins] == :power
|
187
|
+
ins = test_instances.powersupply(name)
|
188
|
+
else
|
189
|
+
ins = test_instances.pin_pmu(name)
|
190
|
+
end
|
191
|
+
ins.set_wait_flags(:a) if options[:duration] == :dynamic
|
192
|
+
ins.pin_levels = options.delete(:pin_levels) if options[:pin_levels]
|
193
|
+
ins.lo_limit = options[:lo_limit]
|
194
|
+
ins.hi_limit = options[:hi_limit]
|
195
|
+
end
|
196
|
+
|
197
|
+
pname = "#{name}_pset"
|
198
|
+
patsets.add(pname, [{ pattern: "#{name}.PAT" },
|
199
|
+
{ pattern: 'nvm_global_subs.PAT', start_label: 'subr' }])
|
200
|
+
ins.pattern = pname
|
201
|
+
if options[:cz_setup]
|
202
|
+
flow.cz(ins, options[:cz_setup], options)
|
203
|
+
else
|
204
|
+
flow.test(ins, options)
|
205
|
+
end
|
206
|
+
|
207
|
+
elsif tester.v93k?
|
208
|
+
tm = test_methods.dc_tml.dc_test.general_pmu
|
209
|
+
ts = test_suites.run(name, options)
|
210
|
+
ts.test_method = tm
|
211
|
+
ts.levels = options.delete(:pin_levels) if options[:pin_levels]
|
212
|
+
ts.lo_limit = options[:lo_limit] if options[:lo_limit]
|
213
|
+
ts.hi_limit = options[:hi_limit] if options[:hi_limit]
|
214
|
+
ts.pattern = name.to_s
|
215
|
+
# if options[:cz_setup]
|
216
|
+
# flow.cz(ins, options[:cz_setup], options)
|
217
|
+
# else
|
218
|
+
# use_limit_params = [:lo_limit, :hi_limit, :scale, :units] # define options to strip for flow.test
|
219
|
+
# options_use_limit = options.dup # duplicate, as modifying options directly, even an assigned copy modifies original
|
220
|
+
# flow.test(ins, options.reject! { |k, _| use_limit_params.include? k }) # set up test skipping use-limit options
|
221
|
+
# flow.use_limit(name, options_use_limit) if options_use_limit[:hi_limit] || options_use_limit[:lo_limit] # Only use use-limit if limits present in flow
|
222
|
+
# end
|
223
|
+
flow.test ts, options
|
224
|
+
end
|
225
|
+
|
226
|
+
def group(name, options = {})
|
227
|
+
flow.group name, options do |group|
|
228
|
+
yield group
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
####################################################
|
233
|
+
####### UltraFLEX Pinmap Stuff ####################
|
234
|
+
####################################################
|
235
|
+
|
236
|
+
# Assign relevant pins for pinmap sheet generation
|
237
|
+
def pinmap(name, options = {})
|
238
|
+
pinmap = pinmaps("#{name}")
|
239
|
+
Origen.top_level.add_pin_group :JTAG, :tdi, :tdo, :tms
|
240
|
+
Origen.top_level.power_pin_groups.keys.each do |grp_key|
|
241
|
+
pinmap.add_power_pin(grp_key, type: 'Power', comment: "# #{grp_key}")
|
242
|
+
end
|
243
|
+
Origen.top_level.virtual_pins.keys.each do |util_pin|
|
244
|
+
upin = Origen.top_level.virtual_pins(util_pin)
|
245
|
+
case upin.type
|
246
|
+
when :virtual_pin
|
247
|
+
pinmap.add_utility_pin(upin.name, type: 'Utility', comment: "# #{util_pin}")
|
248
|
+
when :ate_ch
|
249
|
+
pinmap.add_utility_pin(upin.name, type: 'I/O', comment: "# #{util_pin}")
|
250
|
+
end
|
251
|
+
end
|
252
|
+
Origen.top_level.pin.keys.each do |pkey|
|
253
|
+
pinmap.add_pin(Origen.top_level.pin(pkey).name, type: 'I/O', comment: "# #{pkey}")
|
254
|
+
end
|
255
|
+
Origen.top_level.pin_groups.keys.sort.each do |gkey|
|
256
|
+
# Do not include pins that are aliased to themselves
|
257
|
+
Origen.top_level.pin(gkey).each do |pin|
|
258
|
+
pinmap.add_group_pin(gkey, Origen.top_level.pin(pin.id).name, type: 'I/O', comment: "# #{gkey}")
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
# Assign relevant edges in preparation for edgeset/timeset sheet generation
|
264
|
+
def edge(category, pin, options = {})
|
265
|
+
options = {
|
266
|
+
d_src: 'PAT', # source of the channel drive data (e.g. pattern, drive_hi, drive_lo, etc.)
|
267
|
+
d_fmt: 'NR', # drive data format (NR, RL, RH, etc.)
|
268
|
+
d0_edge: '', # time at which the input drive is turned on
|
269
|
+
d1_edge: '', # time of the initial data drive edge
|
270
|
+
d2_edge: '', # time of the return format data drive edge
|
271
|
+
d3_edge: '', # time at which the input drive is turned off
|
272
|
+
c_mode: 'Edge', # output compare mode
|
273
|
+
c1_edge: '', # time of the initial output compare edge
|
274
|
+
c2_edge: '', # time of the final output compare edge (window compare)
|
275
|
+
t_res: 'Machine', # timing resolution (possibly ATE-specific)
|
276
|
+
clk_per: '' # clock period equation - for use with MCG
|
277
|
+
}.merge(options)
|
278
|
+
|
279
|
+
@edge_collection = edges
|
280
|
+
@edge_collection.add(category, pin, options)
|
281
|
+
end
|
282
|
+
|
283
|
+
def edge_collection
|
284
|
+
@edge_collection
|
285
|
+
end
|
286
|
+
|
287
|
+
def edgeset(sheet_name, options = {})
|
288
|
+
options = {
|
289
|
+
edgeset: :es_default,
|
290
|
+
period: 'cycle', # tester cycle period
|
291
|
+
t_mode: 'Machine' # edgeset timing mode (possibly ATE-specific)
|
292
|
+
}.merge(options)
|
293
|
+
edgeset = options.delete(:edgeset)
|
294
|
+
pin = options.delete(:pin)
|
295
|
+
edge = options.delete(:edge)
|
296
|
+
|
297
|
+
@edgeset = edgesets(sheet_name, options)
|
298
|
+
@edgeset.add(edgeset, pin, edge, options)
|
299
|
+
collect_ac_specs(@edgeset.es[edgeset].spec_sheet, edge)
|
300
|
+
end
|
301
|
+
|
302
|
+
def timeset(sheet_name, options = {})
|
303
|
+
options = {
|
304
|
+
timeset: :default,
|
305
|
+
master_ts: :default
|
306
|
+
}.merge(options)
|
307
|
+
timeset = options.delete(:timeset)
|
308
|
+
pin = options.delete(:pin)
|
309
|
+
eset = options.delete(:eset)
|
310
|
+
|
311
|
+
@timeset = timesets(sheet_name, options)
|
312
|
+
@timeset.add(timeset, pin, eset, options)
|
313
|
+
end
|
314
|
+
|
315
|
+
def ac_specset(sheet_name, expression, options = {})
|
316
|
+
options = {
|
317
|
+
specset: :default,
|
318
|
+
nom: { typ: nil }
|
319
|
+
}.merge(options)
|
320
|
+
|
321
|
+
ss = ac_specsets(sheet_name)
|
322
|
+
add_ac_specs(ss, expression, options)
|
323
|
+
end
|
324
|
+
|
325
|
+
# Collects AC Spec object(s) from the given expression and adds them to the given Specset
|
326
|
+
def collect_ac_specs(ssname, edge, options = {})
|
327
|
+
options = {
|
328
|
+
nom: { typ: nil }
|
329
|
+
}.merge(options)
|
330
|
+
|
331
|
+
# Create a Specsets object from the UFlex program generator API
|
332
|
+
ss = ac_specsets(ssname.to_sym)
|
333
|
+
add_ac_specs(ss, edge.clk_per, options)
|
334
|
+
add_ac_specs(ss, edge.d0_edge, options)
|
335
|
+
add_ac_specs(ss, edge.d1_edge, options)
|
336
|
+
add_ac_specs(ss, edge.d2_edge, options)
|
337
|
+
add_ac_specs(ss, edge.d3_edge, options)
|
338
|
+
add_ac_specs(ss, edge.c1_edge, options)
|
339
|
+
add_ac_specs(ss, edge.c2_edge, options)
|
340
|
+
end
|
341
|
+
|
342
|
+
# Adds new AC Spec object(s) to the given Specset
|
343
|
+
def add_ac_specs(ss, expression, options = {})
|
344
|
+
options = {
|
345
|
+
specset: :default
|
346
|
+
}.merge(options)
|
347
|
+
|
348
|
+
return unless expression.is_a? String
|
349
|
+
# collect all variable names within the expression
|
350
|
+
vars = expression.scan(/[a-zA-Z][\w]+/).map(&:to_sym)
|
351
|
+
vars.each do |var|
|
352
|
+
next if var =~ /^(d0_edge|d1_edge|d2_edge|d3_edge|c1_edge|c2_edge)$/
|
353
|
+
# The substitutions below are used for backward compatibility
|
354
|
+
next if var =~ /^(d_on|d_data|d_ret|d_off|c_open|c_close)$/
|
355
|
+
next if var =~ /^(nS|uS|mS|S)$/i
|
356
|
+
next if ss.ac_specsets.key?(options[:specset]) && ss.ac_specsets[options[:specset]].include?(var)
|
357
|
+
|
358
|
+
ss.add(var, options)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
# Assign relevant power supply levels in preparation for levelset sheet generation
|
363
|
+
def pwr_level(category, options = {})
|
364
|
+
options = {
|
365
|
+
vmain: 1.8, # Main supply voltage
|
366
|
+
valt: 1.8, # Alternate supply voltage
|
367
|
+
ifold: 1, # Supply clamp current
|
368
|
+
delay: 0 # Supply power-up delay
|
369
|
+
}.merge(options)
|
370
|
+
|
371
|
+
@level_collection = levels
|
372
|
+
@level_collection.add_power_level(category, options)
|
373
|
+
end
|
374
|
+
|
375
|
+
# Assign relevant single-ended pin levels in preparation for levelset sheet generation
|
376
|
+
def pin_level_se(category, options = {})
|
377
|
+
options = {
|
378
|
+
vil: 0, # Input drive low
|
379
|
+
vih: 1.8, # Input drive high
|
380
|
+
vol: 1.0, # Output compare low
|
381
|
+
voh: 0.8, # Output compare high
|
382
|
+
vcl: -1, # Voltage clamp low
|
383
|
+
vch: 2.5, # Voltage clamp high
|
384
|
+
vt: 0.9, # Termination voltage
|
385
|
+
voutlotyp: 0, #
|
386
|
+
vouthityp: 0, #
|
387
|
+
dmode: 'Largeswing-VT' # Driver mode
|
388
|
+
}.merge(options)
|
389
|
+
|
390
|
+
@level_collection = levels
|
391
|
+
@level_collection.add_se_pin_level(category, options)
|
392
|
+
end
|
393
|
+
|
394
|
+
def level_collection
|
395
|
+
@level_collection
|
396
|
+
end
|
397
|
+
|
398
|
+
def levelset(sheet_name, options = {})
|
399
|
+
pin = options.delete(:pin)
|
400
|
+
level = options.delete(:level)
|
401
|
+
|
402
|
+
@levelset = levelsets(sheet_name)
|
403
|
+
@levelset.add(sheet_name, pin, level, options)
|
404
|
+
collect_dc_specs(@levelset.spec_sheet, level)
|
405
|
+
end
|
406
|
+
|
407
|
+
def dc_specset(sheet_name, expression, options = {})
|
408
|
+
options = {
|
409
|
+
min: { min: nil },
|
410
|
+
nom: { typ: nil },
|
411
|
+
max: { max: nil }
|
412
|
+
}.merge(options)
|
413
|
+
|
414
|
+
ss = dc_specsets(sheet_name.to_sym)
|
415
|
+
add_dc_specs(ss, expression, options)
|
416
|
+
end
|
417
|
+
|
418
|
+
# Collects DC Spec object(s) from the given expression and adds them to the given Specset
|
419
|
+
def collect_dc_specs(ssname, level, options = {})
|
420
|
+
options = {
|
421
|
+
nom: { typ: nil },
|
422
|
+
min: { min: nil },
|
423
|
+
max: { max: nil }
|
424
|
+
}.merge(options)
|
425
|
+
|
426
|
+
# Create a Specsets object from the UFlex program generator API
|
427
|
+
ss = dc_specsets(ssname.to_sym)
|
428
|
+
if level.respond_to?(:vmain)
|
429
|
+
add_dc_specs(ss, level.vmain, options)
|
430
|
+
add_dc_specs(ss, level.valt, options)
|
431
|
+
add_dc_specs(ss, level.ifold, options)
|
432
|
+
elsif level.respond_to?(:vil)
|
433
|
+
add_dc_specs(ss, level.vil, options)
|
434
|
+
add_dc_specs(ss, level.vih, options)
|
435
|
+
add_dc_specs(ss, level.vol, options)
|
436
|
+
add_dc_specs(ss, level.voh, options)
|
437
|
+
add_dc_specs(ss, level.vcl, options)
|
438
|
+
add_dc_specs(ss, level.vch, options)
|
439
|
+
add_dc_specs(ss, level.vt, options)
|
440
|
+
add_dc_specs(ss, level.voutlotyp, options)
|
441
|
+
add_dc_specs(ss, level.vouthityp, options)
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
# Adds new DC Spec object(s) to the given Specset
|
446
|
+
def add_dc_specs(ss, expression, options = {})
|
447
|
+
options = {
|
448
|
+
specset: :default
|
449
|
+
}.merge(options)
|
450
|
+
|
451
|
+
return unless expression.is_a? String
|
452
|
+
vars = expression.scan(/[a-zA-Z][\w]+/).map(&:to_sym)
|
453
|
+
vars.each do |var|
|
454
|
+
next if var =~ /^(nA|uA|mA|A|nV|uV|mV|V)$/i
|
455
|
+
|
456
|
+
ss.add(var, options)
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
def global_spec(var, options = {})
|
461
|
+
options = {
|
462
|
+
job: nil,
|
463
|
+
value: nil,
|
464
|
+
comment: nil
|
465
|
+
}.merge(options)
|
466
|
+
|
467
|
+
global_specs('SpecsGlobal').add(var, job: options[:job], value: options[:value], comment: options[:comment])
|
468
|
+
end
|
469
|
+
|
470
|
+
def job_def(jname, options = {})
|
471
|
+
options = {
|
472
|
+
pinmap: pinmap_sheets.map { |k, v| v.filename.gsub(/\.txt$/, '') },
|
473
|
+
instances: test_instance_sheets.map { |k, v| v.filename.gsub(/\.txt$/, '') },
|
474
|
+
flows: flow_sheets.map { |k, v| v.filename.gsub(/\.txt$/, '') },
|
475
|
+
ac_specs: ac_specset_sheets.map { |k, v| v.filename.gsub(/\.txt$/, '') },
|
476
|
+
dc_specs: dc_specset_sheets.map { |k, v| v.filename.gsub(/\.txt$/, '') },
|
477
|
+
patsets: patset_sheets.map { |k, v| v.filename.gsub(/\.txt$/, '') },
|
478
|
+
patgroups: patgroup_sheets.map { |k, v| v.filename.gsub(/\.txt$/, '') },
|
479
|
+
bintables: [],
|
480
|
+
cz: [],
|
481
|
+
test_procs: [],
|
482
|
+
mix_sig_timing: [],
|
483
|
+
wave_defs: [],
|
484
|
+
psets: [],
|
485
|
+
sigs_port_map: [],
|
486
|
+
fract_bus: [],
|
487
|
+
comment: nil
|
488
|
+
}.merge(options)
|
489
|
+
|
490
|
+
program_jobs('Jobs').add(jname, options)
|
491
|
+
end
|
492
|
+
|
493
|
+
def reference(reference, options = {})
|
494
|
+
options = {
|
495
|
+
comment: nil
|
496
|
+
}.merge(options)
|
497
|
+
|
498
|
+
references('Refs').add(reference, options)
|
499
|
+
end
|
500
|
+
end
|
501
|
+
end
|
502
|
+
end
|
503
|
+
end
|