origen_testers 0.4.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 (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