origen_testers 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (255) hide show
  1. checksums.yaml +4 -4
  2. data/config/application.rb +151 -151
  3. data/config/boot.rb +13 -13
  4. data/config/commands.rb +86 -86
  5. data/config/users.rb +18 -18
  6. data/config/version.rb +8 -8
  7. data/lib/commands/build.rb +69 -69
  8. data/lib/commands/run.rb +48 -48
  9. data/lib/origen_testers.rb +47 -47
  10. data/lib/origen_testers/api.rb +381 -381
  11. data/lib/origen_testers/basic_test_setups.rb +105 -105
  12. data/lib/origen_testers/callback_handlers.rb +59 -59
  13. data/lib/origen_testers/command_based_tester.rb +45 -45
  14. data/lib/origen_testers/flow.rb +382 -382
  15. data/lib/origen_testers/generator.rb +283 -283
  16. data/lib/origen_testers/generator/identity_map.rb +23 -23
  17. data/lib/origen_testers/generator/placeholder.rb +11 -11
  18. data/lib/origen_testers/generator/test_numberer.rb +23 -23
  19. data/lib/origen_testers/igxl_based_tester.rb +12 -12
  20. data/lib/origen_testers/igxl_based_tester/base.rb +1095 -1095
  21. data/lib/origen_testers/igxl_based_tester/base/ac_specsets.rb +79 -79
  22. data/lib/origen_testers/igxl_based_tester/base/custom_test_instance.rb +169 -169
  23. data/lib/origen_testers/igxl_based_tester/base/dc_specsets.rb +98 -98
  24. data/lib/origen_testers/igxl_based_tester/base/edge.rb +60 -60
  25. data/lib/origen_testers/igxl_based_tester/base/edges.rb +24 -24
  26. data/lib/origen_testers/igxl_based_tester/base/edgeset.rb +39 -39
  27. data/lib/origen_testers/igxl_based_tester/base/edgesets.rb +130 -130
  28. data/lib/origen_testers/igxl_based_tester/base/flow.rb +448 -446
  29. data/lib/origen_testers/igxl_based_tester/base/flow_line.rb +276 -276
  30. data/lib/origen_testers/igxl_based_tester/base/generator.rb +607 -607
  31. data/lib/origen_testers/igxl_based_tester/base/global_specs.rb +83 -83
  32. data/lib/origen_testers/igxl_based_tester/base/job.rb +75 -75
  33. data/lib/origen_testers/igxl_based_tester/base/jobs.rb +44 -44
  34. data/lib/origen_testers/igxl_based_tester/base/level_io_se.rb +59 -59
  35. data/lib/origen_testers/igxl_based_tester/base/level_supply.rb +39 -39
  36. data/lib/origen_testers/igxl_based_tester/base/levels.rb +31 -31
  37. data/lib/origen_testers/igxl_based_tester/base/levelset.rb +110 -110
  38. data/lib/origen_testers/igxl_based_tester/base/patgroup.rb +109 -109
  39. data/lib/origen_testers/igxl_based_tester/base/patgroups.rb +38 -38
  40. data/lib/origen_testers/igxl_based_tester/base/patset.rb +68 -68
  41. data/lib/origen_testers/igxl_based_tester/base/patset_pattern.rb +56 -56
  42. data/lib/origen_testers/igxl_based_tester/base/patsets.rb +38 -38
  43. data/lib/origen_testers/igxl_based_tester/base/patsubr.rb +68 -68
  44. data/lib/origen_testers/igxl_based_tester/base/patsubr_pattern.rb +56 -56
  45. data/lib/origen_testers/igxl_based_tester/base/patsubrs.rb +38 -38
  46. data/lib/origen_testers/igxl_based_tester/base/pinmap.rb +93 -93
  47. data/lib/origen_testers/igxl_based_tester/base/references.rb +25 -25
  48. data/lib/origen_testers/igxl_based_tester/base/test_instance.rb +322 -322
  49. data/lib/origen_testers/igxl_based_tester/base/test_instance_group.rb +66 -66
  50. data/lib/origen_testers/igxl_based_tester/base/test_instances.rb +212 -212
  51. data/lib/origen_testers/igxl_based_tester/base/test_instances/custom_til.rb +37 -37
  52. data/lib/origen_testers/igxl_based_tester/base/timeset.rb +37 -37
  53. data/lib/origen_testers/igxl_based_tester/base/timesets.rb +49 -49
  54. data/lib/origen_testers/igxl_based_tester/base/timesets_basic.rb +49 -49
  55. data/lib/origen_testers/igxl_based_tester/files.rb +43 -43
  56. data/lib/origen_testers/igxl_based_tester/j750.rb +269 -269
  57. data/lib/origen_testers/igxl_based_tester/j750/custom_test_instance.rb +32 -32
  58. data/lib/origen_testers/igxl_based_tester/j750/flow.rb +10 -10
  59. data/lib/origen_testers/igxl_based_tester/j750/flow_line.rb +19 -19
  60. data/lib/origen_testers/igxl_based_tester/j750/generator.rb +19 -19
  61. data/lib/origen_testers/igxl_based_tester/j750/patgroup.rb +9 -9
  62. data/lib/origen_testers/igxl_based_tester/j750/patgroups.rb +10 -10
  63. data/lib/origen_testers/igxl_based_tester/j750/patset.rb +9 -9
  64. data/lib/origen_testers/igxl_based_tester/j750/patset_pattern.rb +18 -18
  65. data/lib/origen_testers/igxl_based_tester/j750/patsets.rb +10 -10
  66. data/lib/origen_testers/igxl_based_tester/j750/patsubr.rb +9 -9
  67. data/lib/origen_testers/igxl_based_tester/j750/patsubr_pattern.rb +18 -18
  68. data/lib/origen_testers/igxl_based_tester/j750/patsubrs.rb +10 -10
  69. data/lib/origen_testers/igxl_based_tester/j750/test_instance.rb +746 -746
  70. data/lib/origen_testers/igxl_based_tester/j750/test_instance_group.rb +9 -9
  71. data/lib/origen_testers/igxl_based_tester/j750/test_instances.rb +10 -10
  72. data/lib/origen_testers/igxl_based_tester/j750_hpt.rb +34 -34
  73. data/lib/origen_testers/igxl_based_tester/j750_hpt/custom_test_instance.rb +32 -32
  74. data/lib/origen_testers/igxl_based_tester/j750_hpt/flow.rb +9 -9
  75. data/lib/origen_testers/igxl_based_tester/j750_hpt/flow_line.rb +9 -9
  76. data/lib/origen_testers/igxl_based_tester/j750_hpt/generator.rb +19 -19
  77. data/lib/origen_testers/igxl_based_tester/j750_hpt/patgroup.rb +9 -9
  78. data/lib/origen_testers/igxl_based_tester/j750_hpt/patgroups.rb +9 -9
  79. data/lib/origen_testers/igxl_based_tester/j750_hpt/patset.rb +9 -9
  80. data/lib/origen_testers/igxl_based_tester/j750_hpt/patset_pattern.rb +9 -9
  81. data/lib/origen_testers/igxl_based_tester/j750_hpt/patsets.rb +9 -9
  82. data/lib/origen_testers/igxl_based_tester/j750_hpt/patsubr.rb +9 -9
  83. data/lib/origen_testers/igxl_based_tester/j750_hpt/patsubr_pattern.rb +9 -9
  84. data/lib/origen_testers/igxl_based_tester/j750_hpt/patsubrs.rb +9 -9
  85. data/lib/origen_testers/igxl_based_tester/j750_hpt/test_instance.rb +599 -599
  86. data/lib/origen_testers/igxl_based_tester/j750_hpt/test_instance_group.rb +9 -9
  87. data/lib/origen_testers/igxl_based_tester/j750_hpt/test_instances.rb +9 -9
  88. data/lib/origen_testers/igxl_based_tester/parser.rb +102 -102
  89. data/lib/origen_testers/igxl_based_tester/parser/ac_spec.rb +9 -9
  90. data/lib/origen_testers/igxl_based_tester/parser/dc_spec.rb +33 -33
  91. data/lib/origen_testers/igxl_based_tester/parser/dc_specs.rb +48 -48
  92. data/lib/origen_testers/igxl_based_tester/parser/descriptions.rb +339 -339
  93. data/lib/origen_testers/igxl_based_tester/parser/flow.rb +109 -109
  94. data/lib/origen_testers/igxl_based_tester/parser/flow_line.rb +203 -203
  95. data/lib/origen_testers/igxl_based_tester/parser/flows.rb +21 -21
  96. data/lib/origen_testers/igxl_based_tester/parser/pattern_set.rb +92 -92
  97. data/lib/origen_testers/igxl_based_tester/parser/pattern_sets.rb +31 -31
  98. data/lib/origen_testers/igxl_based_tester/parser/test_instance.rb +420 -420
  99. data/lib/origen_testers/igxl_based_tester/parser/test_instances.rb +24 -24
  100. data/lib/origen_testers/igxl_based_tester/parser/timeset.rb +13 -13
  101. data/lib/origen_testers/igxl_based_tester/ultraflex.rb +798 -798
  102. data/lib/origen_testers/igxl_based_tester/ultraflex/ac_specsets.rb +10 -10
  103. data/lib/origen_testers/igxl_based_tester/ultraflex/ate_hardware.rb +949 -949
  104. data/lib/origen_testers/igxl_based_tester/ultraflex/custom_test_instance.rb +36 -36
  105. data/lib/origen_testers/igxl_based_tester/ultraflex/dc_specsets.rb +10 -10
  106. data/lib/origen_testers/igxl_based_tester/ultraflex/edge.rb +9 -9
  107. data/lib/origen_testers/igxl_based_tester/ultraflex/edges.rb +9 -9
  108. data/lib/origen_testers/igxl_based_tester/ultraflex/edgeset.rb +9 -9
  109. data/lib/origen_testers/igxl_based_tester/ultraflex/edgesets.rb +10 -10
  110. data/lib/origen_testers/igxl_based_tester/ultraflex/flow.rb +158 -158
  111. data/lib/origen_testers/igxl_based_tester/ultraflex/flow_line.rb +19 -19
  112. data/lib/origen_testers/igxl_based_tester/ultraflex/generator.rb +19 -19
  113. data/lib/origen_testers/igxl_based_tester/ultraflex/global_specs.rb +10 -10
  114. data/lib/origen_testers/igxl_based_tester/ultraflex/job.rb +9 -9
  115. data/lib/origen_testers/igxl_based_tester/ultraflex/jobs.rb +10 -10
  116. data/lib/origen_testers/igxl_based_tester/ultraflex/level_io_se.rb +9 -9
  117. data/lib/origen_testers/igxl_based_tester/ultraflex/level_supply.rb +9 -9
  118. data/lib/origen_testers/igxl_based_tester/ultraflex/levels.rb +9 -9
  119. data/lib/origen_testers/igxl_based_tester/ultraflex/levelset.rb +10 -10
  120. data/lib/origen_testers/igxl_based_tester/ultraflex/patgroup.rb +9 -9
  121. data/lib/origen_testers/igxl_based_tester/ultraflex/patgroups.rb +10 -10
  122. data/lib/origen_testers/igxl_based_tester/ultraflex/patset.rb +9 -9
  123. data/lib/origen_testers/igxl_based_tester/ultraflex/patset_pattern.rb +18 -18
  124. data/lib/origen_testers/igxl_based_tester/ultraflex/patsets.rb +10 -10
  125. data/lib/origen_testers/igxl_based_tester/ultraflex/patsubr.rb +9 -9
  126. data/lib/origen_testers/igxl_based_tester/ultraflex/patsubr_pattern.rb +18 -18
  127. data/lib/origen_testers/igxl_based_tester/ultraflex/patsubrs.rb +10 -10
  128. data/lib/origen_testers/igxl_based_tester/ultraflex/pinmap.rb +10 -10
  129. data/lib/origen_testers/igxl_based_tester/ultraflex/references.rb +10 -10
  130. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/ac_specsets.txt.erb +0 -0
  131. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/dc_specsets.txt.erb +0 -0
  132. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/edgesets.txt.erb +0 -0
  133. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/global_specs.txt.erb +0 -0
  134. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/jobs.txt.erb +0 -0
  135. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/levelset.txt.erb +0 -0
  136. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/pinmap.txt.erb +0 -0
  137. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/references.txt.erb +0 -0
  138. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/timesets.txt.erb +0 -0
  139. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/timesets_basic.txt.erb +0 -0
  140. data/lib/origen_testers/igxl_based_tester/ultraflex/test_instance.rb +315 -315
  141. data/lib/origen_testers/igxl_based_tester/ultraflex/test_instance_group.rb +9 -9
  142. data/lib/origen_testers/igxl_based_tester/ultraflex/test_instances.rb +10 -10
  143. data/lib/origen_testers/igxl_based_tester/ultraflex/timeset.rb +9 -9
  144. data/lib/origen_testers/igxl_based_tester/ultraflex/timesets.rb +10 -10
  145. data/lib/origen_testers/igxl_based_tester/ultraflex/timesets_basic.rb +10 -10
  146. data/lib/origen_testers/interface.rb +324 -328
  147. data/lib/origen_testers/memory_style.rb +77 -77
  148. data/lib/origen_testers/no_interface.rb +7 -7
  149. data/lib/origen_testers/origen_ext/application/runner.rb +25 -25
  150. data/lib/origen_testers/origen_ext/generator.rb +54 -54
  151. data/lib/origen_testers/origen_ext/generator/flow.rb +77 -77
  152. data/lib/origen_testers/origen_ext/generator/resources.rb +21 -21
  153. data/lib/origen_testers/origen_ext/pins/pin.rb +78 -78
  154. data/lib/origen_testers/origen_ext/pins/pin_collection.rb +84 -84
  155. data/lib/origen_testers/parser.rb +22 -22
  156. data/lib/origen_testers/parser/description_lookup.rb +62 -62
  157. data/lib/origen_testers/parser/searchable_array.rb +30 -30
  158. data/lib/origen_testers/parser/searchable_hash.rb +30 -30
  159. data/lib/origen_testers/pattern_compilers.rb +116 -116
  160. data/lib/origen_testers/pattern_compilers/assembler.rb +88 -88
  161. data/lib/origen_testers/pattern_compilers/job.rb +96 -96
  162. data/lib/origen_testers/pattern_compilers/ultraflex_pattern_compiler.rb +599 -599
  163. data/lib/origen_testers/program_generators.rb +62 -62
  164. data/lib/origen_testers/smartest_based_tester.rb +8 -8
  165. data/lib/origen_testers/smartest_based_tester/base.rb +562 -562
  166. data/lib/origen_testers/smartest_based_tester/base/flow.rb +279 -279
  167. data/lib/origen_testers/smartest_based_tester/base/generator.rb +193 -193
  168. data/lib/origen_testers/smartest_based_tester/base/pattern_compiler.rb +32 -32
  169. data/lib/origen_testers/smartest_based_tester/base/pattern_master.rb +69 -69
  170. data/lib/origen_testers/smartest_based_tester/base/processors.rb +13 -13
  171. data/lib/origen_testers/smartest_based_tester/base/processors/empty_branch_cleaner.rb +49 -49
  172. data/lib/origen_testers/smartest_based_tester/base/processors/extract_set_variables.rb +22 -22
  173. data/lib/origen_testers/smartest_based_tester/base/processors/flag_optimizer.rb +143 -143
  174. data/lib/origen_testers/smartest_based_tester/base/processors/if_ran_cleaner.rb +34 -34
  175. data/lib/origen_testers/smartest_based_tester/base/test_method.rb +164 -164
  176. data/lib/origen_testers/smartest_based_tester/base/test_methods.rb +73 -73
  177. data/lib/origen_testers/smartest_based_tester/base/test_methods/ac_tml.rb +33 -33
  178. data/lib/origen_testers/smartest_based_tester/base/test_methods/base_tml.rb +38 -38
  179. data/lib/origen_testers/smartest_based_tester/base/test_methods/custom_tml.rb +19 -19
  180. data/lib/origen_testers/smartest_based_tester/base/test_methods/dc_tml.rb +147 -147
  181. data/lib/origen_testers/smartest_based_tester/base/test_methods/limits.rb +65 -65
  182. data/lib/origen_testers/smartest_based_tester/base/test_suite.rb +193 -193
  183. data/lib/origen_testers/smartest_based_tester/base/test_suites.rb +54 -54
  184. data/lib/origen_testers/smartest_based_tester/base/variables_file.rb +38 -38
  185. data/lib/origen_testers/smartest_based_tester/v93k.rb +8 -8
  186. data/lib/origen_testers/smartest_based_tester/v93k/builder.rb +89 -89
  187. data/lib/origen_testers/smartest_based_tester/v93k/builder/flow.rb +181 -181
  188. data/lib/origen_testers/smartest_based_tester/v93k/builder/pattern_master.rb +54 -54
  189. data/lib/origen_testers/smartest_based_tester/v93k/flow.rb +10 -10
  190. data/lib/origen_testers/smartest_based_tester/v93k/generator.rb +19 -19
  191. data/lib/origen_testers/smartest_based_tester/v93k/pattern_compiler.rb +10 -10
  192. data/lib/origen_testers/smartest_based_tester/v93k/pattern_master.rb +10 -10
  193. data/lib/origen_testers/smartest_based_tester/v93k/templates/template.aiv.erb +17 -17
  194. data/lib/origen_testers/smartest_based_tester/v93k/templates/template.pmfl.erb +13 -13
  195. data/lib/origen_testers/smartest_based_tester/v93k/templates/template.tf.erb +214 -214
  196. data/lib/origen_testers/smartest_based_tester/v93k/templates/vars.tf.erb +48 -48
  197. data/lib/origen_testers/smartest_based_tester/v93k/test_method.rb +9 -9
  198. data/lib/origen_testers/smartest_based_tester/v93k/test_methods.rb +9 -9
  199. data/lib/origen_testers/smartest_based_tester/v93k/test_suite.rb +9 -9
  200. data/lib/origen_testers/smartest_based_tester/v93k/test_suites.rb +9 -9
  201. data/lib/origen_testers/smartest_based_tester/v93k/variables_file.rb +10 -10
  202. data/lib/origen_testers/test/basic_interface.rb +17 -17
  203. data/lib/origen_testers/test/block.rb +21 -21
  204. data/lib/origen_testers/test/custom_test_interface.rb +111 -111
  205. data/lib/origen_testers/test/dut.rb +295 -295
  206. data/lib/origen_testers/test/dut2.rb +76 -76
  207. data/lib/origen_testers/test/dut3.rb +244 -244
  208. data/lib/origen_testers/test/interface.rb +503 -503
  209. data/lib/origen_testers/test/nvm.rb +94 -94
  210. data/lib/origen_testers/timing.rb +362 -362
  211. data/lib/origen_testers/vector.rb +207 -207
  212. data/lib/origen_testers/vector_based_tester.rb +41 -41
  213. data/lib/origen_testers/vector_generator.rb +655 -655
  214. data/lib/origen_testers/vector_pipeline.rb +302 -302
  215. data/pattern/bitmap.rb +7 -7
  216. data/pattern/dc_instr.rb +7 -7
  217. data/pattern/delay.rb +7 -7
  218. data/pattern/freq_counter.rb +6 -6
  219. data/pattern/mem_test.rb +8 -8
  220. data/pattern/multi_vector.rb +122 -122
  221. data/pattern/multi_vector_plus1.rb +125 -125
  222. data/pattern/nvm/j750/add_late_pins.rb +3 -3
  223. data/pattern/nvm/j750/iterator_postfix_test_x_bx.rb +8 -8
  224. data/pattern/nvm/j750/iterator_test_x_bx.rb +8 -8
  225. data/pattern/nvm/j750/j750_halt.rb +159 -159
  226. data/pattern/nvm/j750/j750_workout.rb +209 -209
  227. data/pattern/nvm/j750/timing.rb +73 -73
  228. data/pattern/read_write_reg.rb +61 -61
  229. data/pattern/reset.rb +4 -4
  230. data/pattern/subroutines.rb +69 -69
  231. data/pattern/tester_overlay.rb +52 -52
  232. data/pattern/tester_store.rb +28 -28
  233. data/program/_additional_erase.rb +7 -7
  234. data/program/_efa_resources.rb +7 -7
  235. data/program/_erase.rb +25 -25
  236. data/program/_erase_vfy.rb +5 -5
  237. data/program/_iv_resources.rb +10 -10
  238. data/program/basic_interface.rb +5 -5
  239. data/program/components/_prb1_main.rb +212 -0
  240. data/program/components/_temp.rb +6 -6
  241. data/program/custom_tests.rb +10 -10
  242. data/program/flow_control.rb +329 -321
  243. data/program/prb1.rb +11 -219
  244. data/program/prb1_resources.rb +28 -28
  245. data/program/prb2.rb +27 -27
  246. data/program/test.rb +29 -29
  247. data/program/uflex_resources.rb +199 -199
  248. data/templates/example.txt.erb +53 -53
  249. data/templates/j750/program_sheet.txt.erb +9 -9
  250. data/templates/manifest/v93k.yaml.erb +22 -22
  251. data/templates/web/index.md.erb +51 -51
  252. data/templates/web/layouts/_basic.html.erb +15 -15
  253. data/templates/web/partials/_navbar.html.erb +22 -22
  254. data/templates/web/release_notes.md.erb +5 -5
  255. metadata +6 -5
@@ -1,62 +1,62 @@
1
- require 'active_support/concern'
2
- module OrigenTesters
3
- # Include this module to create an interface that supports multiple tester
4
- # types.
5
- #
6
- # This module will expose generators for all test platforms supported by
7
- # the Testers plugin.
8
- module ProgramGenerators
9
- extend ActiveSupport::Concern
10
- include Interface
11
-
12
- PLATFORMS = [J750, J750_HPT, UltraFLEX, V93K]
13
-
14
- included do
15
- Origen.add_interface(self)
16
- end
17
-
18
- module ClassMethods
19
- # Ensures that the correct generator is loaded before initialize is called
20
- def new(*args, &block)
21
- x = allocate
22
- x._load_generator
23
- x.send(:initialize, *args, &block)
24
- x
25
- end
26
-
27
- # Returns true if the interface class supports the
28
- # given tester instance
29
- def supports?(tester_instance)
30
- PLATFORMS.include?(tester_instance.class)
31
- end
32
- end
33
-
34
- # @api private
35
- def pre_initialize(options = {})
36
- _load_generator
37
- end
38
-
39
- def initialize(options = {})
40
- end
41
-
42
- def tester
43
- Origen.tester
44
- end
45
-
46
- def _load_generator
47
- if tester.v93k?
48
- class << self; include OrigenTesters::V93K::Generator; end
49
- elsif tester.j750_hpt?
50
- class << self; include OrigenTesters::J750_HPT::Generator; end
51
- elsif tester.j750?
52
- class << self; include OrigenTesters::J750::Generator; end
53
- elsif tester.ultraflex?
54
- class << self; include OrigenTesters::UltraFLEX::Generator; end
55
- elsif defined? tester.class::TEST_PROGRAM_GENERATOR
56
- class << self; include tester.class::TEST_PROGRAM_GENERATOR; end
57
- else
58
- fail "The OrigenTesters::ProgramGenerators module does not support #{tester.class}!"
59
- end
60
- end
61
- end
62
- end
1
+ require 'active_support/concern'
2
+ module OrigenTesters
3
+ # Include this module to create an interface that supports multiple tester
4
+ # types.
5
+ #
6
+ # This module will expose generators for all test platforms supported by
7
+ # the Testers plugin.
8
+ module ProgramGenerators
9
+ extend ActiveSupport::Concern
10
+ include Interface
11
+
12
+ PLATFORMS = [J750, J750_HPT, UltraFLEX, V93K]
13
+
14
+ included do
15
+ Origen.add_interface(self)
16
+ end
17
+
18
+ module ClassMethods
19
+ # Ensures that the correct generator is loaded before initialize is called
20
+ def new(*args, &block)
21
+ x = allocate
22
+ x._load_generator
23
+ x.send(:initialize, *args, &block)
24
+ x
25
+ end
26
+
27
+ # Returns true if the interface class supports the
28
+ # given tester instance
29
+ def supports?(tester_instance)
30
+ PLATFORMS.include?(tester_instance.class)
31
+ end
32
+ end
33
+
34
+ # @api private
35
+ def pre_initialize(options = {})
36
+ _load_generator
37
+ end
38
+
39
+ def initialize(options = {})
40
+ end
41
+
42
+ def tester
43
+ Origen.tester
44
+ end
45
+
46
+ def _load_generator
47
+ if tester.v93k?
48
+ class << self; include OrigenTesters::V93K::Generator; end
49
+ elsif tester.j750_hpt?
50
+ class << self; include OrigenTesters::J750_HPT::Generator; end
51
+ elsif tester.j750?
52
+ class << self; include OrigenTesters::J750::Generator; end
53
+ elsif tester.ultraflex?
54
+ class << self; include OrigenTesters::UltraFLEX::Generator; end
55
+ elsif defined? tester.class::TEST_PROGRAM_GENERATOR
56
+ class << self; include tester.class::TEST_PROGRAM_GENERATOR; end
57
+ else
58
+ fail "The OrigenTesters::ProgramGenerators module does not support #{tester.class}!"
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1,8 +1,8 @@
1
- module OrigenTesters
2
- module SmartestBasedTester
3
- autoload :Base, 'origen_testers/smartest_based_tester/base'
4
- autoload :V93K, 'origen_testers/smartest_based_tester/v93k'
5
- end
6
- # Convenience/Legacy names without the SmartestBasedTester namespace
7
- autoload :V93K, 'origen_testers/smartest_based_tester/v93k'
8
- end
1
+ module OrigenTesters
2
+ module SmartestBasedTester
3
+ autoload :Base, 'origen_testers/smartest_based_tester/base'
4
+ autoload :V93K, 'origen_testers/smartest_based_tester/v93k'
5
+ end
6
+ # Convenience/Legacy names without the SmartestBasedTester namespace
7
+ autoload :V93K, 'origen_testers/smartest_based_tester/v93k'
8
+ end
@@ -1,562 +1,562 @@
1
- module OrigenTesters
2
- module SmartestBasedTester
3
- class Base
4
- include VectorBasedTester
5
-
6
- # Disable inline (end of vector) comments, enabled by default
7
- attr_accessor :inline_comments
8
-
9
- # Returns whether the tester has been configured to wrap top-level flow modules with an
10
- # enable or not.
11
- #
12
- # Returns nil if not.
13
- #
14
- # Returns :enabled if the enable is configured to be on by default, or :disabled if it is
15
- # configured to be off by default.
16
- attr_reader :add_flow_enable
17
-
18
- def initialize(options = {})
19
- @max_repeat_loop = 65_535
20
- @min_repeat_loop = 33
21
- @pat_extension = 'avc'
22
- @compress = true
23
- # @support_repeat_previous = true
24
- @match_entries = 10
25
- @name = 'v93k'
26
- @comment_char = '#'
27
- @level_period = true
28
- @inline_comments = true
29
- @overlay_style = :subroutine # default to use subroutine for overlay
30
- @capture_style = :hram # default to use hram for capture
31
- @overlay_subr = nil
32
-
33
- if options[:add_flow_enable]
34
- self.add_flow_enable = options[:add_flow_enable]
35
- end
36
- end
37
-
38
- # Set to :enabled to have all top-level flow modules wrapped by an enable flow variable
39
- # that is enabled by default (top-level flow has to disable modules it doesn't want).
40
- #
41
- # Set to :disabled to have the opposite, where the top-level flow has to enable all
42
- # modules.
43
- #
44
- # Note that the interface can override this setting for each flow during program generation.
45
- def add_flow_enable=(value)
46
- if value == :enable || value == :enabled
47
- @add_flow_enable = :enabled
48
- elsif value == :disable || value == :disabled
49
- @add_flow_enable = :disabled
50
- else
51
- fail "Unknown add_flow_enable value, #{value}, must be :enabled or :disabled"
52
- end
53
- end
54
-
55
- def cycle(options = {})
56
- # handle overlay if requested
57
- ovly_style = nil
58
- if options.key?(:overlay)
59
- ovly_style = options[:overlay][:overlay_style].nil? ? @overlay_style : options[:overlay][:overlay_style]
60
- overlay_str = options[:overlay][:overlay_str]
61
-
62
- # route the overlay request to the appropriate method
63
- case ovly_style
64
- when :subroutine, :default
65
- subroutine_overlay(overlay_str, options)
66
- ovly_style = :subroutine
67
- else
68
- ovly_style = overlay_style_warn(options[:overlay][:overlay_str], options)
69
- end # case ovly_style
70
- else
71
- @overlay_subr = nil
72
- end # of handle overlay
73
-
74
- options_overlay = options.delete(:overlay) if options.key?(:overlay)
75
-
76
- super(options) unless ovly_style == :subroutine
77
-
78
- unless options_overlay.nil?
79
- # stage = :body if ovly_style == :subroutine # always set stage back to body in case subr overlay was selected
80
- end
81
- end
82
-
83
- # Warn user of unsupported overlay style
84
- def overlay_style_warn(overlay_str, options)
85
- Origen.log.warn("Unrecognized overlay style :#{@overlay_style}, defaulting to subroutine")
86
- Origen.log.warn('Available overlay styles :subroutine')
87
- subroutine_overlay(overlay_str, options)
88
- @overlay_style = :subroutine # Just give 1 warning
89
- end
90
-
91
- # Implement subroutine overlay, called by tester.cycle
92
- def subroutine_overlay(sub_name, options = {})
93
- if @overlay_subr != sub_name
94
- # unless last staged vector already has the subr call do the following
95
- i = -1
96
- i -= 1 until stage.bank[i].is_a?(OrigenTesters::Vector)
97
- if stage.bank[i].microcode !~ /#{sub_name}/
98
-
99
- # check for repeat on new last vector, unroll 1 if needed
100
- if stage.bank[i].repeat > 1
101
- v = OrigenTesters::Vector.new
102
- v.pin_vals = stage.bank[i].pin_vals
103
- v.timeset = stage.bank[i].timeset
104
- stage.bank[i].repeat -= 1
105
- stage.store(v)
106
- i = -1
107
- end
108
-
109
- # mark last vector as dont_compress
110
- stage.bank[i].dont_compress = true
111
- # insert subroutine call
112
- call_subroutine sub_name
113
- end # if microcode not placed
114
- @overlay_subr = sub_name
115
- end
116
-
117
- # stage = sub_name
118
- end # subroutine_overlay
119
-
120
- # Capture the pin data from a vector to the tester.
121
- #
122
- # This method uses the Digital Capture feature (Selective mode) of the V93000 to capture
123
- # the data from the given pins on the previous vector.
124
- # Note that is does not actually generate a new vector.
125
- #
126
- # Note also that any drive cycles on the target pins can also be captured, to avoid this
127
- # the wavetable should be set up like this to infer a 'D' (Don't Capture) on vectors where
128
- # the target pin is being used to drive data:
129
- #
130
- # PINS nvm_fail
131
- # 0 d1:0 r1:D 0
132
- # 1 d1:1 r1:D 1
133
- # 2 r1:C Capt
134
- # 3 r1:D NoCapt
135
- #
136
- # Sometimes when generating vectors within a loop you may want to apply a capture
137
- # retrospectively to a previous vector, passing in an offset option will allow you
138
- # to do this.
139
- #
140
- # ==== Examples
141
- # $tester.cycle # This is the vector you want to capture
142
- # $tester.store :pin => pin(:fail) # This applys the required opcode to the given pins
143
- #
144
- # $tester.cycle # This one gets captured
145
- # $tester.cycle
146
- # $tester.cycle
147
- # $tester.store(:pin => pin(:fail), :offset => -2) # Just realized I need to capture that earlier vector
148
- #
149
- # # Capturing multiple pins:
150
- # $tester.cycle
151
- # $tester.store :pins => [pin(:fail), pin(:done)]
152
- #
153
- # Since the V93K store operates on a pin level (rather than vector level as on the J750)
154
- # equivalent functionality can also be achieved by setting the store attribute of the pin
155
- # itself prior to calling $tester.cycle.
156
- # However it is recommended to use the tester API to do the store if cross-compatiblity with
157
- # other platforms, such as the J750, is required.
158
- def store(*pins)
159
- options = pins.last.is_a?(Hash) ? pins.pop : {}
160
- options = { offset: 0
161
- }.merge(options)
162
- pins = pins.flatten.compact
163
- if pins.empty?
164
- fail 'For the V93K you must supply the pins to store/capture'
165
- end
166
- pins.each do |pin|
167
- pin.restore_state do
168
- pin.capture
169
- update_vector_pin_val pin, offset: options[:offset]
170
- last_vector(options[:offset]).dont_compress = true
171
- last_vector(options[:offset]).contains_capture = true
172
- end
173
- end
174
- end
175
- alias_method :capture, :store
176
-
177
- # Same as the store method, except that the capture will be applied to the next
178
- # vector to be generated.
179
- #
180
- # @example
181
- # $tester.store_next_cycle
182
- # $tester.cycle # This is the vector that will be captured
183
- def store_next_cycle(*pins)
184
- options = pins.last.is_a?(Hash) ? pins.pop : {}
185
- options = {
186
- }.merge(options)
187
- pins = pins.flatten.compact
188
- if pins.empty?
189
- fail 'For the V93K you must supply the pins to store/capture'
190
- end
191
- pins.each { |pin| pin.save; pin.capture }
192
- # Register this clean up function to be run after the next vector
193
- # is generated, cool or what!
194
- preset_next_vector do |vector|
195
- vector.contains_capture = true
196
- pins.each(&:restore)
197
- end
198
- end
199
- alias_method :store!, :store_next_cycle
200
-
201
- # Start a subroutine.
202
- #
203
- # Generates a global subroutine label. Global is used to adhere to the best practice of
204
- # containing all subroutines in dedicated patterns, e.g. global_subs.atp
205
- #
206
- # ==== Examples
207
- # $tester.start_subroutine("wait_for_done")
208
- # < generate your subroutine vectors here >
209
- # $tester.end_subroutine
210
- def start_subroutine(name)
211
- local_subroutines << name.to_s.chomp unless local_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
212
- # name += "_subr" unless name =~ /sub/
213
- Pattern.open name: name, call_startup_callbacks: false, subroutine: true
214
- end
215
-
216
- # Ends the current subroutine that was started with a previous call to start_subroutine
217
- def end_subroutine(_cond = false)
218
- Pattern.close call_shutdown_callbacks: false, subroutine: true
219
- end
220
-
221
- # Call a subroutine.
222
- #
223
- # This calls a subroutine immediately following previous vector, it does not
224
- # generate a new vector.
225
- #
226
- # Subroutines should always be called through this method as it ensures a running
227
- # log of called subroutines is maintained and which then gets output in the pattern
228
- # header to import the right dependencies.
229
- #
230
- # An offset option is available to make the call on earlier vectors.
231
- #
232
- # Repeated calls to the same subroutine will automatically be compressed unless
233
- # option :suppress_repeated_calls is supplied and set to false. This means that for
234
- # the common use case of calling a subroutine to implement an overlay the subroutine
235
- # can be called for every bit that has the overlay and the pattern will automatically
236
- # generate correctly.
237
- #
238
- # ==== Examples
239
- # $tester.call_subroutine("mysub")
240
- # $tester.call_subroutine("my_other_sub", :offset => -1)
241
- def call_subroutine(name, options = {})
242
- options = {
243
- offset: 0,
244
- suppress_repeated_calls: true
245
- }.merge(options)
246
- called_subroutines << name.to_s.chomp unless called_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
247
-
248
- code = "SQPG JSUB #{name};"
249
- if !options[:suppress_repeated_calls] ||
250
- last_object != code
251
- microcode code, offset: (options[:offset] * -1)
252
- end
253
- end
254
-
255
- # Handshake with the tester.
256
- #
257
- # ==== Examples
258
- # $tester.handshake # Pass control to the tester for a measurement
259
- def handshake(options = {})
260
- options = {
261
- }.merge(options)
262
- Pattern.split(options)
263
- end
264
-
265
- # Do a frequency measure.
266
- #
267
- # ==== Examples
268
- # $tester.freq_count($top.pin(:d_out)) # Freq measure on pin "d_out"
269
- def freq_count(_pin, options = {})
270
- options = {
271
- }.merge(options)
272
- Pattern.split(options)
273
- end
274
-
275
- # Generates a match loop on up to two pins.
276
- #
277
- # This method is not really intended to be called directly, rather you should call
278
- # via Tester#wait e.g. $tester.wait(:match => true).
279
- #
280
- # The timeout should be provided in cycles, however when called via the wait method the
281
- # time-based helpers (time_in_us, etc) will be converted to cycles for you.
282
- # The following options are available to tailor the match loop behavior, defaults in
283
- # parenthesis:
284
- #
285
- # * :pin - The pin object to match on (*required*)
286
- # * :state - The pin state to match on, :low or :high (*required*)
287
- # * :check_for_fails (false) - Flushes the pipeline and checks for fails prior to the match (to allow binout of fails encountered before the match)
288
- # * :pin2 (nil) - Optionally supply a second pin to match on
289
- # * :state2 (nil) - State for the second pin (required if :pin2 is supplied)
290
- # * :force_fail_on_timeout (true) - Force a vector mis-compare if the match loop times out
291
- #
292
- # ==== Examples
293
- # $tester.wait(:match => true, :time_in_us => 5000, :pin => $top.pin(:done), :state => :high)
294
- def match(pin, state, timeout_in_cycles, options = {})
295
- options = {
296
- check_for_fails: false,
297
- pin2: false,
298
- state2: false,
299
- global_loops: false,
300
- generate_subroutine: false,
301
- force_fail_on_timeout: true
302
- }.merge(options)
303
-
304
- # Ensure the match pins are don't care by default
305
- pin.dont_care
306
- options[:pin2].dont_care if options[:pin2]
307
-
308
- # Single condition loops are simple
309
- if !options[:pin2]
310
- # Use the counted match loop (rather than timed) which is recommended in the V93K docs for new applications
311
- # No pre-match failure handling is required here because the system will cleanly record failure info
312
- # for this kind of match loop
313
- cc "for the #{pin.name.upcase} pin to go #{state.to_s.upcase}"
314
- # Need to ensure at least 8 cycles with no compares before entering
315
- 8.cycles
316
- number_of_loops = (timeout_in_cycles.to_f / 72).ceil
317
- # This seems to be a limit on the max MACT value, so account for longer times by expanding
318
- # the wait loop
319
- if number_of_loops > 262_144
320
- mrpt = ((timeout_in_cycles.to_f / 262_144) - 8).ceil
321
- mrpt = Math.sqrt(mrpt).ceil
322
- mrpt += (8 - (mrpt % 8)) # Keep to a multiple of 8, but round up to be safe
323
- number_of_loops = 262_144
324
- else
325
- mrpt = 8
326
- end
327
- microcode "SQPG MACT #{number_of_loops};"
328
- # Strobe the pin for the required state
329
- state == :low ? pin.expect_lo : pin.expect_hi
330
- # Always do 8 vectors here as this allows reconstruction of test results if multiple loops
331
- # are called in a pattern
332
- 8.cycles
333
- pin.dont_care
334
- # Now do the wait loop, mrpt should always be a multiple of 8
335
- microcode "SQPG MRPT #{mrpt};"
336
- mrpt.times do
337
- cycle(dont_compress: true)
338
- end
339
- microcode 'SQPG PADDING;'
340
- 8.cycles
341
-
342
- else
343
-
344
- # For two pins do something more like the J750 approach where branching based on miscompares is used
345
- # to keep the loop going
346
- cc "for the #{pin.name.upcase} pin to go #{state.to_s.upcase}"
347
- cc "or the #{options[:pin2].name.upcase} pin to go #{options[:state2].to_s.upcase}"
348
-
349
- if options[:check_for_fails]
350
- cc 'Return preserving existing errors if the pattern has already failed before arriving here'
351
- cycle(repeat: propagation_delay)
352
- microcode 'SQPG RETC 1 1;'
353
- end
354
- number_of_loops = (timeout_in_cycles.to_f / ((propagation_delay * 2) + 2)).ceil
355
-
356
- loop_vectors number_of_loops do
357
- # Check pin 1
358
- cc "Check if #{pin.name.upcase} is #{state.to_s.upcase} yet"
359
- state == :low ? pin.expect_lo! : pin.expect_hi!
360
- pin.dont_care
361
- cc 'Wait for failure to propagate'
362
- cycle(repeat: propagation_delay)
363
- cc 'Exit match loop if pin has matched (no error), otherwise clear error and remain in loop'
364
- microcode 'SQPG RETC 0 0;'
365
-
366
- # Check pin 2
367
- cc "Check if #{options[:pin2].name.upcase} is #{options[:state2].to_s.upcase} yet"
368
- options[:state2] == :low ? options[:pin2].expect_lo! : options[:pin2].expect_hi!
369
- options[:pin2].dont_care
370
- cc 'Wait for failure to propagate'
371
- cycle(repeat: propagation_delay)
372
- cc 'Exit match loop if pin has matched (no error), otherwise clear error and remain in loop'
373
- microcode 'SQPG RETC 0 0;'
374
- end
375
-
376
- if options[:force_fail_on_timeout]
377
- cc 'To get here something has gone wrong, strobe again to force a pattern failure'
378
- state == :low ? pin.expect_lo : pin.expect_hi
379
- options[:state2] == :low ? options[:pin2].expect_lo : options[:pin2].expect_hi if options[:pin2]
380
- cycle
381
- pin.dont_care
382
- options[:pin2].dont_care if options[:pin2]
383
- end
384
- end
385
- end
386
-
387
- # Returns the number of cycles to wait for any fails to propagate through the pipeline based on
388
- # the current timeset
389
- def propagation_delay
390
- # From 'Calculating the buffer cycles for JMPE and RETC (and match loops)' in SmarTest docs
391
- data_queue_buffer = (([105, 64 + ((125 + current_period_in_ns - 1) / current_period_in_ns).ceil].min + 3) * 8) + 72
392
- # Don't know how to calculate at runtime, hardcoding these to some default values for now
393
- number_of_sites = 128
394
- sclk_period = 40
395
- prop_delay_buffer = 195 + ((2 * number_of_sites + 3) * (sclk_period / 2))
396
- data_queue_buffer + prop_delay_buffer
397
- end
398
-
399
- # Add a loop to the pattern.
400
- #
401
- # Pass in the number of times to execute it, all vectors
402
- # generated by the given block will be captured in the loop.
403
- #
404
- # ==== Examples
405
- # $tester.loop_vectors 3 do # Do this 3 times...
406
- # $tester.cycle
407
- # some_other_method_to_generate_vectors
408
- # end
409
- #
410
- # For compatibility with the J750 you can supply a name as the first argument
411
- # and that will simply be ignored when generated for the V93K tester...
412
- #
413
- # $tester.loop_vectors "my_loop", 3 do # Do this 3 times...
414
- # $tester.cycle
415
- # some_other_method_to_generate_vectors
416
- # end
417
- def loop_vectors(name = nil, number_of_loops = 1, _global = false)
418
- # The name argument is present to maych J750 API, sort out the
419
- unless name.is_a?(String)
420
- name, number_of_loops, global = nil, name, number_of_loops
421
- end
422
- if number_of_loops > 1
423
- microcode "SQPG LBGN #{number_of_loops};"
424
- yield
425
- microcode 'SQPG LEND;'
426
- else
427
- yield
428
- end
429
- end
430
- alias_method :loop_vector, :loop_vectors
431
-
432
- # An internal method called by Origen to create the pattern header
433
- def pattern_header(options = {})
434
- options = {
435
- }.merge(options)
436
- pin_list = ordered_pins.map do |p|
437
- if Origen.app.pin_pattern_order.include?(p.id)
438
- # specified name overrides pin name
439
- if (p.is_a?(Origen::Pins::PinCollection)) || p.id != p.name
440
- p.id.to_s # groups or aliases can be lower case
441
- else
442
- p.id.to_s.upcase # pins must be uppercase
443
- end
444
- else
445
- if (p.is_a?(Origen::Pins::PinCollection)) || p.id != p.name
446
- p.name.to_s # groups or aliases can be lower case
447
- else
448
- p.name.to_s.upcase # pins must be uppercase
449
- end
450
- end
451
- end.join(' ')
452
- microcode "FORMAT #{pin_list};"
453
- if ordered_pins.size > 0
454
- max_pin_name_length = ordered_pins.map(&:name).max { |a, b| a.length <=> b.length }.length
455
- pin_widths = ordered_pins.map { |p| p.size - 1 }
456
-
457
- max_pin_name_length.times do |i|
458
- cc((' ' * 50) + ordered_pins.map.with_index { |p, x| ((p.name[i] || ' ') + ' ' * pin_widths[x]).gsub('_', '-') }.join(' '))
459
- end
460
- end
461
- end
462
-
463
- # An internal method called by Origen to generate the pattern footer
464
- def pattern_footer(options = {})
465
- options = {
466
- end_in_ka: false
467
- }.merge(options)
468
- if options[:end_in_ka]
469
- Origen.log.warning '93K keep alive not yet implemented!'
470
- ss 'WARNING: 93K keep alive not yet implemented!'
471
- end
472
- microcode 'SQPG STOP;' unless options[:subroutine]
473
- end
474
-
475
- # Returns an array of subroutines called while generating the current pattern
476
- def called_subroutines
477
- @called_subroutines ||= []
478
- end
479
-
480
- # Returns an array of subroutines created by the current pattern
481
- def local_subroutines # :nodoc:
482
- @local_subroutines ||= []
483
- end
484
-
485
- # This is an internal method use by Origen which returns a fully formatted vector
486
- # You can override this if you wish to change the output formatting at vector level
487
- def format_vector(vec)
488
- timeset = vec.timeset ? "#{vec.timeset.name}" : ''
489
- pin_vals = vec.pin_vals ? "#{vec.pin_vals} " : ''
490
- if vec.repeat # > 1
491
- microcode = "R#{vec.repeat}"
492
- else
493
- microcode = vec.microcode ? vec.microcode : ''
494
- end
495
-
496
- if Origen.mode.simulation? || !inline_comments || $_testers_no_inline_comments
497
- comment = ''
498
- else
499
-
500
- header_comments = []
501
- repeat_comment = ''
502
- vec.comments.each_with_index do |comment, i|
503
- if comment =~ /^#/
504
- if comment =~ /^#(R\d+)$/
505
- repeat_comment = Regexp.last_match(1) + ' '
506
- # Throw away the ############# headers and footers
507
- elsif comment !~ /^# ####################/
508
- comment = comment.strip.sub(/^# (## )?/, '')
509
- if comment == ''
510
- # Throw away empty lines at the start/end, but preserve them in the middle
511
- unless header_comments.empty? || i == vec.comments.size - 1
512
- header_comments << comment
513
- end
514
- else
515
- header_comments << comment
516
- end
517
- end
518
- end
519
- end
520
-
521
- if vec.pin_vals && ($_testers_enable_vector_comments || vector_comments)
522
- comment = "#{vec.number}:#{vec.cycle}"
523
- comment += ': ' if !header_comments.empty? || !vec.inline_comment.empty?
524
- else
525
- comment = ''
526
- end
527
- comment += header_comments.join("\cm") unless header_comments.empty?
528
- unless vec.inline_comment.empty?
529
- comment += "\cm" unless header_comments.empty?
530
- comment += "(#{vec.inline_comment})"
531
- end
532
- comment = "#{repeat_comment}#{comment}"
533
- end
534
-
535
- # Max comment length 250 at the end
536
- "#{microcode.ljust(25)}#{timeset.ljust(27)}#{pin_vals}# #{comment[0, 247]};"
537
- end
538
-
539
- # All vectors generated with the supplied block will have all pins set
540
- # to the repeat previous state. Any pins that are changed state within
541
- # the block will still update to the supplied value.
542
- # ==== Example
543
- # # All pins except invoke will be assigned the repeat previous code
544
- # # in the generated vector. On completion of the block they will
545
- # # return to their previous state, except for invoke which will
546
- # # retain the value assigned within the block.
547
- # $tester.repeat_previous do
548
- # $top.pin(:invoke).drive(1)
549
- # $tester.cycle
550
- # end
551
- def repeat_previous
552
- Origen.app.pin_map.each { |_id, pin| pin.repeat_previous = true }
553
- yield
554
- Origen.app.pin_map.each { |_id, pin| pin.repeat_previous = false }
555
- end
556
-
557
- def before_timeset_change(options = {})
558
- microcode "SQPG CTIM #{options[:new].name};" unless level_period?
559
- end
560
- end
561
- end
562
- end
1
+ module OrigenTesters
2
+ module SmartestBasedTester
3
+ class Base
4
+ include VectorBasedTester
5
+
6
+ # Disable inline (end of vector) comments, enabled by default
7
+ attr_accessor :inline_comments
8
+
9
+ # Returns whether the tester has been configured to wrap top-level flow modules with an
10
+ # enable or not.
11
+ #
12
+ # Returns nil if not.
13
+ #
14
+ # Returns :enabled if the enable is configured to be on by default, or :disabled if it is
15
+ # configured to be off by default.
16
+ attr_reader :add_flow_enable
17
+
18
+ def initialize(options = {})
19
+ @max_repeat_loop = 65_535
20
+ @min_repeat_loop = 33
21
+ @pat_extension = 'avc'
22
+ @compress = true
23
+ # @support_repeat_previous = true
24
+ @match_entries = 10
25
+ @name = 'v93k'
26
+ @comment_char = '#'
27
+ @level_period = true
28
+ @inline_comments = true
29
+ @overlay_style = :subroutine # default to use subroutine for overlay
30
+ @capture_style = :hram # default to use hram for capture
31
+ @overlay_subr = nil
32
+
33
+ if options[:add_flow_enable]
34
+ self.add_flow_enable = options[:add_flow_enable]
35
+ end
36
+ end
37
+
38
+ # Set to :enabled to have all top-level flow modules wrapped by an enable flow variable
39
+ # that is enabled by default (top-level flow has to disable modules it doesn't want).
40
+ #
41
+ # Set to :disabled to have the opposite, where the top-level flow has to enable all
42
+ # modules.
43
+ #
44
+ # Note that the interface can override this setting for each flow during program generation.
45
+ def add_flow_enable=(value)
46
+ if value == :enable || value == :enabled
47
+ @add_flow_enable = :enabled
48
+ elsif value == :disable || value == :disabled
49
+ @add_flow_enable = :disabled
50
+ else
51
+ fail "Unknown add_flow_enable value, #{value}, must be :enabled or :disabled"
52
+ end
53
+ end
54
+
55
+ def cycle(options = {})
56
+ # handle overlay if requested
57
+ ovly_style = nil
58
+ if options.key?(:overlay)
59
+ ovly_style = options[:overlay][:overlay_style].nil? ? @overlay_style : options[:overlay][:overlay_style]
60
+ overlay_str = options[:overlay][:overlay_str]
61
+
62
+ # route the overlay request to the appropriate method
63
+ case ovly_style
64
+ when :subroutine, :default
65
+ subroutine_overlay(overlay_str, options)
66
+ ovly_style = :subroutine
67
+ else
68
+ ovly_style = overlay_style_warn(options[:overlay][:overlay_str], options)
69
+ end # case ovly_style
70
+ else
71
+ @overlay_subr = nil
72
+ end # of handle overlay
73
+
74
+ options_overlay = options.delete(:overlay) if options.key?(:overlay)
75
+
76
+ super(options) unless ovly_style == :subroutine
77
+
78
+ unless options_overlay.nil?
79
+ # stage = :body if ovly_style == :subroutine # always set stage back to body in case subr overlay was selected
80
+ end
81
+ end
82
+
83
+ # Warn user of unsupported overlay style
84
+ def overlay_style_warn(overlay_str, options)
85
+ Origen.log.warn("Unrecognized overlay style :#{@overlay_style}, defaulting to subroutine")
86
+ Origen.log.warn('Available overlay styles :subroutine')
87
+ subroutine_overlay(overlay_str, options)
88
+ @overlay_style = :subroutine # Just give 1 warning
89
+ end
90
+
91
+ # Implement subroutine overlay, called by tester.cycle
92
+ def subroutine_overlay(sub_name, options = {})
93
+ if @overlay_subr != sub_name
94
+ # unless last staged vector already has the subr call do the following
95
+ i = -1
96
+ i -= 1 until stage.bank[i].is_a?(OrigenTesters::Vector)
97
+ if stage.bank[i].microcode !~ /#{sub_name}/
98
+
99
+ # check for repeat on new last vector, unroll 1 if needed
100
+ if stage.bank[i].repeat > 1
101
+ v = OrigenTesters::Vector.new
102
+ v.pin_vals = stage.bank[i].pin_vals
103
+ v.timeset = stage.bank[i].timeset
104
+ stage.bank[i].repeat -= 1
105
+ stage.store(v)
106
+ i = -1
107
+ end
108
+
109
+ # mark last vector as dont_compress
110
+ stage.bank[i].dont_compress = true
111
+ # insert subroutine call
112
+ call_subroutine sub_name
113
+ end # if microcode not placed
114
+ @overlay_subr = sub_name
115
+ end
116
+
117
+ # stage = sub_name
118
+ end # subroutine_overlay
119
+
120
+ # Capture the pin data from a vector to the tester.
121
+ #
122
+ # This method uses the Digital Capture feature (Selective mode) of the V93000 to capture
123
+ # the data from the given pins on the previous vector.
124
+ # Note that is does not actually generate a new vector.
125
+ #
126
+ # Note also that any drive cycles on the target pins can also be captured, to avoid this
127
+ # the wavetable should be set up like this to infer a 'D' (Don't Capture) on vectors where
128
+ # the target pin is being used to drive data:
129
+ #
130
+ # PINS nvm_fail
131
+ # 0 d1:0 r1:D 0
132
+ # 1 d1:1 r1:D 1
133
+ # 2 r1:C Capt
134
+ # 3 r1:D NoCapt
135
+ #
136
+ # Sometimes when generating vectors within a loop you may want to apply a capture
137
+ # retrospectively to a previous vector, passing in an offset option will allow you
138
+ # to do this.
139
+ #
140
+ # ==== Examples
141
+ # $tester.cycle # This is the vector you want to capture
142
+ # $tester.store :pin => pin(:fail) # This applys the required opcode to the given pins
143
+ #
144
+ # $tester.cycle # This one gets captured
145
+ # $tester.cycle
146
+ # $tester.cycle
147
+ # $tester.store(:pin => pin(:fail), :offset => -2) # Just realized I need to capture that earlier vector
148
+ #
149
+ # # Capturing multiple pins:
150
+ # $tester.cycle
151
+ # $tester.store :pins => [pin(:fail), pin(:done)]
152
+ #
153
+ # Since the V93K store operates on a pin level (rather than vector level as on the J750)
154
+ # equivalent functionality can also be achieved by setting the store attribute of the pin
155
+ # itself prior to calling $tester.cycle.
156
+ # However it is recommended to use the tester API to do the store if cross-compatiblity with
157
+ # other platforms, such as the J750, is required.
158
+ def store(*pins)
159
+ options = pins.last.is_a?(Hash) ? pins.pop : {}
160
+ options = { offset: 0
161
+ }.merge(options)
162
+ pins = pins.flatten.compact
163
+ if pins.empty?
164
+ fail 'For the V93K you must supply the pins to store/capture'
165
+ end
166
+ pins.each do |pin|
167
+ pin.restore_state do
168
+ pin.capture
169
+ update_vector_pin_val pin, offset: options[:offset]
170
+ last_vector(options[:offset]).dont_compress = true
171
+ last_vector(options[:offset]).contains_capture = true
172
+ end
173
+ end
174
+ end
175
+ alias_method :capture, :store
176
+
177
+ # Same as the store method, except that the capture will be applied to the next
178
+ # vector to be generated.
179
+ #
180
+ # @example
181
+ # $tester.store_next_cycle
182
+ # $tester.cycle # This is the vector that will be captured
183
+ def store_next_cycle(*pins)
184
+ options = pins.last.is_a?(Hash) ? pins.pop : {}
185
+ options = {
186
+ }.merge(options)
187
+ pins = pins.flatten.compact
188
+ if pins.empty?
189
+ fail 'For the V93K you must supply the pins to store/capture'
190
+ end
191
+ pins.each { |pin| pin.save; pin.capture }
192
+ # Register this clean up function to be run after the next vector
193
+ # is generated, cool or what!
194
+ preset_next_vector do |vector|
195
+ vector.contains_capture = true
196
+ pins.each(&:restore)
197
+ end
198
+ end
199
+ alias_method :store!, :store_next_cycle
200
+
201
+ # Start a subroutine.
202
+ #
203
+ # Generates a global subroutine label. Global is used to adhere to the best practice of
204
+ # containing all subroutines in dedicated patterns, e.g. global_subs.atp
205
+ #
206
+ # ==== Examples
207
+ # $tester.start_subroutine("wait_for_done")
208
+ # < generate your subroutine vectors here >
209
+ # $tester.end_subroutine
210
+ def start_subroutine(name)
211
+ local_subroutines << name.to_s.chomp unless local_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
212
+ # name += "_subr" unless name =~ /sub/
213
+ Pattern.open name: name, call_startup_callbacks: false, subroutine: true
214
+ end
215
+
216
+ # Ends the current subroutine that was started with a previous call to start_subroutine
217
+ def end_subroutine(_cond = false)
218
+ Pattern.close call_shutdown_callbacks: false, subroutine: true
219
+ end
220
+
221
+ # Call a subroutine.
222
+ #
223
+ # This calls a subroutine immediately following previous vector, it does not
224
+ # generate a new vector.
225
+ #
226
+ # Subroutines should always be called through this method as it ensures a running
227
+ # log of called subroutines is maintained and which then gets output in the pattern
228
+ # header to import the right dependencies.
229
+ #
230
+ # An offset option is available to make the call on earlier vectors.
231
+ #
232
+ # Repeated calls to the same subroutine will automatically be compressed unless
233
+ # option :suppress_repeated_calls is supplied and set to false. This means that for
234
+ # the common use case of calling a subroutine to implement an overlay the subroutine
235
+ # can be called for every bit that has the overlay and the pattern will automatically
236
+ # generate correctly.
237
+ #
238
+ # ==== Examples
239
+ # $tester.call_subroutine("mysub")
240
+ # $tester.call_subroutine("my_other_sub", :offset => -1)
241
+ def call_subroutine(name, options = {})
242
+ options = {
243
+ offset: 0,
244
+ suppress_repeated_calls: true
245
+ }.merge(options)
246
+ called_subroutines << name.to_s.chomp unless called_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
247
+
248
+ code = "SQPG JSUB #{name};"
249
+ if !options[:suppress_repeated_calls] ||
250
+ last_object != code
251
+ microcode code, offset: (options[:offset] * -1)
252
+ end
253
+ end
254
+
255
+ # Handshake with the tester.
256
+ #
257
+ # ==== Examples
258
+ # $tester.handshake # Pass control to the tester for a measurement
259
+ def handshake(options = {})
260
+ options = {
261
+ }.merge(options)
262
+ Pattern.split(options)
263
+ end
264
+
265
+ # Do a frequency measure.
266
+ #
267
+ # ==== Examples
268
+ # $tester.freq_count($top.pin(:d_out)) # Freq measure on pin "d_out"
269
+ def freq_count(_pin, options = {})
270
+ options = {
271
+ }.merge(options)
272
+ Pattern.split(options)
273
+ end
274
+
275
+ # Generates a match loop on up to two pins.
276
+ #
277
+ # This method is not really intended to be called directly, rather you should call
278
+ # via Tester#wait e.g. $tester.wait(:match => true).
279
+ #
280
+ # The timeout should be provided in cycles, however when called via the wait method the
281
+ # time-based helpers (time_in_us, etc) will be converted to cycles for you.
282
+ # The following options are available to tailor the match loop behavior, defaults in
283
+ # parenthesis:
284
+ #
285
+ # * :pin - The pin object to match on (*required*)
286
+ # * :state - The pin state to match on, :low or :high (*required*)
287
+ # * :check_for_fails (false) - Flushes the pipeline and checks for fails prior to the match (to allow binout of fails encountered before the match)
288
+ # * :pin2 (nil) - Optionally supply a second pin to match on
289
+ # * :state2 (nil) - State for the second pin (required if :pin2 is supplied)
290
+ # * :force_fail_on_timeout (true) - Force a vector mis-compare if the match loop times out
291
+ #
292
+ # ==== Examples
293
+ # $tester.wait(:match => true, :time_in_us => 5000, :pin => $top.pin(:done), :state => :high)
294
+ def match(pin, state, timeout_in_cycles, options = {})
295
+ options = {
296
+ check_for_fails: false,
297
+ pin2: false,
298
+ state2: false,
299
+ global_loops: false,
300
+ generate_subroutine: false,
301
+ force_fail_on_timeout: true
302
+ }.merge(options)
303
+
304
+ # Ensure the match pins are don't care by default
305
+ pin.dont_care
306
+ options[:pin2].dont_care if options[:pin2]
307
+
308
+ # Single condition loops are simple
309
+ if !options[:pin2]
310
+ # Use the counted match loop (rather than timed) which is recommended in the V93K docs for new applications
311
+ # No pre-match failure handling is required here because the system will cleanly record failure info
312
+ # for this kind of match loop
313
+ cc "for the #{pin.name.upcase} pin to go #{state.to_s.upcase}"
314
+ # Need to ensure at least 8 cycles with no compares before entering
315
+ 8.cycles
316
+ number_of_loops = (timeout_in_cycles.to_f / 72).ceil
317
+ # This seems to be a limit on the max MACT value, so account for longer times by expanding
318
+ # the wait loop
319
+ if number_of_loops > 262_144
320
+ mrpt = ((timeout_in_cycles.to_f / 262_144) - 8).ceil
321
+ mrpt = Math.sqrt(mrpt).ceil
322
+ mrpt += (8 - (mrpt % 8)) # Keep to a multiple of 8, but round up to be safe
323
+ number_of_loops = 262_144
324
+ else
325
+ mrpt = 8
326
+ end
327
+ microcode "SQPG MACT #{number_of_loops};"
328
+ # Strobe the pin for the required state
329
+ state == :low ? pin.expect_lo : pin.expect_hi
330
+ # Always do 8 vectors here as this allows reconstruction of test results if multiple loops
331
+ # are called in a pattern
332
+ 8.cycles
333
+ pin.dont_care
334
+ # Now do the wait loop, mrpt should always be a multiple of 8
335
+ microcode "SQPG MRPT #{mrpt};"
336
+ mrpt.times do
337
+ cycle(dont_compress: true)
338
+ end
339
+ microcode 'SQPG PADDING;'
340
+ 8.cycles
341
+
342
+ else
343
+
344
+ # For two pins do something more like the J750 approach where branching based on miscompares is used
345
+ # to keep the loop going
346
+ cc "for the #{pin.name.upcase} pin to go #{state.to_s.upcase}"
347
+ cc "or the #{options[:pin2].name.upcase} pin to go #{options[:state2].to_s.upcase}"
348
+
349
+ if options[:check_for_fails]
350
+ cc 'Return preserving existing errors if the pattern has already failed before arriving here'
351
+ cycle(repeat: propagation_delay)
352
+ microcode 'SQPG RETC 1 1;'
353
+ end
354
+ number_of_loops = (timeout_in_cycles.to_f / ((propagation_delay * 2) + 2)).ceil
355
+
356
+ loop_vectors number_of_loops do
357
+ # Check pin 1
358
+ cc "Check if #{pin.name.upcase} is #{state.to_s.upcase} yet"
359
+ state == :low ? pin.expect_lo! : pin.expect_hi!
360
+ pin.dont_care
361
+ cc 'Wait for failure to propagate'
362
+ cycle(repeat: propagation_delay)
363
+ cc 'Exit match loop if pin has matched (no error), otherwise clear error and remain in loop'
364
+ microcode 'SQPG RETC 0 0;'
365
+
366
+ # Check pin 2
367
+ cc "Check if #{options[:pin2].name.upcase} is #{options[:state2].to_s.upcase} yet"
368
+ options[:state2] == :low ? options[:pin2].expect_lo! : options[:pin2].expect_hi!
369
+ options[:pin2].dont_care
370
+ cc 'Wait for failure to propagate'
371
+ cycle(repeat: propagation_delay)
372
+ cc 'Exit match loop if pin has matched (no error), otherwise clear error and remain in loop'
373
+ microcode 'SQPG RETC 0 0;'
374
+ end
375
+
376
+ if options[:force_fail_on_timeout]
377
+ cc 'To get here something has gone wrong, strobe again to force a pattern failure'
378
+ state == :low ? pin.expect_lo : pin.expect_hi
379
+ options[:state2] == :low ? options[:pin2].expect_lo : options[:pin2].expect_hi if options[:pin2]
380
+ cycle
381
+ pin.dont_care
382
+ options[:pin2].dont_care if options[:pin2]
383
+ end
384
+ end
385
+ end
386
+
387
+ # Returns the number of cycles to wait for any fails to propagate through the pipeline based on
388
+ # the current timeset
389
+ def propagation_delay
390
+ # From 'Calculating the buffer cycles for JMPE and RETC (and match loops)' in SmarTest docs
391
+ data_queue_buffer = (([105, 64 + ((125 + current_period_in_ns - 1) / current_period_in_ns).ceil].min + 3) * 8) + 72
392
+ # Don't know how to calculate at runtime, hardcoding these to some default values for now
393
+ number_of_sites = 128
394
+ sclk_period = 40
395
+ prop_delay_buffer = 195 + ((2 * number_of_sites + 3) * (sclk_period / 2))
396
+ data_queue_buffer + prop_delay_buffer
397
+ end
398
+
399
+ # Add a loop to the pattern.
400
+ #
401
+ # Pass in the number of times to execute it, all vectors
402
+ # generated by the given block will be captured in the loop.
403
+ #
404
+ # ==== Examples
405
+ # $tester.loop_vectors 3 do # Do this 3 times...
406
+ # $tester.cycle
407
+ # some_other_method_to_generate_vectors
408
+ # end
409
+ #
410
+ # For compatibility with the J750 you can supply a name as the first argument
411
+ # and that will simply be ignored when generated for the V93K tester...
412
+ #
413
+ # $tester.loop_vectors "my_loop", 3 do # Do this 3 times...
414
+ # $tester.cycle
415
+ # some_other_method_to_generate_vectors
416
+ # end
417
+ def loop_vectors(name = nil, number_of_loops = 1, _global = false)
418
+ # The name argument is present to maych J750 API, sort out the
419
+ unless name.is_a?(String)
420
+ name, number_of_loops, global = nil, name, number_of_loops
421
+ end
422
+ if number_of_loops > 1
423
+ microcode "SQPG LBGN #{number_of_loops};"
424
+ yield
425
+ microcode 'SQPG LEND;'
426
+ else
427
+ yield
428
+ end
429
+ end
430
+ alias_method :loop_vector, :loop_vectors
431
+
432
+ # An internal method called by Origen to create the pattern header
433
+ def pattern_header(options = {})
434
+ options = {
435
+ }.merge(options)
436
+ pin_list = ordered_pins.map do |p|
437
+ if Origen.app.pin_pattern_order.include?(p.id)
438
+ # specified name overrides pin name
439
+ if (p.is_a?(Origen::Pins::PinCollection)) || p.id != p.name
440
+ p.id.to_s # groups or aliases can be lower case
441
+ else
442
+ p.id.to_s.upcase # pins must be uppercase
443
+ end
444
+ else
445
+ if (p.is_a?(Origen::Pins::PinCollection)) || p.id != p.name
446
+ p.name.to_s # groups or aliases can be lower case
447
+ else
448
+ p.name.to_s.upcase # pins must be uppercase
449
+ end
450
+ end
451
+ end.join(' ')
452
+ microcode "FORMAT #{pin_list};"
453
+ if ordered_pins.size > 0
454
+ max_pin_name_length = ordered_pins.map(&:name).max { |a, b| a.length <=> b.length }.length
455
+ pin_widths = ordered_pins.map { |p| p.size - 1 }
456
+
457
+ max_pin_name_length.times do |i|
458
+ cc((' ' * 50) + ordered_pins.map.with_index { |p, x| ((p.name[i] || ' ') + ' ' * pin_widths[x]).gsub('_', '-') }.join(' '))
459
+ end
460
+ end
461
+ end
462
+
463
+ # An internal method called by Origen to generate the pattern footer
464
+ def pattern_footer(options = {})
465
+ options = {
466
+ end_in_ka: false
467
+ }.merge(options)
468
+ if options[:end_in_ka]
469
+ Origen.log.warning '93K keep alive not yet implemented!'
470
+ ss 'WARNING: 93K keep alive not yet implemented!'
471
+ end
472
+ microcode 'SQPG STOP;' unless options[:subroutine]
473
+ end
474
+
475
+ # Returns an array of subroutines called while generating the current pattern
476
+ def called_subroutines
477
+ @called_subroutines ||= []
478
+ end
479
+
480
+ # Returns an array of subroutines created by the current pattern
481
+ def local_subroutines # :nodoc:
482
+ @local_subroutines ||= []
483
+ end
484
+
485
+ # This is an internal method use by Origen which returns a fully formatted vector
486
+ # You can override this if you wish to change the output formatting at vector level
487
+ def format_vector(vec)
488
+ timeset = vec.timeset ? "#{vec.timeset.name}" : ''
489
+ pin_vals = vec.pin_vals ? "#{vec.pin_vals} " : ''
490
+ if vec.repeat # > 1
491
+ microcode = "R#{vec.repeat}"
492
+ else
493
+ microcode = vec.microcode ? vec.microcode : ''
494
+ end
495
+
496
+ if Origen.mode.simulation? || !inline_comments || $_testers_no_inline_comments
497
+ comment = ''
498
+ else
499
+
500
+ header_comments = []
501
+ repeat_comment = ''
502
+ vec.comments.each_with_index do |comment, i|
503
+ if comment =~ /^#/
504
+ if comment =~ /^#(R\d+)$/
505
+ repeat_comment = Regexp.last_match(1) + ' '
506
+ # Throw away the ############# headers and footers
507
+ elsif comment !~ /^# ####################/
508
+ comment = comment.strip.sub(/^# (## )?/, '')
509
+ if comment == ''
510
+ # Throw away empty lines at the start/end, but preserve them in the middle
511
+ unless header_comments.empty? || i == vec.comments.size - 1
512
+ header_comments << comment
513
+ end
514
+ else
515
+ header_comments << comment
516
+ end
517
+ end
518
+ end
519
+ end
520
+
521
+ if vec.pin_vals && ($_testers_enable_vector_comments || vector_comments)
522
+ comment = "#{vec.number}:#{vec.cycle}"
523
+ comment += ': ' if !header_comments.empty? || !vec.inline_comment.empty?
524
+ else
525
+ comment = ''
526
+ end
527
+ comment += header_comments.join("\cm") unless header_comments.empty?
528
+ unless vec.inline_comment.empty?
529
+ comment += "\cm" unless header_comments.empty?
530
+ comment += "(#{vec.inline_comment})"
531
+ end
532
+ comment = "#{repeat_comment}#{comment}"
533
+ end
534
+
535
+ # Max comment length 250 at the end
536
+ "#{microcode.ljust(25)}#{timeset.ljust(27)}#{pin_vals}# #{comment[0, 247]};"
537
+ end
538
+
539
+ # All vectors generated with the supplied block will have all pins set
540
+ # to the repeat previous state. Any pins that are changed state within
541
+ # the block will still update to the supplied value.
542
+ # ==== Example
543
+ # # All pins except invoke will be assigned the repeat previous code
544
+ # # in the generated vector. On completion of the block they will
545
+ # # return to their previous state, except for invoke which will
546
+ # # retain the value assigned within the block.
547
+ # $tester.repeat_previous do
548
+ # $top.pin(:invoke).drive(1)
549
+ # $tester.cycle
550
+ # end
551
+ def repeat_previous
552
+ Origen.app.pin_map.each { |_id, pin| pin.repeat_previous = true }
553
+ yield
554
+ Origen.app.pin_map.each { |_id, pin| pin.repeat_previous = false }
555
+ end
556
+
557
+ def before_timeset_change(options = {})
558
+ microcode "SQPG CTIM #{options[:new].name};" unless level_period?
559
+ end
560
+ end
561
+ end
562
+ end