origen_testers 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (199) hide show
  1. checksums.yaml +7 -0
  2. data/config/application.rb +140 -0
  3. data/config/commands.rb +73 -0
  4. data/config/development.rb +12 -0
  5. data/config/environment.rb +1 -0
  6. data/config/shared_commands.rb +47 -0
  7. data/config/users.rb +18 -0
  8. data/config/version.rb +8 -0
  9. data/lib/commands/build.rb +69 -0
  10. data/lib/origen_testers.rb +23 -0
  11. data/lib/origen_testers/api.rb +258 -0
  12. data/lib/origen_testers/basic_test_setups.rb +105 -0
  13. data/lib/origen_testers/callback_handlers.rb +58 -0
  14. data/lib/origen_testers/generator.rb +279 -0
  15. data/lib/origen_testers/generator/flow_control_api.rb +611 -0
  16. data/lib/origen_testers/generator/identity_map.rb +23 -0
  17. data/lib/origen_testers/generator/placeholder.rb +11 -0
  18. data/lib/origen_testers/generator/test_numberer.rb +23 -0
  19. data/lib/origen_testers/igxl_based_tester.rb +12 -0
  20. data/lib/origen_testers/igxl_based_tester/base.rb +641 -0
  21. data/lib/origen_testers/igxl_based_tester/base/flow.rb +171 -0
  22. data/lib/origen_testers/igxl_based_tester/base/flow_line.rb +322 -0
  23. data/lib/origen_testers/igxl_based_tester/base/generator.rb +217 -0
  24. data/lib/origen_testers/igxl_based_tester/base/patgroup.rb +109 -0
  25. data/lib/origen_testers/igxl_based_tester/base/patgroups.rb +38 -0
  26. data/lib/origen_testers/igxl_based_tester/base/patset.rb +68 -0
  27. data/lib/origen_testers/igxl_based_tester/base/patset_pattern.rb +56 -0
  28. data/lib/origen_testers/igxl_based_tester/base/patsets.rb +38 -0
  29. data/lib/origen_testers/igxl_based_tester/base/patsubr.rb +68 -0
  30. data/lib/origen_testers/igxl_based_tester/base/patsubr_pattern.rb +56 -0
  31. data/lib/origen_testers/igxl_based_tester/base/patsubrs.rb +38 -0
  32. data/lib/origen_testers/igxl_based_tester/base/test_instance.rb +326 -0
  33. data/lib/origen_testers/igxl_based_tester/base/test_instance_group.rb +58 -0
  34. data/lib/origen_testers/igxl_based_tester/base/test_instances.rb +179 -0
  35. data/lib/origen_testers/igxl_based_tester/files.rb +43 -0
  36. data/lib/origen_testers/igxl_based_tester/j750.rb +248 -0
  37. data/lib/origen_testers/igxl_based_tester/j750/flow.rb +10 -0
  38. data/lib/origen_testers/igxl_based_tester/j750/flow_line.rb +19 -0
  39. data/lib/origen_testers/igxl_based_tester/j750/generator.rb +19 -0
  40. data/lib/origen_testers/igxl_based_tester/j750/patgroup.rb +9 -0
  41. data/lib/origen_testers/igxl_based_tester/j750/patgroups.rb +10 -0
  42. data/lib/origen_testers/igxl_based_tester/j750/patset.rb +9 -0
  43. data/lib/origen_testers/igxl_based_tester/j750/patset_pattern.rb +18 -0
  44. data/lib/origen_testers/igxl_based_tester/j750/patsets.rb +10 -0
  45. data/lib/origen_testers/igxl_based_tester/j750/patsubr.rb +9 -0
  46. data/lib/origen_testers/igxl_based_tester/j750/patsubr_pattern.rb +18 -0
  47. data/lib/origen_testers/igxl_based_tester/j750/patsubrs.rb +10 -0
  48. data/lib/origen_testers/igxl_based_tester/j750/templates/flow.txt.erb +9 -0
  49. data/lib/origen_testers/igxl_based_tester/j750/templates/instances.txt.erb +16 -0
  50. data/lib/origen_testers/igxl_based_tester/j750/templates/patgroups.txt.erb +8 -0
  51. data/lib/origen_testers/igxl_based_tester/j750/templates/patsets.txt.erb +10 -0
  52. data/lib/origen_testers/igxl_based_tester/j750/templates/patsubrs.txt.erb +10 -0
  53. data/lib/origen_testers/igxl_based_tester/j750/test_instance.rb +547 -0
  54. data/lib/origen_testers/igxl_based_tester/j750/test_instance_group.rb +9 -0
  55. data/lib/origen_testers/igxl_based_tester/j750/test_instances.rb +10 -0
  56. data/lib/origen_testers/igxl_based_tester/j750_hpt.rb +34 -0
  57. data/lib/origen_testers/igxl_based_tester/j750_hpt/flow.rb +9 -0
  58. data/lib/origen_testers/igxl_based_tester/j750_hpt/flow_line.rb +9 -0
  59. data/lib/origen_testers/igxl_based_tester/j750_hpt/generator.rb +19 -0
  60. data/lib/origen_testers/igxl_based_tester/j750_hpt/patgroup.rb +9 -0
  61. data/lib/origen_testers/igxl_based_tester/j750_hpt/patgroups.rb +9 -0
  62. data/lib/origen_testers/igxl_based_tester/j750_hpt/patset.rb +9 -0
  63. data/lib/origen_testers/igxl_based_tester/j750_hpt/patset_pattern.rb +9 -0
  64. data/lib/origen_testers/igxl_based_tester/j750_hpt/patsets.rb +9 -0
  65. data/lib/origen_testers/igxl_based_tester/j750_hpt/patsubr.rb +9 -0
  66. data/lib/origen_testers/igxl_based_tester/j750_hpt/patsubr_pattern.rb +9 -0
  67. data/lib/origen_testers/igxl_based_tester/j750_hpt/patsubrs.rb +9 -0
  68. data/lib/origen_testers/igxl_based_tester/j750_hpt/test_instance.rb +515 -0
  69. data/lib/origen_testers/igxl_based_tester/j750_hpt/test_instance_group.rb +9 -0
  70. data/lib/origen_testers/igxl_based_tester/j750_hpt/test_instances.rb +9 -0
  71. data/lib/origen_testers/igxl_based_tester/parser.rb +102 -0
  72. data/lib/origen_testers/igxl_based_tester/parser/ac_spec.rb +9 -0
  73. data/lib/origen_testers/igxl_based_tester/parser/ac_specs.rb +0 -0
  74. data/lib/origen_testers/igxl_based_tester/parser/dc_spec.rb +33 -0
  75. data/lib/origen_testers/igxl_based_tester/parser/dc_specs.rb +48 -0
  76. data/lib/origen_testers/igxl_based_tester/parser/descriptions.rb +339 -0
  77. data/lib/origen_testers/igxl_based_tester/parser/flow.rb +109 -0
  78. data/lib/origen_testers/igxl_based_tester/parser/flow_line.rb +203 -0
  79. data/lib/origen_testers/igxl_based_tester/parser/flows.rb +21 -0
  80. data/lib/origen_testers/igxl_based_tester/parser/pattern_set.rb +92 -0
  81. data/lib/origen_testers/igxl_based_tester/parser/pattern_sets.rb +31 -0
  82. data/lib/origen_testers/igxl_based_tester/parser/test_instance.rb +341 -0
  83. data/lib/origen_testers/igxl_based_tester/parser/test_instances.rb +24 -0
  84. data/lib/origen_testers/igxl_based_tester/parser/timeset.rb +13 -0
  85. data/lib/origen_testers/igxl_based_tester/parser/timesets.rb +0 -0
  86. data/lib/origen_testers/igxl_based_tester/ultraflex.rb +477 -0
  87. data/lib/origen_testers/igxl_based_tester/ultraflex/flow.rb +10 -0
  88. data/lib/origen_testers/igxl_based_tester/ultraflex/flow_line.rb +19 -0
  89. data/lib/origen_testers/igxl_based_tester/ultraflex/generator.rb +19 -0
  90. data/lib/origen_testers/igxl_based_tester/ultraflex/patgroup.rb +9 -0
  91. data/lib/origen_testers/igxl_based_tester/ultraflex/patgroups.rb +10 -0
  92. data/lib/origen_testers/igxl_based_tester/ultraflex/patset.rb +9 -0
  93. data/lib/origen_testers/igxl_based_tester/ultraflex/patset_pattern.rb +18 -0
  94. data/lib/origen_testers/igxl_based_tester/ultraflex/patsets.rb +10 -0
  95. data/lib/origen_testers/igxl_based_tester/ultraflex/patsubr.rb +9 -0
  96. data/lib/origen_testers/igxl_based_tester/ultraflex/patsubr_pattern.rb +18 -0
  97. data/lib/origen_testers/igxl_based_tester/ultraflex/patsubrs.rb +10 -0
  98. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/flow.txt.erb +9 -0
  99. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/instances.txt.erb +16 -0
  100. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/patgroups.txt.erb +9 -0
  101. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/patsets.txt.erb +10 -0
  102. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/patsubrs.txt.erb +10 -0
  103. data/lib/origen_testers/igxl_based_tester/ultraflex/test_instance.rb +270 -0
  104. data/lib/origen_testers/igxl_based_tester/ultraflex/test_instance_group.rb +9 -0
  105. data/lib/origen_testers/igxl_based_tester/ultraflex/test_instances.rb +10 -0
  106. data/lib/origen_testers/interface.rb +183 -0
  107. data/lib/origen_testers/parser.rb +22 -0
  108. data/lib/origen_testers/parser/description_lookup.rb +62 -0
  109. data/lib/origen_testers/parser/searchable_array.rb +30 -0
  110. data/lib/origen_testers/parser/searchable_hash.rb +30 -0
  111. data/lib/origen_testers/pattern_compilers.rb +116 -0
  112. data/lib/origen_testers/pattern_compilers/assembler.rb +88 -0
  113. data/lib/origen_testers/pattern_compilers/job.rb +96 -0
  114. data/lib/origen_testers/pattern_compilers/ultraflex_pattern_compiler.rb +599 -0
  115. data/lib/origen_testers/program_generators.rb +55 -0
  116. data/lib/origen_testers/smartest_based_tester.rb +8 -0
  117. data/lib/origen_testers/smartest_based_tester/base.rb +411 -0
  118. data/lib/origen_testers/smartest_based_tester/base/flow.rb +188 -0
  119. data/lib/origen_testers/smartest_based_tester/base/flow_node.rb +476 -0
  120. data/lib/origen_testers/smartest_based_tester/base/generator.rb +123 -0
  121. data/lib/origen_testers/smartest_based_tester/base/pattern_compiler.rb +23 -0
  122. data/lib/origen_testers/smartest_based_tester/base/pattern_master.rb +47 -0
  123. data/lib/origen_testers/smartest_based_tester/base/test_method.rb +143 -0
  124. data/lib/origen_testers/smartest_based_tester/base/test_methods.rb +73 -0
  125. data/lib/origen_testers/smartest_based_tester/base/test_methods/ac_tml.rb +33 -0
  126. data/lib/origen_testers/smartest_based_tester/base/test_methods/base_tml.rb +38 -0
  127. data/lib/origen_testers/smartest_based_tester/base/test_methods/custom_tml.rb +19 -0
  128. data/lib/origen_testers/smartest_based_tester/base/test_methods/dc_tml.rb +147 -0
  129. data/lib/origen_testers/smartest_based_tester/base/test_methods/limits.rb +43 -0
  130. data/lib/origen_testers/smartest_based_tester/base/test_suite.rb +166 -0
  131. data/lib/origen_testers/smartest_based_tester/base/test_suites.rb +58 -0
  132. data/lib/origen_testers/smartest_based_tester/v93k.rb +8 -0
  133. data/lib/origen_testers/smartest_based_tester/v93k/builder.rb +89 -0
  134. data/lib/origen_testers/smartest_based_tester/v93k/builder/flow.rb +169 -0
  135. data/lib/origen_testers/smartest_based_tester/v93k/builder/pattern_master.rb +54 -0
  136. data/lib/origen_testers/smartest_based_tester/v93k/flow.rb +10 -0
  137. data/lib/origen_testers/smartest_based_tester/v93k/flow_node.rb +9 -0
  138. data/lib/origen_testers/smartest_based_tester/v93k/generator.rb +19 -0
  139. data/lib/origen_testers/smartest_based_tester/v93k/pattern_compiler.rb +10 -0
  140. data/lib/origen_testers/smartest_based_tester/v93k/pattern_master.rb +10 -0
  141. data/lib/origen_testers/smartest_based_tester/v93k/templates/template.aiv.erb +17 -0
  142. data/lib/origen_testers/smartest_based_tester/v93k/templates/template.flow.erb +201 -0
  143. data/lib/origen_testers/smartest_based_tester/v93k/templates/template.pmfl.erb +13 -0
  144. data/lib/origen_testers/smartest_based_tester/v93k/test_method.rb +9 -0
  145. data/lib/origen_testers/smartest_based_tester/v93k/test_methods.rb +9 -0
  146. data/lib/origen_testers/smartest_based_tester/v93k/test_suite.rb +9 -0
  147. data/lib/origen_testers/smartest_based_tester/v93k/test_suites.rb +9 -0
  148. data/lib/origen_testers/test/basic_interface.rb +17 -0
  149. data/lib/origen_testers/test/block.rb +21 -0
  150. data/lib/origen_testers/test/dut.rb +184 -0
  151. data/lib/origen_testers/test/dut2.rb +76 -0
  152. data/lib/origen_testers/test/j750_base_interface.rb +119 -0
  153. data/lib/origen_testers/test/j750_hpt_interface.rb +8 -0
  154. data/lib/origen_testers/test/j750_interface.rb +8 -0
  155. data/lib/origen_testers/test/nvm.rb +94 -0
  156. data/lib/origen_testers/test/ultraflex_interface.rb +110 -0
  157. data/lib/origen_testers/test/v93k_interface.rb +115 -0
  158. data/lib/origen_testers/timing.rb +362 -0
  159. data/lib/origen_testers/vector.rb +203 -0
  160. data/lib/origen_testers/vector_based_tester.rb +42 -0
  161. data/lib/origen_testers/vector_generator.rb +623 -0
  162. data/lib/origen_testers/vector_pipeline.rb +288 -0
  163. data/pattern/dc_instr.rb +7 -0
  164. data/pattern/delay.rb +7 -0
  165. data/pattern/mem_test.rb +8 -0
  166. data/pattern/multi_vector.rb +117 -0
  167. data/pattern/multi_vector_plus1.rb +125 -0
  168. data/pattern/nvm/j750/add_late_pins.rb +3 -0
  169. data/pattern/nvm/j750/iterator_postfix_test_x_bx.rb +8 -0
  170. data/pattern/nvm/j750/iterator_test_x_bx.rb +8 -0
  171. data/pattern/nvm/j750/j750_halt.rb +159 -0
  172. data/pattern/nvm/j750/j750_workout.rb +202 -0
  173. data/pattern/nvm/j750/timing.rb +73 -0
  174. data/pattern/nvm/v93k/v93k_workout.rb +136 -0
  175. data/pattern/read_write_reg.rb +58 -0
  176. data/pattern/reset.rb +4 -0
  177. data/pattern/subroutines.rb +38 -0
  178. data/program/_additional_erase.rb +7 -0
  179. data/program/_efa_resources.rb +7 -0
  180. data/program/_erase.rb +25 -0
  181. data/program/_erase_vfy.rb +5 -0
  182. data/program/_iv_resources.rb +10 -0
  183. data/program/basic_interface.rb +5 -0
  184. data/program/components/_prb2_main.rb +6 -0
  185. data/program/flow_control.rb +164 -0
  186. data/program/prb1.rb +226 -0
  187. data/program/prb1_resources.rb +28 -0
  188. data/program/prb2.rb +40 -0
  189. data/program/test.rb +20 -0
  190. data/templates/example.txt.erb +53 -0
  191. data/templates/j750/_vt_flow.txt.erb +8 -0
  192. data/templates/j750/_vt_instances.txt.erb +4 -0
  193. data/templates/j750/program_sheet.txt.erb +9 -0
  194. data/templates/manifest/v93k.yaml.erb +22 -0
  195. data/templates/web/index.md.erb +51 -0
  196. data/templates/web/layouts/_basic.html.erb +15 -0
  197. data/templates/web/partials/_navbar.html.erb +22 -0
  198. data/templates/web/release_notes.md.erb +5 -0
  199. metadata +332 -0
@@ -0,0 +1,203 @@
1
+ module OrigenTesters
2
+ # A simple class to model a vector
3
+ class Vector
4
+ attr_accessor :repeat, :microcode, :timeset, :pin_vals,
5
+ :number, :cycle_number, :dont_compress,
6
+ :comments, :inline_comment, :cycle, :number
7
+
8
+ def initialize(attrs = {})
9
+ @inline_comment = ''
10
+ attrs.each do |attribute, value|
11
+ send("#{attribute}=", value)
12
+ end
13
+ end
14
+
15
+ def comments
16
+ @comments ||= []
17
+ end
18
+
19
+ def update(attrs = {})
20
+ attrs.each do |attribute, value|
21
+ send("#{attribute}=", value)
22
+ end
23
+ end
24
+
25
+ # Returns the value (a string) that is assigned to the given pin by the
26
+ # given vector
27
+ #
28
+ # vector.pin_vals # => "1 1 XX10 H X1"
29
+ # vector.pin_value($dut.pins(:jtag)) # => "XX10"
30
+ def pin_value(pin)
31
+ $tester.regex_for_pin(pin).match(pin_vals)
32
+ Regexp.last_match(1)
33
+ end
34
+
35
+ # Replace the current pin value assigned to the given pin with either the state
36
+ # that it currently has, or with a supplied string value.
37
+ #
38
+ # In the case of a string being supplied as the 2nd argument, the caller is
39
+ # responsible for ensuring that the pin state format/codes matches that used
40
+ # by the current tester.
41
+ #
42
+ # vector.pin_vals # => "1 1 XX10 H X1"
43
+ # $dut.pins(:jtag).drive(0)
44
+ # vector.set_pin_value($dut.pins(:jtag))
45
+ # vector.pin_vals # => "1 1 0000 H X1"
46
+ # vector.set_pin_value($dut.pins(:jtag), "XXXX")
47
+ # vector.pin_vals # => "1 1 XXXX H X1"
48
+ def set_pin_value(pin, value = nil)
49
+ regex = $tester.regex_for_pin_sub(pin)
50
+ value ||= pin.to_vector
51
+ if $tester.ordered_pins_cache.first == pin
52
+ self.pin_vals = pin_vals.sub(regex, value + '\2')
53
+ elsif $tester.ordered_pins_cache.last == pin
54
+ self.pin_vals = pin_vals.sub(regex, '\1' + value)
55
+ else
56
+ self.pin_vals = pin_vals.sub(regex, '\1' + value + '\3')
57
+ end
58
+ end
59
+
60
+ # Converts the vector to the period specified by the given timeset (instead of the period
61
+ # for the timeset it was originally created with).
62
+ #
63
+ # This may convert the single vector to multiple vectors, in which case the method will
64
+ # yield as many vectors as required back to the caller.
65
+ def convert_to_timeset(tset)
66
+ # If no conversion required
67
+ if tset.period_in_ns == timeset.period_in_ns
68
+ yield self
69
+ else
70
+ if tset.period_in_ns > timeset.period_in_ns
71
+ fail "Cannot convert a vector with timeset #{timeset.name} to timeset #{tset.name}!"
72
+ end
73
+ if timeset.period_in_ns % tset.period_in_ns != 0
74
+ fail "The period of timeset #{timeset.name} is not a multiple of the period of timeset #{tset.name}!"
75
+ end
76
+ if $tester.timing_toggled_pins.empty?
77
+ vector_modification_required = false
78
+ else
79
+ # If the timing toggled pins are not driving on this vector, then no
80
+ # modification will be required
81
+ vector_modification_required = $tester.timing_toggled_pins.any? do |pin|
82
+ value = pin_value(pin)
83
+ value == '1' || value == '0'
84
+ end
85
+ end
86
+ number_of_base_vectors = repeat || 1
87
+ vectors_per_period = timeset.period_in_ns / tset.period_in_ns
88
+ self.inline_comment += "Period levelled (#{timeset.name})"
89
+ self.timeset = tset
90
+ if vector_modification_required && vectors_per_period > 1
91
+ pin_values = $tester.timing_toggled_pins.map do |pin|
92
+ on = pin_value(pin)
93
+ if on == '1'
94
+ { pin: pin, on: '1', off: '0' }
95
+ elsif on == '0'
96
+ { pin: pin, on: '0', off: '1' }
97
+ end
98
+ end
99
+ pin_vals_with_compare = nil
100
+ number_of_base_vectors.times do |i|
101
+ # Drive the 'on' value on the first cycle, this is already setup
102
+ v = dup
103
+ v.repeat = 1
104
+ v.pin_vals = inhibit_compares
105
+ yield v
106
+ # Then drive the pin 'off' value for the remainder
107
+ v = dup
108
+ r = vectors_per_period - 1
109
+ if r > 1
110
+ v = dup
111
+ v.repeat = r - 1
112
+ pin_values.each { |vals| v.set_pin_value(vals[:pin], vals[:off]) if vals }
113
+ yield v
114
+ end
115
+ v = dup
116
+ v.repeat = 1
117
+ v.pin_vals = restore_compares
118
+ pin_values.each { |vals| v.set_pin_value(vals[:pin], vals[:off]) if vals }
119
+ yield v
120
+ end
121
+ else
122
+ self.repeat = number_of_base_vectors * vectors_per_period
123
+ yield self
124
+ end
125
+ end
126
+ end
127
+
128
+ # Set all active compare data to X.
129
+ # The original values will be preserved so that they can be restored
130
+ # vector.pin_vals # => "1 1 LHLL 10001 L 1 XX 0"
131
+ # vector.inhibit_compares # => "1 1 XXXX 10001 X 1 XX 0"
132
+ # vector.restore_compares # => "1 1 LHLL 10001 L 1 XX 0"
133
+ def inhibit_compares
134
+ @orig_pin_vals = pin_vals
135
+ @pin_vals = pin_vals.gsub(/H|L/, 'X')
136
+ end
137
+
138
+ # @see Vector#inhibit_compares
139
+ def restore_compares
140
+ @pin_vals = @orig_pin_vals
141
+ end
142
+
143
+ # Updates the pin values to reflect the value currently held by the given pin
144
+ def update_pin_val(pin)
145
+ vals = pin_vals.split(' ')
146
+ if pin.belongs_to_a_pin_group? && !pin.is_a?(Origen::Pins::PinCollection)
147
+ port = nil
148
+ pin.groups.each { |i| port = i[1] if port.nil? && Origen.tester.ordered_pins.include?(i[1]) } # see if group is included in ordered pins
149
+ if port
150
+ ix = Origen.tester.ordered_pins.index(port) # find index of port
151
+ i = port.index(pin)
152
+ else
153
+ ix = Origen.tester.ordered_pins.index(pin)
154
+ i = 0
155
+ end
156
+ else
157
+ ix = Origen.tester.ordered_pins.index(pin)
158
+ i = 0
159
+ end
160
+
161
+ if Origen.pin_bank.pin_groups.keys.include? pin.id
162
+ val = pin.map { |p| Origen.tester.format_pin_state(p) }.join('')
163
+ vals[ix] = val
164
+ else
165
+ val = Origen.tester.format_pin_state(pin)
166
+ vals[ix][i] = val
167
+ end
168
+
169
+ self.pin_vals = vals.join(' ')
170
+ end
171
+
172
+ def ordered_pins
173
+ Origen.app.pin_map.sort_by { |id, pin| pin.order }.map { |id, pin| pin }
174
+ end
175
+
176
+ def microcode=(val)
177
+ if val && has_microcode? && @microcode != val
178
+ fail "Trying to assign microcode: #{val}, but vector already has microcode: #{@microcode}"
179
+ else
180
+ @microcode = val
181
+ end
182
+ end
183
+
184
+ # Since repeat 0 is non-intuitive every vector implicitly has a repeat of 1
185
+ def repeat
186
+ @repeat || 1
187
+ end
188
+
189
+ def has_microcode?
190
+ !!(@microcode && !@microcode.empty?)
191
+ end
192
+
193
+ def ==(obj)
194
+ if obj.is_a?(Vector)
195
+ self.has_microcode? == obj.has_microcode? &&
196
+ timeset == obj.timeset &&
197
+ pin_vals == obj.pin_vals
198
+ else
199
+ super obj
200
+ end
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,42 @@
1
+ require 'active_support/concern'
2
+ module OrigenTesters
3
+ # Including this module in a class gives it all the basics required
4
+ # to generator vector-based test patterns
5
+ module VectorBasedTester
6
+ extend ActiveSupport::Concern
7
+
8
+ require 'origen_testers/vector_generator'
9
+ require 'origen_testers/timing'
10
+ require 'origen_testers/api'
11
+
12
+ include VectorGenerator
13
+ include Timing
14
+ include API
15
+
16
+ included do
17
+ end
18
+
19
+ module ClassMethods # :nodoc:
20
+ # This overrides the new method of any class which includes this
21
+ # module to force the newly created instance to be registered as
22
+ # a tester with Origen
23
+ def new(*args, &block) # :nodoc:
24
+ if Origen.app.with_doc_tester?
25
+ x = Origen::Tester::Doc.allocate
26
+ if Origen.app.with_html_doc_tester?
27
+ x.html_mode = true
28
+ end
29
+ else
30
+ x = allocate
31
+ end
32
+ x.send(:initialize, *args, &block)
33
+ x.register_tester
34
+ x
35
+ end
36
+ end
37
+
38
+ def register_tester # :nodoc:
39
+ Origen.app.tester = self
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,623 @@
1
+ require 'active_support/concern'
2
+ module OrigenTesters
3
+ module VectorGenerator
4
+ extend ActiveSupport::Concern
5
+
6
+ require 'erb'
7
+
8
+ included do
9
+ # When set to true vector and cycle number comments will be appended to pattern vectors.
10
+ # This can also be enabled by running the generate command with the '-v' switch.
11
+ attr_accessor :vector_comments
12
+ attr_accessor :compress
13
+ attr_accessor :expand_repeats
14
+ end
15
+
16
+ def vector_group_size
17
+ @vector_group_size || 1
18
+ end
19
+
20
+ def vector_group_size=(number)
21
+ if number > 1 && number.odd?
22
+ fail 'Only even numbers can be supplied for the vector_group_size!'
23
+ end
24
+ # Each pattern should run with its own tester instance, but just in case
25
+ @pipeline = nil
26
+ @vector_group_size = number
27
+ end
28
+
29
+ def with_vector_group_size(number)
30
+ orig = vector_group_size
31
+ self.vector_group_size = number
32
+ yield
33
+ self.vector_group_size = orig
34
+ end
35
+
36
+ # Duplicate the last vector as required until aligned with the start of the
37
+ # next vector group
38
+ def align
39
+ stage.store :align
40
+ end
41
+ alias_method :align_to_first, :align
42
+
43
+ # Duplicate the last vector as required until aligned to the last vector of the
44
+ # current vector group
45
+ def align_to_last
46
+ stage.store :align_last
47
+ end
48
+
49
+ # Returns an array of pin IDs that are currently inhibited (will not
50
+ # be included when vectors are generated)
51
+ def inhibited_pins
52
+ @inhibited_pins ||= []
53
+ end
54
+
55
+ # init vector count when first accessed, otherwise return value
56
+ def vec_count
57
+ @vec_count ||= 0
58
+ end
59
+
60
+ # increment vector count
61
+ def inc_vec_count(num = 1)
62
+ vec_count if @vec_count.nil? # define if not already
63
+ @vec_count = @vec_count + num
64
+ end
65
+
66
+ # decrement vector count
67
+ def dec_vec_count(num = 1)
68
+ vec_count if @vec_count.nil? # define if not already
69
+ @vec_count = @vec_count - num
70
+ end
71
+
72
+ # init cycle count when first accessed, otherwise return value
73
+ def cycle_count
74
+ @cycle_count ||= 0
75
+ end
76
+
77
+ # increment cycle count
78
+ def inc_cycle_count(num = 1)
79
+ cycle_count if @cycle_count.nil? # define if not already
80
+ @cycle_count = @cycle_count + num
81
+ end
82
+
83
+ # reset_cycle_count
84
+ def reset_cycle_count(num = 0)
85
+ cycle_count if @cycle_count.nil? # define if not already
86
+ @cycle_count = num
87
+ end
88
+
89
+ # Call to prevent the given pins from appearing in the generated vectors.
90
+ #
91
+ # This is a convenient way to inhibit something like a J750 mux pin from
92
+ # appearing in the patterns when generating the pattern for a different
93
+ # platform.
94
+ #
95
+ # When used this
96
+ # method must be called before the first vector is generated - it will not be retrospectively
97
+ # applied to existing vectors.
98
+ def inhibit_pin(*pins)
99
+ pins.each do |pin|
100
+ pin = $dut.pin(pin) if pin.is_a?(Symbol)
101
+ inhibited_pins << pin
102
+ end
103
+ inhibited_pins.uniq!
104
+ inhibited_pins.compact!
105
+ inhibited_pins
106
+ end
107
+ alias_method :inhibit_pins, :inhibit_pin
108
+
109
+ # Render content directly into a pattern, any options will be passed to the template
110
+ def render(template, options = {})
111
+ # Record the current file, this can be used to resolve any relative path
112
+ # references in the file about to be compiled
113
+ Origen.file_handler.current_file = template
114
+ # Ran into crosstalk problems when rendering ERB templates recursively, setting eoutvar based
115
+ # on the name of the file will causes each template to be rendered into its own 'bank'.
116
+ # Not sure why the final gsub is needed but seems to fail to parse correctly otherwise.
117
+ eoutvar = Pathname.new(template).basename('.*').basename('.*').to_s.gsub('-', '_')
118
+ # Make the file name available to the template
119
+ Origen.generator.compiler.options[:file] = template
120
+ options.each { |k, v| Origen.generator.compiler.options[k] = v }
121
+ code = Origen.generator.compiler.insert(ERB.new(File.read(template.to_s), 0, Origen.config.erb_trim_mode, eoutvar).result)
122
+ code.strip!
123
+ push_microcode code
124
+ end
125
+
126
+ # If the tester defines a method named template this method will compile
127
+ # whatever template file is returned by that method.
128
+ #
129
+ # This method is called automatically after the body section of a Pattern.create
130
+ # operation has completed.
131
+ def render_template
132
+ _render(:template)
133
+ end
134
+
135
+ # Same as the render method, except the template method should be called body_template.
136
+ def render_body
137
+ _render(:body_template)
138
+ end
139
+
140
+ # If the tester defines a method named footer_template this method will compile
141
+ # whatever template file is returned by that method.
142
+ #
143
+ # This method is called automatically during the footer section of a Pattern.create
144
+ # operation.
145
+ def render_footer
146
+ _render(:footer_template)
147
+ end
148
+
149
+ # If the tester defines a method named header_template this method will compile
150
+ # whatever template file is returned by that method.
151
+ #
152
+ # This method is called automatically during the header section of a Pattern.create
153
+ # operation.
154
+ def render_header
155
+ _render(:header_template)
156
+ end
157
+
158
+ def _render(method) # :nodoc:
159
+ if self.respond_to?(method)
160
+ template = send(method)
161
+ # Record the current file, this can be used to resolve any relative path
162
+ # references in the file about to be compiled
163
+ Origen.file_handler.current_file = template
164
+ # Ran into crosstalk problems when rendering ERB templates recursively, setting eoutvar based
165
+ # on the name of the file will causes each template to be rendered into its own 'bank'.
166
+ # Not sure why the final gsub is needed but seems to fail to parse correctly otherwise.
167
+ eoutvar = Pathname.new(template).basename('.*').basename('.*').to_s.gsub('-', '_')
168
+ # Make the file name available to the template
169
+ Origen.generator.compiler.options[:file] = template
170
+ push_microcode Origen.generator.compiler.insert(ERB.new(File.read(template.to_s), 0, Origen.config.erb_trim_mode, eoutvar).result)
171
+ end
172
+ end
173
+
174
+ def stage
175
+ Origen.generator.stage
176
+ end
177
+
178
+ def push_comment(msg)
179
+ # Comments are stored verbatim for now, can't see much use for a dedicated comment object
180
+ stage.store msg unless @inhibit_comments
181
+ end
182
+
183
+ def microcode(code, options = {})
184
+ unless @inhibit_vectors
185
+ if options[:offset] && options[:offset] != 0
186
+ stage.insert_from_end code, options[:offset]
187
+ else
188
+ stage.store code
189
+ end
190
+ end
191
+ end
192
+ alias_method :push_microcode, :microcode
193
+
194
+ def last_vector(offset = 0)
195
+ stage.last_vector(offset)
196
+ end
197
+
198
+ def last_object(offset = 0)
199
+ stage.last_object(offset)
200
+ end
201
+
202
+ # Allows the attributes for the next vector to be setup prior
203
+ # to generating it.
204
+ #
205
+ # A block can be optionally supplied to act as a clean up method,
206
+ # that is the block will be saved and executed after the next
207
+ # cycle has been generated.
208
+ #
209
+ # See the V93K store_next_cycle method for an example of using
210
+ # this.
211
+ def preset_next_vector(attrs = {}, &block)
212
+ @preset_next_vector = attrs
213
+ @preset_next_vector_cleanup = block
214
+ end
215
+
216
+ # Called by every $tester.cycle command to push a vector to the stage object
217
+ def push_vector(attrs = {})
218
+ attrs = {
219
+ dont_compress: @dont_compress
220
+ }.merge(attrs)
221
+ unless @inhibit_vectors
222
+ if @preset_next_vector
223
+ attrs = @preset_next_vector.merge(attrs) do |key, preset, current|
224
+ if preset && current && current != ''
225
+ fail "Value for #{key} set by preset_next_vector clashed with the next vector!"
226
+ else
227
+ preset || current
228
+ end
229
+ end
230
+ @preset_next_vector = nil
231
+ end
232
+ stage.store Vector.new(attrs)
233
+ inc_vec_count
234
+ inc_cycle_count(attrs[:repeat] || 1)
235
+ if @preset_next_vector_cleanup
236
+ @preset_next_vector_cleanup.call
237
+ @preset_next_vector_cleanup = nil
238
+ end
239
+ end
240
+ end
241
+ alias_method :vector, :push_vector
242
+
243
+ def update_vector(attrs = {})
244
+ unless @inhibit_vectors
245
+ offset = (attrs.delete(:offset) || 0).abs
246
+ stage.last_vector(offset).update(attrs)
247
+ end
248
+ end
249
+
250
+ def update_vector_pin_val(pin, options = {})
251
+ unless @inhibit_vectors
252
+ offset = (options.delete(:offset) || 0).abs
253
+ stage.last_vector(offset).update_pin_val(pin)
254
+ end
255
+ end
256
+
257
+ # Adds the given microcode to the last vector if possible. If not possible (meaning the
258
+ # vector already contains microcode) then a new cycle will be added with the given
259
+ # microcode.
260
+ def add_microcode_to_last_or_cycle(code)
261
+ cycle if !stage.last_vector || stage.last_vector.has_microcode?
262
+ stage.last_vector.update(microcode: code)
263
+ end
264
+
265
+ # Final pass of a generator vector array which returns lines suitable for writing to the
266
+ # output file. This gives the tester model a chance to concatenate repeats and any other
267
+ # last optimization/formatting changes it wishes to make.
268
+ #
269
+ # At this point vector array contains a combination of non-vector lines and uncompressed
270
+ # Vector objects (vector lines)
271
+ #
272
+ def format(vector_array, section)
273
+ # Go through vector_array and print out both
274
+ # vectors and non-vectors to pattern (via 'yield line')
275
+ vector_array.each do |vec|
276
+ # skip here important for the ways delays are currently handled
277
+ # TODO: This seems like an upstream bug that should be investigated, why is such
278
+ # a vector even generated?
279
+ if vec.is_a?(String)
280
+ if vec.strip[0] == comment_char
281
+ pipeline.push_comment(vec)
282
+ else
283
+ pipeline.push_microcode(vec)
284
+ end
285
+ else
286
+ next if vec.respond_to?(:repeat) && vec.repeat == 0 # skip vectors with repeat of 0!
287
+ pipeline << vec
288
+ end
289
+ pipeline.flush do |vector|
290
+ expand_vector(vector) do |line|
291
+ yield line
292
+ end
293
+ end
294
+ end
295
+ # now flush buffer if there is still a vector
296
+ pipeline.empty(min_vectors: section == :footer ? @min_pattern_vectors : nil) do |vector|
297
+ expand_vector(vector) do |line|
298
+ yield line
299
+ end
300
+ end
301
+ end
302
+
303
+ # Tester models can overwrite this if they wish to inject any additional pattern lines
304
+ # at final pattern dump time
305
+ def before_write_pattern_line(line)
306
+ [line]
307
+ end
308
+
309
+ def pipeline
310
+ @pipeline ||= VectorPipeline.new(vector_group_size)
311
+ end
312
+
313
+ def dont_compress
314
+ if block_given?
315
+ orig = @dont_compress
316
+ @dont_compress = true
317
+ yield
318
+ @dont_compress = orig
319
+ else
320
+ @dont_compress
321
+ end
322
+ end
323
+
324
+ def dont_compress=(val)
325
+ @dont_compress = val
326
+ end
327
+
328
+ # expands (uncompresses to pattern) vector if desired or leaves it as is
329
+ # allows for tracking and formatting of vector
330
+ # if comment then return without modification
331
+ def expand_vector(vec)
332
+ if vec.is_a?(Vector)
333
+ if expand_repeats
334
+ vec.repeat.times do
335
+ vec.repeat = 1
336
+ yield track_and_format_vector(vec)
337
+ end
338
+ else
339
+ yield track_and_format_vector(vec)
340
+ end
341
+ else
342
+ yield vec # Return comments without modification
343
+ end
344
+ end
345
+
346
+ # Update tracking info (stats object) and allow for
347
+ # any additional formatting via format_vector
348
+ # method if overridden
349
+ def track_and_format_vector(vec)
350
+ unless vec.timeset
351
+ puts 'No timeset defined!'
352
+ puts 'Add one to your top level startup method or target like this:'
353
+ puts '$tester.set_timeset("nvmbist", 40) # Where 40 is the period in ns'
354
+ exit 1
355
+ end
356
+ stats = Origen.app.stats
357
+ stats.add_vector
358
+ if vector_group_size > 1 && vec.repeat > 1
359
+ stats.add_cycle(1)
360
+ stats.add_cycle((vec.repeat - 1) * vector_group_size)
361
+ stats.add_time_in_ns(vec.timeset.period_in_ns)
362
+ stats.add_time_in_ns((vec.repeat - 1) * vector_group_size * vec.timeset.period_in_ns)
363
+ else
364
+ stats.add_cycle(vec.repeat)
365
+ stats.add_time_in_ns(vec.repeat * vec.timeset.period_in_ns)
366
+ end
367
+ format_vector(vec)
368
+ end
369
+
370
+ def format_vector(vec)
371
+ end
372
+
373
+ def pingroup_map
374
+ Origen.app.pingroup_map
375
+ end
376
+
377
+ # Cache any pin ordering for later use since all vectors should be formatted the same
378
+ def ordered_pins_cache(options = {})
379
+ @ordered_pins_cache ||= ordered_pins(options)
380
+ end
381
+
382
+ def ordered_pins(options = {})
383
+ options = {
384
+ include_inhibited_pins: false,
385
+ include_pingroups: true
386
+ }.merge(options)
387
+
388
+ pinorder = Origen.app.pin_pattern_order.dup
389
+ pinexclude = Origen.app.pin_pattern_exclude.dup
390
+ pinids = []
391
+
392
+ if Origen.app.pin_pattern_order.last.is_a?(Hash)
393
+ options.merge!(pinorder.pop)
394
+ end
395
+ if Origen.app.pin_pattern_exclude.last.is_a?(Hash)
396
+ options.merge!(pinexclude.pop)
397
+ end
398
+
399
+ ordered_pins = []
400
+
401
+ # add bit here that puts pingroup id into ordered pins array and deletes included pins
402
+ pins = Origen.pin_bank.pins.dup
403
+ pingroups = Origen.pin_bank.pin_groups.dup
404
+
405
+ if pinorder && pinorder.size > 0
406
+ pinorder.each do |id|
407
+ if Origen.pin_bank.pin_groups.keys.include? id
408
+ # see if group is already in ordered_pins
409
+ fail "Pin group #{id} is duplicately defined in pin_pattern_order" unless pingroups.include? id
410
+ # see if any pins in group are already in pin_order
411
+ used = []
412
+ pingroups[id].each do |pin|
413
+ pinorder.each { |pin| pinids << Origen.pin_bank.find(pin).id if Origen.pin_bank.find(pin) }
414
+ used << pin if pinids.include?(pin.id) # see if pin included in pinids
415
+ end
416
+ if !used.empty?
417
+ pingroups[id].each { |pin| ordered_pins << pin unless used.include?(pin) }
418
+ else
419
+ # this is a pin group, add pin_group and delete all pins in group
420
+ ordered_pins << pingroups[id]
421
+ pingroups[id].each do |pin|
422
+ fail "Pin (#{pin.name}) in group (#{id}) is duplicately defined in pin_pattern_order" unless pins.include? pin.id
423
+ pins.delete(pin.id)
424
+ end
425
+ end
426
+ pingroups.delete(id)
427
+ else # this is a pin
428
+ pin = Origen.pin_bank.find(id)
429
+ fail "Undefined pin (#{id}) added to pin_pattern_order" unless pin
430
+ ordered_pins << pin
431
+ pin.name = id
432
+ fail "Individual pin (#{pin.name}) is duplicately defined in pin_pattern_order" unless pins.include? pin.id
433
+ pins.delete(pin.id)
434
+ end
435
+ end
436
+ end
437
+
438
+ if pinexclude && pinexclude.size > 0
439
+ pinexclude.each do |id|
440
+ if Origen.pin_bank.pin_groups.keys.include? id
441
+ # see if group is already in ordered_pins
442
+ fail "Pin group #{id} is defined both in pin_pattern_order and pin_pattern_exclude" unless pingroups.include? id
443
+ # this is a pin group, delete all pins in group
444
+ pingroups[id].each do |pin|
445
+ fail "Pin (#{pin.name}) in group (#{id}) is defined both in pin_pattern_order and pin_pattern_exclude" unless pins.include? pin.id
446
+ pins.delete(pin.id)
447
+ end
448
+ else # this is a pin, delete the pin
449
+ pin = Origen.pin_bank.find(id)
450
+ fail "Undefined pin (#{id}) added to pin_pattern_exclude" unless pin
451
+ fail "Pin #{pin.name} is defined both in pin_pattern_order and pin_pattern_exclude" unless pins.include? pin.id
452
+ pin.name = id
453
+ pins.delete(pin.id)
454
+ end
455
+ end
456
+ end
457
+
458
+ unless options[:only]
459
+ # all the rest of the pins to the end of the pattern order
460
+ pins.each do |id, pin|
461
+ # check for port
462
+ if pin.belongs_to_a_pin_group?
463
+ if id =~ /(\D+)\d+$/
464
+ name = Regexp.last_match[1]
465
+ port = nil
466
+ pin.groups.each do |group|
467
+ if group[0] == name.to_sym # belongs to a port
468
+ port = group[1]
469
+ end
470
+ end
471
+ if pingroups.include?(port.id)
472
+ ordered_pins << port
473
+ port.each { |pin| pins.delete(pin.id) }
474
+ end
475
+ else
476
+ ordered_pins << pin
477
+ end
478
+ else
479
+ ordered_pins << pin
480
+ end
481
+ end
482
+ end
483
+
484
+ ordered_pins.map do |pin|
485
+ if options[:include_inhibited_pins]
486
+ pin
487
+ else
488
+ inhibited_pins.include?(pin) ? nil : pin
489
+ end
490
+ end.compact
491
+ end
492
+
493
+ def current_pin_vals
494
+ ordered_pins_cache.map(&:to_vector).join(' ')
495
+ end
496
+
497
+ # Returns a regular expression that can be used to get the value
498
+ # of the given pin within the string returned by current_pin_vals.
499
+ # str = $tester.current_pin_vals # => "1 1 XX10 H X1"
500
+ # regex = $tester.regex_for_pin($dut.pins(:jtag)) # => /\w{1} \w{1} (\w{4}) \w{1} \w{2}/
501
+ # regex.match(str)
502
+ # Regexp.last_match(1) # => "XX10"
503
+ #
504
+ # @see Vector#pin_value
505
+ def regex_for_pin(pin)
506
+ @regex_for_pins ||= {}
507
+ # Cache this as potentially called many times during pattern generation
508
+ @regex_for_pins[pin] ||= begin
509
+ regex = '/'
510
+ ordered_pins_cache.each do |p|
511
+ if pin == p
512
+ regex += "(\\w{#{p.size}}) "
513
+ else
514
+ regex += "\\w{#{p.size}} "
515
+ end
516
+ end
517
+ eval(regex.strip + '/')
518
+ end
519
+ end
520
+
521
+ # Returns a regular expression that can be used to change the value
522
+ # of the given pin within the string returned by current_pin_vals.
523
+ # str = $tester.current_pin_vals # => "1 1 XX10 H X1"
524
+ # regex = $tester.regex_for_pin_sub($dut.pins(:jtag)) # => /(\w{1} \w{1} )(\w{4})( \w{1} \w{2})/
525
+ # str.sub(regex, '\1LLLL\3') # => "1 1 LLLL H X1"
526
+ #
527
+ # @see Vector#set_pin_value
528
+ def regex_for_pin_sub(pin)
529
+ @regex_for_pin_subs ||= {}
530
+ # Cache this as potentially called many times during pattern generation
531
+ @regex_for_pin_subs[pin] ||= begin
532
+ regex = '/'
533
+ first_pin_done = false
534
+ match_pin_done = false
535
+ ordered_pins_cache.each do |p|
536
+ if pin == p
537
+ regex += ')' if first_pin_done
538
+ regex += "(\\w{#{p.size}})( "
539
+ else
540
+ regex += '(' unless first_pin_done
541
+ regex += "\\w{#{p.size}} "
542
+ end
543
+ first_pin_done = true
544
+ end
545
+ regex.strip!
546
+ if regex[-1] == '('
547
+ regex.chop!
548
+ else
549
+ regex += ')'
550
+ end
551
+ eval(regex + '/')
552
+ end
553
+ end
554
+
555
+ def get_pingroup(pin)
556
+ pingroup_map.each do |id, pins|
557
+ return id if pins.include? pin
558
+ end
559
+ nil
560
+ end
561
+
562
+ def update_pin_from_formatted_state(pin, state)
563
+ if state == @repeat_previous || state == '-'
564
+ pin.repeat_previous = true
565
+ elsif state == @drive_very_hi_state || state == '2'
566
+ pin.drive_very_hi
567
+ elsif state == @drive_hi_state || state == '1'
568
+ pin.drive_hi
569
+ elsif state == @drive_lo_state || state == '0'
570
+ pin.drive_lo
571
+ elsif state == @expect_hi_state || state == 'H'
572
+ pin.expect_hi
573
+ elsif state == @expect_lo_state || state == 'L'
574
+ pin.expect_lo
575
+ elsif state == @expect_mid_state || state == 'M'
576
+ pin.expect_mid
577
+ elsif state == @drive_mem_state || state == 'D'
578
+ pin.drive_mem
579
+ elsif state == @expect_mem_state || state == 'E'
580
+ pin.expect_mem
581
+ elsif state == @capture_state || state == 'C'
582
+ pin.capture
583
+ elsif state == @dont_care_state || state == 'X'
584
+ pin.dont_care
585
+ else
586
+ fail "Unknown pin state: #{state}"
587
+ end
588
+ end
589
+
590
+ # @see Origen::Pins::Pin#to_vector
591
+ def format_pin_state(pin)
592
+ if pin.repeat_previous? && @support_repeat_previous
593
+ @repeat_previous || '-'
594
+ elsif pin.driving?
595
+ if pin.value == 1
596
+ if pin.high_voltage?
597
+ @drive_very_hi_state || '2'
598
+ else
599
+ @drive_hi_state || '1'
600
+ end
601
+ else
602
+ @drive_lo_state || '0'
603
+ end
604
+ elsif pin.comparing_midband?
605
+ @expect_mid_state || 'M'
606
+ elsif pin.comparing?
607
+ if pin.value == 1
608
+ @expect_hi_state || 'H'
609
+ else
610
+ @expect_lo_state || 'L'
611
+ end
612
+ elsif pin.driving_mem?
613
+ @drive_mem_state || 'D'
614
+ elsif pin.comparing_mem?
615
+ @expect_mem_state || 'E'
616
+ elsif pin.to_be_captured?
617
+ @capture_state || 'C'
618
+ else
619
+ @dont_care_state || 'X'
620
+ end
621
+ end
622
+ end
623
+ end