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,23 +1,23 @@
1
- module OrigenTesters
2
- module Generator
3
- class IdentityMap
4
- def initialize
5
- @store = {}
6
- @versions = {}
7
- end
8
-
9
- def current_version_of(obj)
10
- map = map_for(obj)
11
- if map
12
- map[:replaced_by] || map[:instance]
13
- else
14
- obj
15
- end
16
- end
17
-
18
- def map_for(obj)
19
- @store[obj.object_id]
20
- end
21
- end
22
- end
23
- end
1
+ module OrigenTesters
2
+ module Generator
3
+ class IdentityMap
4
+ def initialize
5
+ @store = {}
6
+ @versions = {}
7
+ end
8
+
9
+ def current_version_of(obj)
10
+ map = map_for(obj)
11
+ if map
12
+ map[:replaced_by] || map[:instance]
13
+ else
14
+ obj
15
+ end
16
+ end
17
+
18
+ def map_for(obj)
19
+ @store[obj.object_id]
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,11 +1,11 @@
1
- module OrigenTesters
2
- module Generator
3
- class Placeholder
4
- attr_accessor :type, :file, :options, :id
5
-
6
- def initialize(type, file, options = {})
7
- @type, @file, @options = type, file, options
8
- end
9
- end
10
- end
11
- end
1
+ module OrigenTesters
2
+ module Generator
3
+ class Placeholder
4
+ attr_accessor :type, :file, :options, :id
5
+
6
+ def initialize(type, file, options = {})
7
+ @type, @file, @options = type, file, options
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,23 +1,23 @@
1
- module OrigenTesters
2
- module Generator
3
- class TestNumberer
4
- # Will return a test number for the given test.
5
- #
6
- # @param [Hash] options Options to customize the number generation
7
- # @option options [Integer] :bits (6) The number of bits in the DAC code
8
- # @option options [Float] :range (1.26) The range parameter, see code formula
9
- # @option options [Integer] :offset (0) The o
10
- def test_number_for(test_name, options = {})
11
- options = {
12
-
13
- }.merge(options)
14
- end
15
-
16
- private
17
-
18
- def store_file
19
- @store_file ||= Pathname.new "#{Origen.root}/.test_program/test_numbers"
20
- end
21
- end
22
- end
23
- end
1
+ module OrigenTesters
2
+ module Generator
3
+ class TestNumberer
4
+ # Will return a test number for the given test.
5
+ #
6
+ # @param [Hash] options Options to customize the number generation
7
+ # @option options [Integer] :bits (6) The number of bits in the DAC code
8
+ # @option options [Float] :range (1.26) The range parameter, see code formula
9
+ # @option options [Integer] :offset (0) The o
10
+ def test_number_for(test_name, options = {})
11
+ options = {
12
+
13
+ }.merge(options)
14
+ end
15
+
16
+ private
17
+
18
+ def store_file
19
+ @store_file ||= Pathname.new "#{Origen.root}/.test_program/test_numbers"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,12 +1,12 @@
1
- module OrigenTesters
2
- module IGXLBasedTester
3
- autoload :Base, 'origen_testers/igxl_based_tester/base.rb'
4
- autoload :J750, 'origen_testers/igxl_based_tester/j750.rb'
5
- autoload :J750_HPT, 'origen_testers/igxl_based_tester/j750_hpt.rb'
6
- autoload :UltraFLEX, 'origen_testers/igxl_based_tester/ultraflex.rb'
7
- end
8
- # Convenience/Legacy names without the IGXLBasedTester namespace
9
- autoload :J750, 'origen_testers/igxl_based_tester/j750.rb'
10
- autoload :J750_HPT, 'origen_testers/igxl_based_tester/j750_hpt.rb'
11
- autoload :UltraFLEX, 'origen_testers/igxl_based_tester/ultraflex.rb'
12
- end
1
+ module OrigenTesters
2
+ module IGXLBasedTester
3
+ autoload :Base, 'origen_testers/igxl_based_tester/base.rb'
4
+ autoload :J750, 'origen_testers/igxl_based_tester/j750.rb'
5
+ autoload :J750_HPT, 'origen_testers/igxl_based_tester/j750_hpt.rb'
6
+ autoload :UltraFLEX, 'origen_testers/igxl_based_tester/ultraflex.rb'
7
+ end
8
+ # Convenience/Legacy names without the IGXLBasedTester namespace
9
+ autoload :J750, 'origen_testers/igxl_based_tester/j750.rb'
10
+ autoload :J750_HPT, 'origen_testers/igxl_based_tester/j750_hpt.rb'
11
+ autoload :UltraFLEX, 'origen_testers/igxl_based_tester/ultraflex.rb'
12
+ end
@@ -1,1095 +1,1095 @@
1
- module OrigenTesters
2
- module IGXLBasedTester
3
- # This is the base class of all IGXL-based testers
4
- class Base
5
- include VectorBasedTester
6
-
7
- attr_accessor :software_version
8
- attr_accessor :pattern_compiler_pinmap
9
- attr_accessor :memory_test_en
10
- attr_accessor :testerconfig
11
- attr_accessor :channelmap
12
- attr_accessor :default_channelmap
13
- attr_accessor :default_testerconfig
14
- attr_accessor :max_site
15
- # NOTE: DO NOT USE THIS CLASS DIRECTLY ONLY USED AS PARENT FOR
16
- # DESIRED TESTER CLASS
17
-
18
- # Returns a new IGXLBasedTester instance, normally there would only ever be one of these
19
- # assigned to the global variable such as $tester by your target.
20
- def initialize
21
- @unique_counter = 0
22
- @counter_lsb_bits = 0
23
- @counter_msb_bits = 0
24
- @max_repeat_loop = 65_535 # 16 bits
25
- @min_repeat_loop = 2
26
- @pat_extension = 'atp'
27
- @active_loads = true
28
- @pipeline_depth = 34
29
- @software_version = ''
30
- @compress = true
31
- @support_repeat_previous = true
32
- @match_entries = 10
33
- @name = ''
34
- @program_comment_char = ['logprint', "'"]
35
- @opcode_mode = :extended
36
- @flags = %w(cpuA cpuB cpuC cpuD)
37
- @microcode = {}
38
- @microcode[:enable] = 'enable'
39
- @microcode[:set_flag] = 'set_cpu'
40
- @microcode[:mask_vector] = 'ign ifc icc'
41
-
42
- @mask_vector = false # sticky option to mask all subsequent vectors
43
-
44
- @min_pattern_vectors = 0 # no minimum
45
-
46
- @memory_test_en = false # memory test enabled (for all patterns?)
47
-
48
- @testerconfig ||= {}
49
- @channelmap ||= {}
50
- @pushed_instrument_configs = {}
51
- @overlay_style = :subroutine # default to use subroutine for overlay
52
- @capture_style = :hram # default to use hram for capture
53
- @overlay_history = {} # used to track labels, subroutines, digsrc pins used etc
54
- @overlay_subr = nil
55
- @capture_history = {}
56
- end
57
-
58
- def igxl_based?
59
- true
60
- end
61
-
62
- def import_tester_config(testconfigname, fullconfigpath)
63
- # This function reads in CurrentConfig.txt file generated by IG-XL.
64
- # testconfigname example ==> "FT", "WT", "Production"
65
- # fullconfigpath example ==> "/product_folder/CurrentConfig.txt"
66
-
67
- puts "importing Testerconfig #{testconfigname}..."
68
- slotnum = Struct.new(:slot, :instrument, :idprom)
69
- @testerconfig[testconfigname] ||= {}
70
- current_config_file = Pathname.new(fullconfigpath)
71
- File.open(current_config_file, 'r').each_line do |line|
72
- if line =~ /^\d*.0/
73
- (slot, blank1, instrument, blank2, idprom) = line.split(/\t/)
74
- if (!slot.nil?) && (!instrument.nil?) && (!idprom.nil?)
75
- @testerconfig[testconfigname][slot.split('.').first.to_i] = slotnum.new(slot.split('.').first.to_i, instrument, idprom.chomp)
76
- end
77
- end
78
- end
79
-
80
- @default_testerconfig ||= testconfigname # Default TesterConfig gets set if it's not nil
81
- end
82
-
83
- def get_tester_instrument(testconfigname, slot)
84
- @testerconfig[testconfigname].each_with_index do |element, index|
85
- if slot.to_s == element[0].to_s
86
- return element[1][:instrument]
87
- end
88
- end
89
- nil # if no corresponding slot
90
- end
91
-
92
- def get_instrument_slots(testconfigname, instrument) # testconfigname example "WT", "FT", "Production"
93
- @slots = []
94
- @testerconfig[testconfigname].each_with_index do |element, index|
95
- if instrument.to_s == element[1][:instrument].to_s
96
- @slots << element[0].to_i
97
- end
98
- end
99
- @slots # if no corresponding slot
100
- end
101
-
102
- def import_chanmap(chanmapname, fullchanmappath)
103
- # This function reads IG-XL ChannelMap file
104
- # chanmapname example ==> "FT", "WT", "FTX2"
105
- # fullchanmappath example ==> "/product_folder/Chans_FT.txt"
106
-
107
- puts "importing ChannelMap #{fullchanmappath}..."
108
-
109
- chanassignment = Struct.new(:pinname, :site, :channel, :type, :packagepin)
110
- chanmap_file = Pathname.new(fullchanmappath)
111
- @channelmap[chanmapname] ||= {}
112
- File.open(chanmap_file, 'r').each_line.with_index do |line, index|
113
- if index == 0
114
- unless line =~ /DTChanMap/
115
- puts "#{fullchanmappath} is not a valid IG-XL ChannelMap!"
116
- break
117
- end
118
- end
119
- if index == 5
120
- siteloc = line.strip.split(/\t/).size - 1 # strip all white spaces and grab second to last
121
- @max_site_s = line.split(/\t/)[siteloc].strip.split(/\s/)[1]
122
- @max_site = @max_site_s.to_i
123
- (0..@max_site).each do |sitenum|
124
- @channelmap[chanmapname][sitenum] ||= {}
125
- end
126
- end
127
- if index > 5
128
- (blank1, pinname, packagepin, type) = line.split(/\t/)
129
- (0..@max_site).each do |sitenum|
130
- channel = line.split(/\t/)[4 + sitenum].to_s
131
- @channelmap[chanmapname][sitenum][pinname.downcase.intern] = chanassignment.new(pinname.downcase.intern, sitenum, channel.chomp, type.chomp, packagepin)
132
- end
133
- end
134
- end
135
- @default_channelmap ||= chanmapname # Default Channelmap gets set if it's not nil
136
- end
137
-
138
- def get_tester_channel(chanmapname, pinname, sitenum)
139
- if sitenum <= @max_site
140
- @testerchannel = @channelmap[chanmapname][sitenum][pinname].channel
141
- return @testerchannel
142
- else
143
- return nil
144
- end
145
- end
146
-
147
- # Check if a specific pin for a given channelmap for a given site number is using merged channel.
148
- # If yes, return x2 for Merged2, x4 for Merged4, etc. If no, return nil.
149
- def merged_channels(chanmapname, pinname, sitenum)
150
- if sitenum <= @max_site
151
- if @channelmap[chanmapname][sitenum][pinname].type.include?('Merged')
152
- @merged_channels = @channelmap[chanmapname][sitenum][pinname].type.split('Merged')[1]
153
- return 'x' + @merged_channels
154
- end
155
- else
156
- return nil
157
- end
158
- end
159
-
160
- # Check if a specific HexVS supply is HexVS+ variety, which has +/-2mV accuracy as opposed to
161
- # +/-7mV accuracy.
162
- # If the specific HexVS is HexVS+ variety, returns a "+" string, otherwise nil.
163
- def is_hexvs_plus(testconfigname, slot)
164
- if @testerconfig[testconfigname][slot][:instrument].to_s == 'HexVS'
165
- @productnum = @testerconfig[testconfigname][slot][:idprom].split(' ')[0]
166
- if (@productnum.include?('974-294-')) && (@productnum.split('-')[2].to_i >= 20)
167
- return '+'
168
- end
169
- end
170
- nil # if nothing matched
171
- end
172
-
173
- # Check if a specific VHDVS (UVS256) supply is High-Accuracy (HA) variety, which has +/-5mV+0.1%*SUPPLY accuracy as opposed to
174
- # +/-10mV+0.1%*SUPPLY accuracy.
175
- # If the specific VHDVS is of High-Accuracy variety, returns a "+" string, otherwise nil.
176
- def is_vhdvs_plus(testconfigname, slot)
177
- if @testerconfig[testconfigname][slot][:instrument].to_s == 'VHDVS'
178
- @productnum = @testerconfig[testconfigname][slot][:idprom].split(' ')[0]
179
- # binding.pry
180
- if (@productnum.include?('805-052-')) && (@productnum.split('-')[2].to_i >= 05)
181
- return '+'
182
- end
183
- end
184
- nil # if nothing matched
185
- end
186
- # Check if a specific VHDVS (UVS256) channel assignment is _HC variety (high-current)
187
- # If the specific VHDVS channel is _HC variety, returns a "_HC" string, otherwise nil.
188
- def is_vhdvs_hc(chanmapname, pinname, sitenum)
189
- if sitenum <= @max_site
190
- if @channelmap[chanmapname][sitenum][pinname].channel.downcase.include?('hc')
191
- return '_HC'
192
- end
193
- end
194
- nil # if nothing matched
195
- end
196
-
197
- def assign_dc_instr_pins(dc_pins)
198
- if !dc_pins.is_a?(Array)
199
- @dc_pins = [] << dc_pins
200
- else
201
- @dc_pins = dc_pins
202
- end
203
- end
204
-
205
- def assign_digsrc_pins(digsrc_pins)
206
- if !digsrc_pins.is_a?(Array)
207
- @digsrc_pins = [] << digsrc_pins
208
- else
209
- @digsrc_pins = digsrc_pins
210
- end
211
- end
212
-
213
- def assign_digcap_pins(digcap_pins)
214
- if !digcap_pins.is_a?(Array)
215
- @digcap_pins = [] << digcap_pins
216
- else
217
- @digcap_pins = digcap_pins
218
- end
219
- end
220
-
221
- def get_dc_instr_pins
222
- @dc_pins
223
- end
224
-
225
- def get_digsrc_pins
226
- @digsrc_pins
227
- end
228
-
229
- def get_digcap_pins
230
- @digcap_pins
231
- end
232
-
233
- def flows
234
- parser.flows
235
- end
236
-
237
- # Main accessor to all content parsed from existing test program sheets found in the
238
- # supplied directory or in Origen.config.test_program_output_directory
239
- def parser(prog_dir = Origen.config.test_program_output_directory)
240
- unless prog_dir
241
- fail 'You must supply the directory containing the test program sheets, or define it via Origen.config.test_program_output_directory'
242
- end
243
- @parser ||= IGXLBasedTester::Parser.new
244
- @parsed_dir ||= false
245
- if @parsed_dir != prog_dir
246
- @parser.parse(prog_dir)
247
- @parsed_dir = prog_dir
248
- end
249
- @parser
250
- end
251
-
252
- # Capture a vector to the tester HRAM.
253
- #
254
- # This method applies a store vector (stv) opcode to the previous vector, note that is does
255
- # not actually generate a new vector.
256
- #
257
- # Sometimes when generating vectors within a loop you may want to apply a stv opcode
258
- # retrospectively to a previous vector, passing in an offset option will allow you
259
- # to do this.
260
- #
261
- # On J750 the pins argument is ignored since the tester only supports whole vector capture.
262
- #
263
- # @example
264
- # $tester.cycle # This is the vector you want to capture
265
- # $tester.store # This applies the STV opcode
266
- #
267
- # $tester.cycle # This one gets stored
268
- # $tester.cycle
269
- # $tester.cycle
270
- # $tester.store(:offset => -2) # Just realized I need to capture that earlier vector
271
- def store(*pins)
272
- options = pins.last.is_a?(Hash) ? pins.pop : {}
273
- options = { offset: 0
274
- }.merge(options)
275
- update_vector microcode: 'stv', offset: options[:offset]
276
- last_vector(options[:offset]).contains_capture = true
277
- end
278
- alias_method :to_hram, :store
279
- alias_method :capture, :store
280
-
281
- # Capture the next vector generated to HRAM
282
- #
283
- # This method applies a store vector (stv) opcode to the next vector to be generated,
284
- # note that is does not actually generate a new vector.
285
- #
286
- # On J750 the pins argument is ignored since the tester only supports whole vector capture.
287
- #
288
- # @example
289
- # $tester.store_next_cycle
290
- # $tester.cycle # This is the vector that will be captured
291
- def store_next_cycle(*pins)
292
- options = pins.last.is_a?(Hash) ? pins.pop : {}
293
- options = {
294
- }.merge(options)
295
-
296
- preset_next_vector microcode: 'stv' do |vector|
297
- vector.contains_capture = true
298
- end
299
- end
300
- alias_method :store!, :store_next_cycle
301
-
302
- # @api private
303
- def remove_store_from_vector(vector)
304
- super
305
- vector.microcode = nil
306
- end
307
-
308
- # Call a subroutine.
309
- #
310
- # This method applies a call subroutine opcode to the previous vector, it does not
311
- # generate a new vector.
312
- #
313
- # Subroutines should always be called through this method as it ensures a running
314
- # log of called subroutines is maintained and which then gets output in the pattern
315
- # header to import the right dependencies.
316
- #
317
- # An offset option is available to make the call on earlier vectors.
318
- #
319
- # ==== Examples
320
- # $tester.call_subroutine("mysub")
321
- # $tester.call_subroutine("my_other_sub", :offset => -1)
322
- def call_subroutine(name, options = {})
323
- options = {
324
- offset: 0
325
- }.merge(options)
326
- called_subroutines << name.to_s.chomp unless called_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
327
- update_vector microcode: "call #{name}", offset: options[:offset]
328
- end
329
-
330
- # Start a subroutine.
331
- #
332
- # Generates a global subroutine label. Global is used to adhere to the best practice of
333
- # containing all subroutines in dedicated patterns, e.g. global_subs.atp
334
- #
335
- # ==== Examples
336
- # $tester.start_subroutine("wait_for_done")
337
- # < generate your subroutine vectors here >
338
- # $tester.end_subroutine
339
- def start_subroutine(name, options = {})
340
- local_subroutines << name.to_s.chomp unless local_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
341
- if $tester.ultraflex? && (name =~ /keep_?alive/ || options[:keep_alive])
342
- microcode "keepalive subr #{name}:"
343
- else
344
- microcode "global subr #{name}:"
345
- end
346
- end
347
-
348
- # End a subroutine.
349
- #
350
- # Generates a return opcode on the last vector.
351
- #
352
- # ==== Examples
353
- # $tester.start_subroutine("wait_for_done")
354
- # < generate your subroutine vectors here >
355
- # $tester.end_subroutine
356
- # cond: whether return is conditional on a flag (to permit to mix subrs together)
357
- def end_subroutine(cond = false, options = {})
358
- (cond, options) = false, cond if cond.is_a?(Hash)
359
- if cond
360
- update_vector microcode: 'if (flag) return'
361
- else
362
- update_vector microcode: 'return'
363
- end
364
- end
365
-
366
- # Do a frequency measure.
367
- #
368
- # Write the necessary micro code to do a frequency measure on the given pin,
369
- # optionally supply a read code to pass information to the tester.
370
- #
371
- # ==== Examples
372
- # $tester.freq_count($top.pin(:d_out)) # Freq measure on pin "d_out"
373
- # $tester.freq_count($top.pin(:d_out):readcode => 10)
374
- def freq_count(pin, options = {})
375
- options = { readcode: false
376
- }.merge(options)
377
-
378
- set_code(options[:readcode]) if options[:readcode]
379
- cycle(microcode: "#{@microcode[:set_flag]} (cpuA)")
380
- cycle(microcode: "#{@microcode[:set_flag]} (cpuA)")
381
- cycle(microcode: "#{@microcode[:set_flag]} (cpuB)")
382
- cycle(microcode: "#{@microcode[:set_flag]} (cpuC)")
383
- cycle(microcode: 'freq_loop_1:')
384
- cycle(microcode: 'if (cpuA) jump freq_loop_1')
385
- pin.drive_lo
386
- delay(2000)
387
- pin.dont_care
388
- cycle(microcode: "freq_loop_2: #{@microcode[:enable]} (#{@flags[1]})")
389
- cycle(microcode: 'if (flag) jump freq_loop_2')
390
- cycle(microcode: "#{@microcode[:enable]} (#{@flags[2]})")
391
- cycle(microcode: 'if (flag) jump freq_loop_1')
392
- end
393
-
394
- # * J750 Specific *
395
- #
396
- # Generates a single MTO opcode line for J750
397
- #
398
- # Codes implemented: xa load_preset, xa inc, ya load_preset, ya inc, stv_m0, stv_m1, stv_c<br>
399
- def memory_test(options = {})
400
- options = {
401
- gen_vector: true, # Default generate vector not just MTO opcode
402
- init_counter_x: false, # initialize counter X
403
- inc_counter_x: false, # increment counter X
404
- init_counter_y: false, # initialize counter X
405
- inc_counter_y: false, # increment counter X
406
- capture_vector: false, # capture vector to memory using all mem types
407
- capture_vector_mem0: false, # capture vector to memory type 0, here for J750 will be stv_m0
408
- capture_vector_mem1: false, # capture vector to memory type 1, here for J750 will be stv_m1
409
- capture_vector_mem2: false, # capture vector to memory type 2, here for J750 will be stv_c
410
- pin: false, # pin on which to drive or expect data, pass pin object here!
411
- pin_data: false, # pin data (:none, :drive, :expect)
412
- }.merge(options)
413
-
414
- mto_opcode = ''
415
-
416
- if options[:init_counter_x]
417
- mto_opcode += ' xa load_preset'
418
- end
419
- if options[:inc_counter_x]
420
- mto_opcode += ' xa inc'
421
- end
422
- if options[:init_counter_y]
423
- mto_opcode += ' ya load_preset'
424
- end
425
- if options[:inc_counter_y]
426
- mto_opcode += ' ya inc'
427
- end
428
- if options[:capture_vector]
429
- mto_opcode += ' stv_m0 stv_m1 stv_c'
430
- end
431
- if options[:capture_vector_mem0]
432
- mto_opcode += ' stv_m0'
433
- end
434
- if options[:capture_vector_mem1]
435
- mto_opcode += ' stv_m1'
436
- end
437
- if options[:capture_vector_mem2]
438
- mto_opcode += ' stv_c'
439
- end
440
-
441
- unless mto_opcode.eql?('')
442
- mto_opcode = '(mto:' + mto_opcode + ')'
443
- end
444
-
445
- if options[:gen_vector]
446
- if options[:pin]
447
- case options[:pin_data]
448
- when :drive
449
- # store current pin state
450
- cur_pin_state = options[:pin].state.to_sym
451
- options[:pin].drive_mem
452
- when :expect
453
- # store current pin state
454
- cur_pin_state = options[:pin].state.to_sym
455
- options[:pin].expect_mem
456
- end
457
- end
458
- cycle(microcode: "#{mto_opcode}")
459
- if options[:pin]
460
- # restore previous pin state
461
- case options[:pin_data]
462
- when :drive
463
- options[:pin].state = cur_pin_state
464
- when :expect
465
- options[:pin].state = cur_pin_state
466
- end
467
- end
468
- else
469
- microcode "#{mto_opcode}"
470
- end
471
- end
472
-
473
- # Generates a match loop on up to two pins.
474
- #
475
- # This method is not really intended to be called directly, rather you should call
476
- # via Tester#wait e.g. $tester.wait(:match => true).
477
- #
478
- # The timeout should be provided in cycles, however when called via the wait method the
479
- # time-based helpers (time_in_us, etc) will be converted to cycles for you.
480
- # The following options are available to tailor the match loop behavior, defaults in
481
- # parenthesis:
482
- # * :pin - The pin object to match on (*required*)
483
- # * :state - The pin state to match on, :low or :high (*required*)
484
- # * :pin2 (nil) - Optionally supply a second pin to match on
485
- # * :state2 (nil) - State for the second pin (required if :pin2 is supplied)
486
- # * :check_for_fails (false) - Flushes the pipeline and handshakes with the tester (passing readcode 100) prior to the match (to allow binout of fails encountered before the match)
487
- # * :force_fail_on_timeout (true) - Force a vector mis-compare if the match loop times out
488
- # * :on_timeout_goto ("") - Optionally supply a label to branch to on timeout, by default will continue from the end of the match loop
489
- # * :on_pin_match_goto ("") - Optionally supply a label to branch to when pin 1 matches, by default will continue from the end of the match loop
490
- # * :on_pin2_match_goto ("") - Optionally supply a label to branch to when pin 2 matches, by default will continue from the end of the match loop
491
- # * :multiple_entries (false) - Supply an integer to generate multiple entries into the match (each with a unique readcode), this can be useful when debugging patterns with multiple matches
492
- # * :force_fail_on_timeout (true) - force pattern to fail if timeout occurs
493
- # * :global_loops (false) - whether match loop loops should use global labels
494
- # * :manual_stop (false) - whether to use extra cpuB flag to resolve IG-XL v.3.50.xx bug where VBT clears cpuA immediately
495
- # at start of PatFlagFunc instead of at end. Use will have to manually clear cpuB to resume this pattern.
496
- # ==== Examples
497
- # $tester.wait(:match => true, :time_in_us => 5000, :pin => $top.pin(:done), :state => :high)
498
- def match(pin, state, timeout, options = {})
499
- options = {
500
- check_for_fails: false,
501
- on_timeout_goto: false,
502
- pin2: false,
503
- state2: false,
504
- on_pin_match_goto: false,
505
- multiple_entries: false,
506
- force_fail_on_timeout: true,
507
- global_loops: false,
508
- manual_stop: false,
509
- clr_fail_post_match: false
510
- }.merge(options)
511
- options[:on_block_match_goto] ||= options.delete(:on_pin_match_goto)
512
-
513
- match_block(timeout, options) do |match_conditions, fail_conditions|
514
- # Define match conditions
515
- match_conditions.add do
516
- state == :low ? pin.expect_lo : pin.expect_hi
517
- cc "Check if #{pin.name} is #{state == :low ? 'low' : 'high'}"
518
- cycle
519
- pin.dont_care
520
- end
521
-
522
- if options[:pin2]
523
- match_conditions.add do
524
- state == :low ? pin.expect_hi : pin.expect_lo
525
- options[:state2] == :low ? options[:pin2].expect_lo : options[:pin2].expect_hi
526
- cc "Check if #{options[:pin2].name} is #{options[:state2] == :low ? 'low' : 'high'}"
527
- cycle
528
- options[:pin2].dont_care
529
- pin.dont_care
530
- end
531
- end
532
-
533
- # Define fail conditions
534
- fail_conditions.add do
535
- state == :low ? pin.expect_lo : pin.expect_hi
536
- cc "Check if #{pin.name} is #{state == :low ? 'low' : 'high'}"
537
- if options[:pin2]
538
- options[:state2] == :low ? options[:pin2].expect_lo : options[:pin2].expect_hi
539
- cc "Check if #{options[:pin2].name} is #{options[:state2] == :low ? 'low' : 'high'}"
540
- end
541
- cycle
542
- pin.dont_care
543
- options[:pin2].dont_care if options[:pin2]
544
- end
545
- end
546
- end
547
-
548
- # Call a match loop.
549
- #
550
- # Normally you would put your match loop in a global subs pattern, then you can
551
- # call it via this method. This method automatically syncs match loop naming with
552
- # the match generation flow, no arguments required.
553
- #
554
- # This is an IGXLBasedTester specific API.
555
- #
556
- # ==== Examples
557
- # $tester.cycle
558
- # $tester.call_match # Calls the match loop, or the first entry point if you have multiple
559
- # $tester.cycle
560
- # $tester.call_match # Calls the match loop, or the second entry point if you have multiple
561
- def call_match
562
- @match_counter = @match_counter || 0
563
- call_subroutine("match_done_#{@match_counter}")
564
- @match_counter += 1 unless @match_counter == (@match_entries || 1) - 1
565
- end
566
-
567
- # Apply a label to the pattern.
568
- #
569
- # No additional vector is generated.
570
- # Arguments:
571
- # name : label name
572
- # global : (optional) whether to apply global label, default=false
573
- #
574
- # ==== Examples
575
- # $tester.label("something_significant")
576
- # $tester.label("something_significant",true) # apply global label
577
- def label(name, global = false)
578
- global_opt = (global) ? 'global ' : ''
579
- microcode global_opt + name + ':'
580
- end
581
-
582
- # * J750 Specific *
583
- #
584
- # Set a readcode.
585
- #
586
- # Use the set an explicit readcode for communicating with the tester. This method
587
- # will generate an additional vector.
588
- #
589
- # ==== Examples
590
- # $tester.set_code(55)
591
- def set_code(code)
592
- cycle(microcode: "set_code #{code}")
593
- end
594
-
595
- # Branch execution to the given point.
596
- #
597
- # This generates a new vector with a jump instruction to a given label. This method
598
- # will generate an additional vector.
599
- #
600
- # ==== Examples
601
- # $tester.branch_to("something_significant")
602
- def branch_to(label)
603
- cycle(microcode: "jump #{label}")
604
- end
605
- alias_method :branch, :branch_to
606
-
607
- # Add loop to the pattern.
608
- #
609
- # Pass in a name for the loop and the number of times to execute it, all vectors
610
- # generated by the given block will be captured in the loop.
611
- #
612
- # Optional arguments: global - whether to apply global label (default=false)
613
- # label_first - whether to apply loop label before loop vector or not
614
- #
615
- # ==== Examples
616
- # $tester.loop_vectors("pulse_loop", 3) do # Do this 3 times...
617
- # $tester.cycle
618
- # some_other_method_to_generate_vectors
619
- # end
620
- def loop_vectors(name, number_of_loops, global = false, label_first = false)
621
- if number_of_loops > 1
622
- @loop_counters ||= {}
623
- if @loop_counters[name]
624
- @loop_counters[name] += 1
625
- else
626
- @loop_counters[name] = 0
627
- end
628
- loop_name = @loop_counters[name] == 0 ? name : "#{name}_#{@loop_counters[name]}"
629
- if label_first
630
- global_opt = (global) ? 'global ' : ''
631
- microcode "#{global_opt}#{loop_name}: "
632
- end
633
- cycle(microcode: "loopA #{number_of_loops}")
634
- unless label_first
635
- global_opt = (global) ? 'global ' : ''
636
- cycle(microcode: "#{global_opt}#{loop_name}: ")
637
- end
638
- yield
639
- cycle(microcode: "end_loopA #{loop_name}")
640
- else
641
- yield
642
- end
643
- end
644
- alias_method :loop_vector, :loop_vectors
645
-
646
- # An internal method called by Origen Pattern Create to create the pattern header
647
- def pattern_header(options = {})
648
- options = {
649
- instruments: {}, # Provide instruments here if desired as a hash (e.g. "mto" => "dgen_2bit")
650
- subroutine_pat: false,
651
- svm_only: true, # Whether 'svm_only' can be specified
652
- group: false, # If true the end pattern is intended to run within a pattern group
653
- high_voltage: false, # Supply a pin name here to declare it as an HV instrument (not yet defined)
654
- freq_counter: false, # Supply a pin name here to declare it as a frequency counter
655
- memory_test: false, # If true, define 2-bit MTO DGEN as instrument
656
- }.merge(options)
657
-
658
- if level_period?
659
- microcode "import tset #{min_period_timeset.name};"
660
- else
661
- called_timesets.each do |timeset|
662
- microcode "import tset #{timeset.name};"
663
- end
664
- end
665
- unless options[:group] # Withhold imports for pattern groups, is this correct?
666
- called_subroutines.each do |sub_name|
667
- # Don't import any called subroutines that are declared in the current pattern
668
- microcode "import svm_subr #{sub_name};" unless local_subroutines.include?(sub_name)
669
- end
670
- end
671
-
672
- # If memory test, then add to instruments hash
673
- if options[:memory_test]
674
- options[:instruments].merge!('mto' => 'dgen_2bit')
675
- end
676
-
677
- if options[:svm_only]
678
- microcode "svm_only_file = #{options[:subroutine_pat] ? 'yes' : 'no'};"
679
- end
680
-
681
- microcode "opcode_mode = #{@opcode_mode};"
682
- microcode "digital_inst = #{options[:digital_inst]};" if options[:digital_inst]
683
- microcode 'compressed = yes;' # if $dut.gzip_patterns
684
- if tester.j750? && options[:freq_counter]
685
- # pin setup type => freq_counter is only for the J750.
686
- # UltraFLEX has frequency counter capability behind every pin.
687
- # need to make sure the pin_setup freq_count is defined after opcode_mode extended since freq count only work in extended mode
688
- if @opcode_mode == :extended
689
- microcode "pin_setup = {#{options[:freq_counter]} freq_count;}"
690
- else
691
- fail 'pin_setup freq_count can only work in extended mode'
692
- end
693
- end
694
-
695
- # Take care of any instruments
696
- options[:instruments] = options[:instruments].merge(@pushed_instrument_configs)
697
- if options[:instruments].length > 0
698
- microcode 'instruments = {'
699
- options[:instruments].each do |pins, instrument|
700
- if "#{pins}" == 'nil'
701
- microcode " #{instrument};"
702
- elsif instrument == 'digsrc'
703
- microcode " #{pins}:#{instrument} #{options[:digsrc_width]}:#{options[:digsrc_bit_order]}:#{options[:digsrc_mode]}:format=#{options[:digsrc_format]}:#{options[:digsrc_site_uniqueness]}:#{options[:digsrc_auto_cond]};"
704
- elsif instrument == 'digcap'
705
- microcode " #{pins}:#{instrument} #{options[:digcap_width]}:#{options[:digcap_bit_order]}:#{options[:digcap_mode]}:format=#{options[:digcap_format]}:data_type=#{options[:digcap_data_type]}:#{options[:digcap_auto_cond]}:#{options[:digcap_auto_trig_enable]}:#{options[:digcap_store_stv]}:#{options[:digcap_receive_data]};"
706
- else
707
- microcode " #{pins}:#{instrument};"
708
- end
709
- end
710
- microcode '}'
711
- end
712
-
713
- options[:high_voltage] = @use_hv_pin
714
- microcode "pin_setup = {#{options[:high_voltage]} high_voltage;}" if options[:high_voltage]
715
- microcode ''
716
-
717
- pin_list = ordered_pins.map(&:name).join(', ')
718
-
719
- # here indicate pattern header specific stuff
720
- yield pin_list
721
- if ordered_pins.size > 0
722
- max_pin_name_length = ordered_pins.map(&:name).max { |a, b| a.length <=> b.length }.length
723
- pin_widths = ordered_pins.map { |p| p.size - 1 }
724
-
725
- max_pin_name_length.times do |i|
726
- cc((' ' * 93) + ordered_pins.map.with_index { |p, x| ((p.name[i] || ' ') + ' ' * pin_widths[x]).gsub('_', '-') }.join(' '))
727
- end
728
- end
729
- end
730
-
731
- # An internal method called by Origen to generate the pattern footer
732
- def pattern_footer(options = {})
733
- options = {
734
- subroutine_pat: false,
735
- end_in_ka: false,
736
- end_with_halt: false,
737
- end_module: true
738
- }.merge(options)
739
- $tester.align_to_last
740
- # cycle(:microcode => "#{$dut.end_of_pattern_label}:") if $dut.end_of_pattern_label
741
- if options[:end_in_ka]
742
- keep_alive(options)
743
- else
744
- if options[:end_with_halt]
745
- $tester.cycle microcode: 'halt'
746
- else
747
- if options[:end_module]
748
- $tester.cycle microcode: 'end_module' unless options[:subroutine_pat]
749
- else
750
- $tester.cycle
751
- end
752
- end
753
- end
754
- microcode '}'
755
- end
756
-
757
- # Returns an array of subroutines called while generating the current pattern
758
- def called_subroutines
759
- @called_subroutines ||= []
760
- end
761
-
762
- # Returns an array of subroutines created by the current pattern
763
- def local_subroutines # :nodoc:
764
- @local_subroutines ||= []
765
- end
766
-
767
- # This is an internal method use by Origen which returns a fully formatted vector
768
- # You can override this if you wish to change the output formatting at vector level
769
- def format_vector(vec)
770
- timeset = vec.timeset ? "> #{vec.timeset.name}" : ''
771
- pin_vals = vec.pin_vals ? "#{vec.pin_vals} ;" : ''
772
- if vec.repeat > 1
773
- microcode = "repeat #{vec.repeat}"
774
- else
775
- microcode = vec.microcode ? vec.microcode : ''
776
- end
777
- if vec.pin_vals && ($_testers_enable_vector_comments || vector_comments)
778
- comment = " // #{vec.number}:#{vec.cycle} #{vec.inline_comment}"
779
- else
780
- comment = vec.inline_comment.empty? ? '' : " // #{vec.inline_comment}"
781
- end
782
-
783
- "#{microcode.ljust(65)}#{timeset.ljust(31)}#{pin_vals}#{comment}"
784
- end
785
-
786
- # Override this to force the formatting to match the v1 J750 model (easier diffs)
787
- def push_microcode(code) # :nodoc:
788
- stage.store(code.ljust(65) + ''.ljust(31))
789
- end
790
- alias_method :microcode, :push_microcode
791
-
792
- # All vectors generated with the supplied block will have all pins set
793
- # to the repeat previous state. Any pins that are changed state within
794
- # the block will still update to the supplied value.
795
- # ==== Example
796
- # # All pins except invoke will be assigned the repeat previous code
797
- # # in the generated vector. On completion of the block they will
798
- # # return to their previous state, except for invoke which will
799
- # # retain the value assigned within the block.
800
- # $tester.repeat_previous do
801
- # $top.pin(:invoke).drive(1)
802
- # $tester.cycle
803
- # end
804
- def repeat_previous
805
- pinmap = Origen.pin_bank.pins
806
- pinmap.each { |id, pin| pin.repeat_previous = true }
807
- yield
808
- pinmap.each { |id, pin| pin.repeat_previous = false }
809
- end
810
-
811
- def ignore_fails(*pins)
812
- pins.each(&:suspend)
813
- yield
814
- pins.each(&:resume)
815
- end
816
-
817
- def enable_flag(options = {})
818
- options = { flagnum: 4, # default flag to use
819
- }.merge(options)
820
-
821
- if options[:flagnum] > @flags.length
822
- abort "ERROR! Invalid flag value passed to 'enable_flag' method!\n"
823
- end
824
- flagname = @flags[options[:flagnum] - 1]
825
- update_vector(microcode: "#{@microcode[:enable]}(#{flagname})")
826
- end
827
-
828
- def set_flag(options = {})
829
- options = { flagnum: 4, # default flag to use
830
- }.merge(options)
831
-
832
- if options[:flagnum] > @flags.length
833
- abort "ERROR! Invalid flag value passed to 'set_flag' method!\n"
834
- end
835
- flagname = @flags[options[:flagnum] - 1]
836
- update_vector(microcode: "#{@microcode[:set_flag]}(#{flagname})")
837
- end
838
-
839
- def cycle(options = {})
840
- # handle overlay if requested
841
- ovly_style = nil
842
- if options.key?(:overlay)
843
- ovly_style = options[:overlay][:overlay_style].nil? ? @overlay_style : options[:overlay][:overlay_style]
844
- overlay_str = options[:overlay][:overlay_str]
845
-
846
- # route the overlay request to the appropriate method
847
- case ovly_style
848
- when :subroutine, :default
849
- subroutine_overlay(overlay_str, options)
850
- ovly_style = :subroutine
851
- when :label
852
- options[:dont_compress] = true
853
- unless @overlay_history.key?(overlay_str)
854
- label "#{overlay_str}", true
855
- @overlay_history[overlay_str] = { is_label: true }
856
- end
857
- when :digsrc
858
- if ultraflex?
859
- cur_pin_state = options[:overlay][:pins].state.to_sym
860
- options[:overlay][:pins].drive_mem
861
- options = digsrc_overlay(options)
862
- else
863
- ovly_style = overlay_style_warn(options[:overlay][:overlay_str], options)
864
- end
865
- else
866
- ovly_style = overlay_style_warn(options[:overlay][:overlay_str], options)
867
- end # case ovly_style
868
- else
869
- @overlay_subr = nil
870
- end # of handle overlay
871
-
872
- options_overlay = options.delete(:overlay) if options.key?(:overlay)
873
- unless ovly_style == :subroutine
874
- if @mask_vector
875
- # tack on masking opcodes
876
- super(options.merge(microcode: "#{options[:microcode]} #{@microcode[:mask_vector]}"))
877
- else
878
- super(options)
879
- end
880
- end # unless ovly_style
881
-
882
- unless options_overlay.nil?
883
- options_overlay[:pins].state = cur_pin_state if ovly_style == :digsrc
884
- # stage = :body if ovly_style == :subroutine # always set stage back to body in case subr overlay was selected
885
- end
886
- end
887
-
888
- # Warn user of unsupported overlay style
889
- def overlay_style_warn(overlay_str, options)
890
- Origen.log.warn("Unrecognized overlay style :#{@overlay_style}, defaulting to subroutine")
891
- Origen.log.warn('Available overlay styles :label, :subroutine') if j750? || j750_hpt?
892
- Origen.log.warn('Available overlay styles :digsrc, :digsrc_subroutine, :label, :subroutine') if ultraflex?
893
- subroutine_overlay(overlay_str, options)
894
- @overlay_style = :subroutine # Just give 1 warning
895
- end
896
-
897
- # Call this method at the start of any digsrc overlay operations, this method
898
- # takes care of all the microcodes and delays that's needed for digsrc overlay
899
- # Required arguments:
900
- # pins
901
- # Optionsal arguments:
902
- # options[:dssc_mode] = :single or :dual, anything else wil be
903
- # treated as if it's operating in :quad mode
904
- def digsrc_start(pins, options = {})
905
- options = {
906
- dssc_mode: :single # defaults dssc_mode to single mode
907
- }.merge(options)
908
- if pins.size > 1
909
- microcode "((#{format_multiple_instrument_pins(pins)}):DigSrc = Start)"
910
- else
911
- microcode "((#{pin}):DigSrc = Start)"
912
- end
913
- if options[:dssc_mode] == :single
914
- $tester.cycle(repeat: 145) # minimum of 144 cycles, adding 1 for safey measures
915
- elsif options[:dssc_mode] == :dual
916
- $tester.cycle(repeat: 289) # minimum of 288 cycles, adding 1 for safety measures
917
- else
918
- $tester.cycle(repeat: 577) # minimum of 577 cycles, adding 1 for safety measures
919
- end
920
- end
921
-
922
- # Call this method at the end of each digscr overlay operation to clear the pattern
923
- # memory pipeline, so that the pattern is ready to do the next digsrc overlay operation.
924
- # Required arguments:
925
- # pins
926
- def digsrc_stop(pins, options = {})
927
- if pins.size > 1
928
- microcode "((#{format_multiple_instrument_pins(pins)}):DigSrc = Stop)"
929
- else
930
- microcode "((#{pins}):DigSrc = Stop)"
931
- end
932
- end
933
-
934
- # Call this method before each tester cycle to insert the digsrc overlay microcode
935
- def digsrc_send(pins)
936
- microcode "((#{format_multiple_instrument_pins(pins)}):DigSrc = SEND)"
937
- end
938
-
939
- # Call this method before each tester cycle to inser the digcap overlay microcode
940
- def digcap_store(pins)
941
- microcode "((#{format_multiple_instrument_pins(pins)}):DigCap = STORE)"
942
- end
943
-
944
- def apply_digsrc_settings(options = {})
945
- options.merge!(digsrc_width: 1) if options[:digsrc_width].nil? # default to digsrc 1
946
- options.merge!(digsrc_bit_order: :lsb) if options[:digsrc_bit_order].nil? # default to lsb
947
- options.merge!(digsrc_mode: :serial) if options[:digsrc_mode].nil? # default to serial mode
948
- options.merge!(digsrc_format: :binary) if options[:digsrc_format].nil? # default to binary
949
- options.merge!(digsrc_site_uniqueness: :unique_sites) if options[:digsrc_site_uniqueness].nil? # default to unique sites
950
- options.merge!(digsrc_data_type: :default) if options[:digsrc_data_type].nil? # default to default
951
- options.merge!(digsrc_auto_cond: :auto_cond_disable) if options[:digsrc_auto_cond].nil? # default to disable
952
- @digsrc_settings = options
953
- end
954
-
955
- def apply_digcap_settings(options = {})
956
- options.merge!(digcap_width: 8) if options[:digcap_width].nil? # default to digcap 8
957
- options.merge!(digcap_bit_order: :lsb) if options[:digcap_bit_order].nil? # default to lsb
958
- options.merge!(digcap_mode: :serial) if options[:digcap_mode].nil? # default to serial mode
959
- options.merge!(digcap_site_uniqueness: :unique_sites) if options[:digcap_site_uniqueness].nil? # default to unique sites
960
- options.merge!(digcap_format: :binary) if options[:digcap_format].nil? # default to binary
961
- options.merge!(digcap_data_type: :default) if options[:digcap_data_type].nil? # default to default
962
- options.merge!(digcap_auto_cond: :auto_cond_disable) if options[:digcap_auto_cond].nil? # default to disable
963
- options.merge!(digcap_auto_trig_enable: :auto_trig_disable) if options[:digcap_auto_trig_enable].nil? # default to disable
964
- options.merge!(digcap_store_stv: :store_stv_disable) if options[:digcap_store_stv].nil? # default to disable
965
- options.merge!(digcap_receive_data: :store_stv_disable) if options[:digcap_receive_data].nil? # default to logic
966
- @digcap_settings = options
967
- end
968
-
969
- # Call this method if there are more than one pin/pin groups used with an instrument,
970
- # this method will format an array of pins into the correct format required by igxl
971
- # pattern microcodes.
972
- def format_multiple_instrument_pins(pins, options = {})
973
- return_value = ''
974
- pins.each do |pin|
975
- return_value += "#{pin}"
976
- return_value += ',' unless pins.last == pin
977
- end
978
- return_value
979
- end
980
-
981
- def mask_fails(setclr)
982
- @mask_vector = setclr
983
- end
984
-
985
- # Similar to push_microcode, but for the instrument statement in the pattern header
986
- #
987
- # @example
988
- # tester.push_instrument 'SAR_IN_1', 'UltraSource'
989
- # # results in the below line added
990
- # # instruments = {
991
- # # SAR_IN_1:UltraSource;
992
- # # }
993
- def push_instrument(pin_spec, instrument_def)
994
- @pushed_instrument_configs[pin_spec] = instrument_def
995
- end
996
-
997
- # Implement subroutine overlay, called by tester.cycle
998
- def subroutine_overlay(sub_name, options = {})
999
- if @overlay_subr != sub_name
1000
- # unless last staged vector already has the subr call do the following
1001
- i = -1
1002
- i -= 1 until stage.bank[i].is_a?(OrigenTesters::Vector)
1003
- if stage.bank[i].microcode !~ /call #{sub_name}/
1004
-
1005
- # check for repeat on new last vector, unroll 1 if needed
1006
- if stage.bank[i].repeat > 1
1007
- v = OrigenTesters::Vector.new
1008
- v.pin_vals = stage.bank[i].pin_vals
1009
- v.timeset = stage.bank[i].timeset
1010
- stage.bank[i].repeat -= 1
1011
- stage.store(v)
1012
- i = -1
1013
- end
1014
-
1015
- # mark last vector as dont_compress
1016
- stage.bank[i].dont_compress = true
1017
- # insert subroutine call
1018
- call_subroutine sub_name
1019
- end # if microcode not placed
1020
- @overlay_subr = sub_name
1021
- end
1022
-
1023
- # stage = sub_name
1024
- end # subroutine_overlay
1025
-
1026
- # Perform digsrc overlay (called by tester.cycle)
1027
- def digsrc_overlay(options = {})
1028
- options[:overlay] = { change_data: true }.merge(options[:overlay])
1029
- pin_name = dut.pin(options[:overlay][:pins]).name
1030
- repeat_count = options[:repeat].nil? ? 1 : options[:repeat]
1031
-
1032
- if options[:overlay][:change_data]
1033
- # add the send microcode
1034
- microcode "((#{pin_name}):DigSrc = SEND)"
1035
-
1036
- # keep track of amount of digsrc used for header comment
1037
- if @overlay_history[pin_name].nil?
1038
- @overlay_history[pin_name] = { count: repeat_count, is_digsrc: true }
1039
- else
1040
- @overlay_history[pin_name][:count] += repeat_count
1041
- end
1042
-
1043
- # ensure no unwanted repeats on the send vector
1044
- options[:dont_compress] = true
1045
-
1046
- # ensure start microcode is placed at the beginning of the pattern
1047
- if @overlay_history[pin_name][:start_applied].nil?
1048
- # insert start microcode at the beginning of the pattern
1049
- stage.insert_from_start "((#{pin_name}):DigSrc = Start)", 0
1050
- @overlay_history[pin_name][:start_applied] = true
1051
-
1052
- # get the first vector of the pattern
1053
- i = 0
1054
- i += 1 until stage.bank[i].is_a?(OrigenTesters::Vector)
1055
- first_vector = stage.bank[i]
1056
-
1057
- # insert a copy of the first vector with no repeats
1058
- unless first_vector.inline_comment == 'added for digsrc start opcode'
1059
- v = OrigenTesters::Vector.new
1060
- v.pin_vals = stage.bank[i].pin_vals
1061
- v.timeset = stage.bank[i].timeset
1062
- v.inline_comment = 'added for digsrc start opcode'
1063
- v.dont_compress = true
1064
- stage.insert_from_start v, i
1065
-
1066
- # decrement repeat count of previous first vector if > 1
1067
- first_vector.repeat -= 1 if first_vector.repeat > 1
1068
- end
1069
-
1070
- # get cycle count up to this point, add repeat to beginning if needed
1071
- cycle_count = -1
1072
- stage.bank.each { |v| cycle_count += v.repeat if v.is_a?(OrigenTesters::Vector) }
1073
- if cycle_count < @dssc_send_delay
1074
- d = OrigenTesters::Vector.new
1075
- d.pin_vals = first_vector.pin_vals
1076
- d.timeset = first_vector.timeset
1077
- d.inline_comment = 'added for dssc start to send delay'
1078
- d.repeat = @dssc_send_delay - cycle_count
1079
-
1080
- # get the first vector of the pattern
1081
- i = 0
1082
- i += 1 until stage.bank[i].is_a?(OrigenTesters::Vector)
1083
-
1084
- # insert new vector after the first vector
1085
- stage.insert_from_start d, i + 1
1086
- end
1087
-
1088
- end # of place start microcode
1089
-
1090
- end # if options[:change_data]
1091
- options
1092
- end # digsrc overlay
1093
- end
1094
- end
1095
- end
1
+ module OrigenTesters
2
+ module IGXLBasedTester
3
+ # This is the base class of all IGXL-based testers
4
+ class Base
5
+ include VectorBasedTester
6
+
7
+ attr_accessor :software_version
8
+ attr_accessor :pattern_compiler_pinmap
9
+ attr_accessor :memory_test_en
10
+ attr_accessor :testerconfig
11
+ attr_accessor :channelmap
12
+ attr_accessor :default_channelmap
13
+ attr_accessor :default_testerconfig
14
+ attr_accessor :max_site
15
+ # NOTE: DO NOT USE THIS CLASS DIRECTLY ONLY USED AS PARENT FOR
16
+ # DESIRED TESTER CLASS
17
+
18
+ # Returns a new IGXLBasedTester instance, normally there would only ever be one of these
19
+ # assigned to the global variable such as $tester by your target.
20
+ def initialize
21
+ @unique_counter = 0
22
+ @counter_lsb_bits = 0
23
+ @counter_msb_bits = 0
24
+ @max_repeat_loop = 65_535 # 16 bits
25
+ @min_repeat_loop = 2
26
+ @pat_extension = 'atp'
27
+ @active_loads = true
28
+ @pipeline_depth = 34
29
+ @software_version = ''
30
+ @compress = true
31
+ @support_repeat_previous = true
32
+ @match_entries = 10
33
+ @name = ''
34
+ @program_comment_char = ['logprint', "'"]
35
+ @opcode_mode = :extended
36
+ @flags = %w(cpuA cpuB cpuC cpuD)
37
+ @microcode = {}
38
+ @microcode[:enable] = 'enable'
39
+ @microcode[:set_flag] = 'set_cpu'
40
+ @microcode[:mask_vector] = 'ign ifc icc'
41
+
42
+ @mask_vector = false # sticky option to mask all subsequent vectors
43
+
44
+ @min_pattern_vectors = 0 # no minimum
45
+
46
+ @memory_test_en = false # memory test enabled (for all patterns?)
47
+
48
+ @testerconfig ||= {}
49
+ @channelmap ||= {}
50
+ @pushed_instrument_configs = {}
51
+ @overlay_style = :subroutine # default to use subroutine for overlay
52
+ @capture_style = :hram # default to use hram for capture
53
+ @overlay_history = {} # used to track labels, subroutines, digsrc pins used etc
54
+ @overlay_subr = nil
55
+ @capture_history = {}
56
+ end
57
+
58
+ def igxl_based?
59
+ true
60
+ end
61
+
62
+ def import_tester_config(testconfigname, fullconfigpath)
63
+ # This function reads in CurrentConfig.txt file generated by IG-XL.
64
+ # testconfigname example ==> "FT", "WT", "Production"
65
+ # fullconfigpath example ==> "/product_folder/CurrentConfig.txt"
66
+
67
+ puts "importing Testerconfig #{testconfigname}..."
68
+ slotnum = Struct.new(:slot, :instrument, :idprom)
69
+ @testerconfig[testconfigname] ||= {}
70
+ current_config_file = Pathname.new(fullconfigpath)
71
+ File.open(current_config_file, 'r').each_line do |line|
72
+ if line =~ /^\d*.0/
73
+ (slot, blank1, instrument, blank2, idprom) = line.split(/\t/)
74
+ if (!slot.nil?) && (!instrument.nil?) && (!idprom.nil?)
75
+ @testerconfig[testconfigname][slot.split('.').first.to_i] = slotnum.new(slot.split('.').first.to_i, instrument, idprom.chomp)
76
+ end
77
+ end
78
+ end
79
+
80
+ @default_testerconfig ||= testconfigname # Default TesterConfig gets set if it's not nil
81
+ end
82
+
83
+ def get_tester_instrument(testconfigname, slot)
84
+ @testerconfig[testconfigname].each_with_index do |element, index|
85
+ if slot.to_s == element[0].to_s
86
+ return element[1][:instrument]
87
+ end
88
+ end
89
+ nil # if no corresponding slot
90
+ end
91
+
92
+ def get_instrument_slots(testconfigname, instrument) # testconfigname example "WT", "FT", "Production"
93
+ @slots = []
94
+ @testerconfig[testconfigname].each_with_index do |element, index|
95
+ if instrument.to_s == element[1][:instrument].to_s
96
+ @slots << element[0].to_i
97
+ end
98
+ end
99
+ @slots # if no corresponding slot
100
+ end
101
+
102
+ def import_chanmap(chanmapname, fullchanmappath)
103
+ # This function reads IG-XL ChannelMap file
104
+ # chanmapname example ==> "FT", "WT", "FTX2"
105
+ # fullchanmappath example ==> "/product_folder/Chans_FT.txt"
106
+
107
+ puts "importing ChannelMap #{fullchanmappath}..."
108
+
109
+ chanassignment = Struct.new(:pinname, :site, :channel, :type, :packagepin)
110
+ chanmap_file = Pathname.new(fullchanmappath)
111
+ @channelmap[chanmapname] ||= {}
112
+ File.open(chanmap_file, 'r').each_line.with_index do |line, index|
113
+ if index == 0
114
+ unless line =~ /DTChanMap/
115
+ puts "#{fullchanmappath} is not a valid IG-XL ChannelMap!"
116
+ break
117
+ end
118
+ end
119
+ if index == 5
120
+ siteloc = line.strip.split(/\t/).size - 1 # strip all white spaces and grab second to last
121
+ @max_site_s = line.split(/\t/)[siteloc].strip.split(/\s/)[1]
122
+ @max_site = @max_site_s.to_i
123
+ (0..@max_site).each do |sitenum|
124
+ @channelmap[chanmapname][sitenum] ||= {}
125
+ end
126
+ end
127
+ if index > 5
128
+ (blank1, pinname, packagepin, type) = line.split(/\t/)
129
+ (0..@max_site).each do |sitenum|
130
+ channel = line.split(/\t/)[4 + sitenum].to_s
131
+ @channelmap[chanmapname][sitenum][pinname.downcase.intern] = chanassignment.new(pinname.downcase.intern, sitenum, channel.chomp, type.chomp, packagepin)
132
+ end
133
+ end
134
+ end
135
+ @default_channelmap ||= chanmapname # Default Channelmap gets set if it's not nil
136
+ end
137
+
138
+ def get_tester_channel(chanmapname, pinname, sitenum)
139
+ if sitenum <= @max_site
140
+ @testerchannel = @channelmap[chanmapname][sitenum][pinname].channel
141
+ return @testerchannel
142
+ else
143
+ return nil
144
+ end
145
+ end
146
+
147
+ # Check if a specific pin for a given channelmap for a given site number is using merged channel.
148
+ # If yes, return x2 for Merged2, x4 for Merged4, etc. If no, return nil.
149
+ def merged_channels(chanmapname, pinname, sitenum)
150
+ if sitenum <= @max_site
151
+ if @channelmap[chanmapname][sitenum][pinname].type.include?('Merged')
152
+ @merged_channels = @channelmap[chanmapname][sitenum][pinname].type.split('Merged')[1]
153
+ return 'x' + @merged_channels
154
+ end
155
+ else
156
+ return nil
157
+ end
158
+ end
159
+
160
+ # Check if a specific HexVS supply is HexVS+ variety, which has +/-2mV accuracy as opposed to
161
+ # +/-7mV accuracy.
162
+ # If the specific HexVS is HexVS+ variety, returns a "+" string, otherwise nil.
163
+ def is_hexvs_plus(testconfigname, slot)
164
+ if @testerconfig[testconfigname][slot][:instrument].to_s == 'HexVS'
165
+ @productnum = @testerconfig[testconfigname][slot][:idprom].split(' ')[0]
166
+ if (@productnum.include?('974-294-')) && (@productnum.split('-')[2].to_i >= 20)
167
+ return '+'
168
+ end
169
+ end
170
+ nil # if nothing matched
171
+ end
172
+
173
+ # Check if a specific VHDVS (UVS256) supply is High-Accuracy (HA) variety, which has +/-5mV+0.1%*SUPPLY accuracy as opposed to
174
+ # +/-10mV+0.1%*SUPPLY accuracy.
175
+ # If the specific VHDVS is of High-Accuracy variety, returns a "+" string, otherwise nil.
176
+ def is_vhdvs_plus(testconfigname, slot)
177
+ if @testerconfig[testconfigname][slot][:instrument].to_s == 'VHDVS'
178
+ @productnum = @testerconfig[testconfigname][slot][:idprom].split(' ')[0]
179
+ # binding.pry
180
+ if (@productnum.include?('805-052-')) && (@productnum.split('-')[2].to_i >= 05)
181
+ return '+'
182
+ end
183
+ end
184
+ nil # if nothing matched
185
+ end
186
+ # Check if a specific VHDVS (UVS256) channel assignment is _HC variety (high-current)
187
+ # If the specific VHDVS channel is _HC variety, returns a "_HC" string, otherwise nil.
188
+ def is_vhdvs_hc(chanmapname, pinname, sitenum)
189
+ if sitenum <= @max_site
190
+ if @channelmap[chanmapname][sitenum][pinname].channel.downcase.include?('hc')
191
+ return '_HC'
192
+ end
193
+ end
194
+ nil # if nothing matched
195
+ end
196
+
197
+ def assign_dc_instr_pins(dc_pins)
198
+ if !dc_pins.is_a?(Array)
199
+ @dc_pins = [] << dc_pins
200
+ else
201
+ @dc_pins = dc_pins
202
+ end
203
+ end
204
+
205
+ def assign_digsrc_pins(digsrc_pins)
206
+ if !digsrc_pins.is_a?(Array)
207
+ @digsrc_pins = [] << digsrc_pins
208
+ else
209
+ @digsrc_pins = digsrc_pins
210
+ end
211
+ end
212
+
213
+ def assign_digcap_pins(digcap_pins)
214
+ if !digcap_pins.is_a?(Array)
215
+ @digcap_pins = [] << digcap_pins
216
+ else
217
+ @digcap_pins = digcap_pins
218
+ end
219
+ end
220
+
221
+ def get_dc_instr_pins
222
+ @dc_pins
223
+ end
224
+
225
+ def get_digsrc_pins
226
+ @digsrc_pins
227
+ end
228
+
229
+ def get_digcap_pins
230
+ @digcap_pins
231
+ end
232
+
233
+ def flows
234
+ parser.flows
235
+ end
236
+
237
+ # Main accessor to all content parsed from existing test program sheets found in the
238
+ # supplied directory or in Origen.config.test_program_output_directory
239
+ def parser(prog_dir = Origen.config.test_program_output_directory)
240
+ unless prog_dir
241
+ fail 'You must supply the directory containing the test program sheets, or define it via Origen.config.test_program_output_directory'
242
+ end
243
+ @parser ||= IGXLBasedTester::Parser.new
244
+ @parsed_dir ||= false
245
+ if @parsed_dir != prog_dir
246
+ @parser.parse(prog_dir)
247
+ @parsed_dir = prog_dir
248
+ end
249
+ @parser
250
+ end
251
+
252
+ # Capture a vector to the tester HRAM.
253
+ #
254
+ # This method applies a store vector (stv) opcode to the previous vector, note that is does
255
+ # not actually generate a new vector.
256
+ #
257
+ # Sometimes when generating vectors within a loop you may want to apply a stv opcode
258
+ # retrospectively to a previous vector, passing in an offset option will allow you
259
+ # to do this.
260
+ #
261
+ # On J750 the pins argument is ignored since the tester only supports whole vector capture.
262
+ #
263
+ # @example
264
+ # $tester.cycle # This is the vector you want to capture
265
+ # $tester.store # This applies the STV opcode
266
+ #
267
+ # $tester.cycle # This one gets stored
268
+ # $tester.cycle
269
+ # $tester.cycle
270
+ # $tester.store(:offset => -2) # Just realized I need to capture that earlier vector
271
+ def store(*pins)
272
+ options = pins.last.is_a?(Hash) ? pins.pop : {}
273
+ options = { offset: 0
274
+ }.merge(options)
275
+ update_vector microcode: 'stv', offset: options[:offset]
276
+ last_vector(options[:offset]).contains_capture = true
277
+ end
278
+ alias_method :to_hram, :store
279
+ alias_method :capture, :store
280
+
281
+ # Capture the next vector generated to HRAM
282
+ #
283
+ # This method applies a store vector (stv) opcode to the next vector to be generated,
284
+ # note that is does not actually generate a new vector.
285
+ #
286
+ # On J750 the pins argument is ignored since the tester only supports whole vector capture.
287
+ #
288
+ # @example
289
+ # $tester.store_next_cycle
290
+ # $tester.cycle # This is the vector that will be captured
291
+ def store_next_cycle(*pins)
292
+ options = pins.last.is_a?(Hash) ? pins.pop : {}
293
+ options = {
294
+ }.merge(options)
295
+
296
+ preset_next_vector microcode: 'stv' do |vector|
297
+ vector.contains_capture = true
298
+ end
299
+ end
300
+ alias_method :store!, :store_next_cycle
301
+
302
+ # @api private
303
+ def remove_store_from_vector(vector)
304
+ super
305
+ vector.microcode = nil
306
+ end
307
+
308
+ # Call a subroutine.
309
+ #
310
+ # This method applies a call subroutine opcode to the previous vector, it does not
311
+ # generate a new vector.
312
+ #
313
+ # Subroutines should always be called through this method as it ensures a running
314
+ # log of called subroutines is maintained and which then gets output in the pattern
315
+ # header to import the right dependencies.
316
+ #
317
+ # An offset option is available to make the call on earlier vectors.
318
+ #
319
+ # ==== Examples
320
+ # $tester.call_subroutine("mysub")
321
+ # $tester.call_subroutine("my_other_sub", :offset => -1)
322
+ def call_subroutine(name, options = {})
323
+ options = {
324
+ offset: 0
325
+ }.merge(options)
326
+ called_subroutines << name.to_s.chomp unless called_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
327
+ update_vector microcode: "call #{name}", offset: options[:offset]
328
+ end
329
+
330
+ # Start a subroutine.
331
+ #
332
+ # Generates a global subroutine label. Global is used to adhere to the best practice of
333
+ # containing all subroutines in dedicated patterns, e.g. global_subs.atp
334
+ #
335
+ # ==== Examples
336
+ # $tester.start_subroutine("wait_for_done")
337
+ # < generate your subroutine vectors here >
338
+ # $tester.end_subroutine
339
+ def start_subroutine(name, options = {})
340
+ local_subroutines << name.to_s.chomp unless local_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
341
+ if $tester.ultraflex? && (name =~ /keep_?alive/ || options[:keep_alive])
342
+ microcode "keepalive subr #{name}:"
343
+ else
344
+ microcode "global subr #{name}:"
345
+ end
346
+ end
347
+
348
+ # End a subroutine.
349
+ #
350
+ # Generates a return opcode on the last vector.
351
+ #
352
+ # ==== Examples
353
+ # $tester.start_subroutine("wait_for_done")
354
+ # < generate your subroutine vectors here >
355
+ # $tester.end_subroutine
356
+ # cond: whether return is conditional on a flag (to permit to mix subrs together)
357
+ def end_subroutine(cond = false, options = {})
358
+ (cond, options) = false, cond if cond.is_a?(Hash)
359
+ if cond
360
+ update_vector microcode: 'if (flag) return'
361
+ else
362
+ update_vector microcode: 'return'
363
+ end
364
+ end
365
+
366
+ # Do a frequency measure.
367
+ #
368
+ # Write the necessary micro code to do a frequency measure on the given pin,
369
+ # optionally supply a read code to pass information to the tester.
370
+ #
371
+ # ==== Examples
372
+ # $tester.freq_count($top.pin(:d_out)) # Freq measure on pin "d_out"
373
+ # $tester.freq_count($top.pin(:d_out):readcode => 10)
374
+ def freq_count(pin, options = {})
375
+ options = { readcode: false
376
+ }.merge(options)
377
+
378
+ set_code(options[:readcode]) if options[:readcode]
379
+ cycle(microcode: "#{@microcode[:set_flag]} (cpuA)")
380
+ cycle(microcode: "#{@microcode[:set_flag]} (cpuA)")
381
+ cycle(microcode: "#{@microcode[:set_flag]} (cpuB)")
382
+ cycle(microcode: "#{@microcode[:set_flag]} (cpuC)")
383
+ cycle(microcode: 'freq_loop_1:')
384
+ cycle(microcode: 'if (cpuA) jump freq_loop_1')
385
+ pin.drive_lo
386
+ delay(2000)
387
+ pin.dont_care
388
+ cycle(microcode: "freq_loop_2: #{@microcode[:enable]} (#{@flags[1]})")
389
+ cycle(microcode: 'if (flag) jump freq_loop_2')
390
+ cycle(microcode: "#{@microcode[:enable]} (#{@flags[2]})")
391
+ cycle(microcode: 'if (flag) jump freq_loop_1')
392
+ end
393
+
394
+ # * J750 Specific *
395
+ #
396
+ # Generates a single MTO opcode line for J750
397
+ #
398
+ # Codes implemented: xa load_preset, xa inc, ya load_preset, ya inc, stv_m0, stv_m1, stv_c<br>
399
+ def memory_test(options = {})
400
+ options = {
401
+ gen_vector: true, # Default generate vector not just MTO opcode
402
+ init_counter_x: false, # initialize counter X
403
+ inc_counter_x: false, # increment counter X
404
+ init_counter_y: false, # initialize counter X
405
+ inc_counter_y: false, # increment counter X
406
+ capture_vector: false, # capture vector to memory using all mem types
407
+ capture_vector_mem0: false, # capture vector to memory type 0, here for J750 will be stv_m0
408
+ capture_vector_mem1: false, # capture vector to memory type 1, here for J750 will be stv_m1
409
+ capture_vector_mem2: false, # capture vector to memory type 2, here for J750 will be stv_c
410
+ pin: false, # pin on which to drive or expect data, pass pin object here!
411
+ pin_data: false, # pin data (:none, :drive, :expect)
412
+ }.merge(options)
413
+
414
+ mto_opcode = ''
415
+
416
+ if options[:init_counter_x]
417
+ mto_opcode += ' xa load_preset'
418
+ end
419
+ if options[:inc_counter_x]
420
+ mto_opcode += ' xa inc'
421
+ end
422
+ if options[:init_counter_y]
423
+ mto_opcode += ' ya load_preset'
424
+ end
425
+ if options[:inc_counter_y]
426
+ mto_opcode += ' ya inc'
427
+ end
428
+ if options[:capture_vector]
429
+ mto_opcode += ' stv_m0 stv_m1 stv_c'
430
+ end
431
+ if options[:capture_vector_mem0]
432
+ mto_opcode += ' stv_m0'
433
+ end
434
+ if options[:capture_vector_mem1]
435
+ mto_opcode += ' stv_m1'
436
+ end
437
+ if options[:capture_vector_mem2]
438
+ mto_opcode += ' stv_c'
439
+ end
440
+
441
+ unless mto_opcode.eql?('')
442
+ mto_opcode = '(mto:' + mto_opcode + ')'
443
+ end
444
+
445
+ if options[:gen_vector]
446
+ if options[:pin]
447
+ case options[:pin_data]
448
+ when :drive
449
+ # store current pin state
450
+ cur_pin_state = options[:pin].state.to_sym
451
+ options[:pin].drive_mem
452
+ when :expect
453
+ # store current pin state
454
+ cur_pin_state = options[:pin].state.to_sym
455
+ options[:pin].expect_mem
456
+ end
457
+ end
458
+ cycle(microcode: "#{mto_opcode}")
459
+ if options[:pin]
460
+ # restore previous pin state
461
+ case options[:pin_data]
462
+ when :drive
463
+ options[:pin].state = cur_pin_state
464
+ when :expect
465
+ options[:pin].state = cur_pin_state
466
+ end
467
+ end
468
+ else
469
+ microcode "#{mto_opcode}"
470
+ end
471
+ end
472
+
473
+ # Generates a match loop on up to two pins.
474
+ #
475
+ # This method is not really intended to be called directly, rather you should call
476
+ # via Tester#wait e.g. $tester.wait(:match => true).
477
+ #
478
+ # The timeout should be provided in cycles, however when called via the wait method the
479
+ # time-based helpers (time_in_us, etc) will be converted to cycles for you.
480
+ # The following options are available to tailor the match loop behavior, defaults in
481
+ # parenthesis:
482
+ # * :pin - The pin object to match on (*required*)
483
+ # * :state - The pin state to match on, :low or :high (*required*)
484
+ # * :pin2 (nil) - Optionally supply a second pin to match on
485
+ # * :state2 (nil) - State for the second pin (required if :pin2 is supplied)
486
+ # * :check_for_fails (false) - Flushes the pipeline and handshakes with the tester (passing readcode 100) prior to the match (to allow binout of fails encountered before the match)
487
+ # * :force_fail_on_timeout (true) - Force a vector mis-compare if the match loop times out
488
+ # * :on_timeout_goto ("") - Optionally supply a label to branch to on timeout, by default will continue from the end of the match loop
489
+ # * :on_pin_match_goto ("") - Optionally supply a label to branch to when pin 1 matches, by default will continue from the end of the match loop
490
+ # * :on_pin2_match_goto ("") - Optionally supply a label to branch to when pin 2 matches, by default will continue from the end of the match loop
491
+ # * :multiple_entries (false) - Supply an integer to generate multiple entries into the match (each with a unique readcode), this can be useful when debugging patterns with multiple matches
492
+ # * :force_fail_on_timeout (true) - force pattern to fail if timeout occurs
493
+ # * :global_loops (false) - whether match loop loops should use global labels
494
+ # * :manual_stop (false) - whether to use extra cpuB flag to resolve IG-XL v.3.50.xx bug where VBT clears cpuA immediately
495
+ # at start of PatFlagFunc instead of at end. Use will have to manually clear cpuB to resume this pattern.
496
+ # ==== Examples
497
+ # $tester.wait(:match => true, :time_in_us => 5000, :pin => $top.pin(:done), :state => :high)
498
+ def match(pin, state, timeout, options = {})
499
+ options = {
500
+ check_for_fails: false,
501
+ on_timeout_goto: false,
502
+ pin2: false,
503
+ state2: false,
504
+ on_pin_match_goto: false,
505
+ multiple_entries: false,
506
+ force_fail_on_timeout: true,
507
+ global_loops: false,
508
+ manual_stop: false,
509
+ clr_fail_post_match: false
510
+ }.merge(options)
511
+ options[:on_block_match_goto] ||= options.delete(:on_pin_match_goto)
512
+
513
+ match_block(timeout, options) do |match_conditions, fail_conditions|
514
+ # Define match conditions
515
+ match_conditions.add do
516
+ state == :low ? pin.expect_lo : pin.expect_hi
517
+ cc "Check if #{pin.name} is #{state == :low ? 'low' : 'high'}"
518
+ cycle
519
+ pin.dont_care
520
+ end
521
+
522
+ if options[:pin2]
523
+ match_conditions.add do
524
+ state == :low ? pin.expect_hi : pin.expect_lo
525
+ options[:state2] == :low ? options[:pin2].expect_lo : options[:pin2].expect_hi
526
+ cc "Check if #{options[:pin2].name} is #{options[:state2] == :low ? 'low' : 'high'}"
527
+ cycle
528
+ options[:pin2].dont_care
529
+ pin.dont_care
530
+ end
531
+ end
532
+
533
+ # Define fail conditions
534
+ fail_conditions.add do
535
+ state == :low ? pin.expect_lo : pin.expect_hi
536
+ cc "Check if #{pin.name} is #{state == :low ? 'low' : 'high'}"
537
+ if options[:pin2]
538
+ options[:state2] == :low ? options[:pin2].expect_lo : options[:pin2].expect_hi
539
+ cc "Check if #{options[:pin2].name} is #{options[:state2] == :low ? 'low' : 'high'}"
540
+ end
541
+ cycle
542
+ pin.dont_care
543
+ options[:pin2].dont_care if options[:pin2]
544
+ end
545
+ end
546
+ end
547
+
548
+ # Call a match loop.
549
+ #
550
+ # Normally you would put your match loop in a global subs pattern, then you can
551
+ # call it via this method. This method automatically syncs match loop naming with
552
+ # the match generation flow, no arguments required.
553
+ #
554
+ # This is an IGXLBasedTester specific API.
555
+ #
556
+ # ==== Examples
557
+ # $tester.cycle
558
+ # $tester.call_match # Calls the match loop, or the first entry point if you have multiple
559
+ # $tester.cycle
560
+ # $tester.call_match # Calls the match loop, or the second entry point if you have multiple
561
+ def call_match
562
+ @match_counter = @match_counter || 0
563
+ call_subroutine("match_done_#{@match_counter}")
564
+ @match_counter += 1 unless @match_counter == (@match_entries || 1) - 1
565
+ end
566
+
567
+ # Apply a label to the pattern.
568
+ #
569
+ # No additional vector is generated.
570
+ # Arguments:
571
+ # name : label name
572
+ # global : (optional) whether to apply global label, default=false
573
+ #
574
+ # ==== Examples
575
+ # $tester.label("something_significant")
576
+ # $tester.label("something_significant",true) # apply global label
577
+ def label(name, global = false)
578
+ global_opt = (global) ? 'global ' : ''
579
+ microcode global_opt + name + ':'
580
+ end
581
+
582
+ # * J750 Specific *
583
+ #
584
+ # Set a readcode.
585
+ #
586
+ # Use the set an explicit readcode for communicating with the tester. This method
587
+ # will generate an additional vector.
588
+ #
589
+ # ==== Examples
590
+ # $tester.set_code(55)
591
+ def set_code(code)
592
+ cycle(microcode: "set_code #{code}")
593
+ end
594
+
595
+ # Branch execution to the given point.
596
+ #
597
+ # This generates a new vector with a jump instruction to a given label. This method
598
+ # will generate an additional vector.
599
+ #
600
+ # ==== Examples
601
+ # $tester.branch_to("something_significant")
602
+ def branch_to(label)
603
+ cycle(microcode: "jump #{label}")
604
+ end
605
+ alias_method :branch, :branch_to
606
+
607
+ # Add loop to the pattern.
608
+ #
609
+ # Pass in a name for the loop and the number of times to execute it, all vectors
610
+ # generated by the given block will be captured in the loop.
611
+ #
612
+ # Optional arguments: global - whether to apply global label (default=false)
613
+ # label_first - whether to apply loop label before loop vector or not
614
+ #
615
+ # ==== Examples
616
+ # $tester.loop_vectors("pulse_loop", 3) do # Do this 3 times...
617
+ # $tester.cycle
618
+ # some_other_method_to_generate_vectors
619
+ # end
620
+ def loop_vectors(name, number_of_loops, global = false, label_first = false)
621
+ if number_of_loops > 1
622
+ @loop_counters ||= {}
623
+ if @loop_counters[name]
624
+ @loop_counters[name] += 1
625
+ else
626
+ @loop_counters[name] = 0
627
+ end
628
+ loop_name = @loop_counters[name] == 0 ? name : "#{name}_#{@loop_counters[name]}"
629
+ if label_first
630
+ global_opt = (global) ? 'global ' : ''
631
+ microcode "#{global_opt}#{loop_name}: "
632
+ end
633
+ cycle(microcode: "loopA #{number_of_loops}")
634
+ unless label_first
635
+ global_opt = (global) ? 'global ' : ''
636
+ cycle(microcode: "#{global_opt}#{loop_name}: ")
637
+ end
638
+ yield
639
+ cycle(microcode: "end_loopA #{loop_name}")
640
+ else
641
+ yield
642
+ end
643
+ end
644
+ alias_method :loop_vector, :loop_vectors
645
+
646
+ # An internal method called by Origen Pattern Create to create the pattern header
647
+ def pattern_header(options = {})
648
+ options = {
649
+ instruments: {}, # Provide instruments here if desired as a hash (e.g. "mto" => "dgen_2bit")
650
+ subroutine_pat: false,
651
+ svm_only: true, # Whether 'svm_only' can be specified
652
+ group: false, # If true the end pattern is intended to run within a pattern group
653
+ high_voltage: false, # Supply a pin name here to declare it as an HV instrument (not yet defined)
654
+ freq_counter: false, # Supply a pin name here to declare it as a frequency counter
655
+ memory_test: false, # If true, define 2-bit MTO DGEN as instrument
656
+ }.merge(options)
657
+
658
+ if level_period?
659
+ microcode "import tset #{min_period_timeset.name};"
660
+ else
661
+ called_timesets.each do |timeset|
662
+ microcode "import tset #{timeset.name};"
663
+ end
664
+ end
665
+ unless options[:group] # Withhold imports for pattern groups, is this correct?
666
+ called_subroutines.each do |sub_name|
667
+ # Don't import any called subroutines that are declared in the current pattern
668
+ microcode "import svm_subr #{sub_name};" unless local_subroutines.include?(sub_name)
669
+ end
670
+ end
671
+
672
+ # If memory test, then add to instruments hash
673
+ if options[:memory_test]
674
+ options[:instruments].merge!('mto' => 'dgen_2bit')
675
+ end
676
+
677
+ if options[:svm_only]
678
+ microcode "svm_only_file = #{options[:subroutine_pat] ? 'yes' : 'no'};"
679
+ end
680
+
681
+ microcode "opcode_mode = #{@opcode_mode};"
682
+ microcode "digital_inst = #{options[:digital_inst]};" if options[:digital_inst]
683
+ microcode 'compressed = yes;' # if $dut.gzip_patterns
684
+ if tester.j750? && options[:freq_counter]
685
+ # pin setup type => freq_counter is only for the J750.
686
+ # UltraFLEX has frequency counter capability behind every pin.
687
+ # need to make sure the pin_setup freq_count is defined after opcode_mode extended since freq count only work in extended mode
688
+ if @opcode_mode == :extended
689
+ microcode "pin_setup = {#{options[:freq_counter]} freq_count;}"
690
+ else
691
+ fail 'pin_setup freq_count can only work in extended mode'
692
+ end
693
+ end
694
+
695
+ # Take care of any instruments
696
+ options[:instruments] = options[:instruments].merge(@pushed_instrument_configs)
697
+ if options[:instruments].length > 0
698
+ microcode 'instruments = {'
699
+ options[:instruments].each do |pins, instrument|
700
+ if "#{pins}" == 'nil'
701
+ microcode " #{instrument};"
702
+ elsif instrument == 'digsrc'
703
+ microcode " #{pins}:#{instrument} #{options[:digsrc_width]}:#{options[:digsrc_bit_order]}:#{options[:digsrc_mode]}:format=#{options[:digsrc_format]}:#{options[:digsrc_site_uniqueness]}:#{options[:digsrc_auto_cond]};"
704
+ elsif instrument == 'digcap'
705
+ microcode " #{pins}:#{instrument} #{options[:digcap_width]}:#{options[:digcap_bit_order]}:#{options[:digcap_mode]}:format=#{options[:digcap_format]}:data_type=#{options[:digcap_data_type]}:#{options[:digcap_auto_cond]}:#{options[:digcap_auto_trig_enable]}:#{options[:digcap_store_stv]}:#{options[:digcap_receive_data]};"
706
+ else
707
+ microcode " #{pins}:#{instrument};"
708
+ end
709
+ end
710
+ microcode '}'
711
+ end
712
+
713
+ options[:high_voltage] = @use_hv_pin
714
+ microcode "pin_setup = {#{options[:high_voltage]} high_voltage;}" if options[:high_voltage]
715
+ microcode ''
716
+
717
+ pin_list = ordered_pins.map(&:name).join(', ')
718
+
719
+ # here indicate pattern header specific stuff
720
+ yield pin_list
721
+ if ordered_pins.size > 0
722
+ max_pin_name_length = ordered_pins.map(&:name).max { |a, b| a.length <=> b.length }.length
723
+ pin_widths = ordered_pins.map { |p| p.size - 1 }
724
+
725
+ max_pin_name_length.times do |i|
726
+ cc((' ' * 93) + ordered_pins.map.with_index { |p, x| ((p.name[i] || ' ') + ' ' * pin_widths[x]).gsub('_', '-') }.join(' '))
727
+ end
728
+ end
729
+ end
730
+
731
+ # An internal method called by Origen to generate the pattern footer
732
+ def pattern_footer(options = {})
733
+ options = {
734
+ subroutine_pat: false,
735
+ end_in_ka: false,
736
+ end_with_halt: false,
737
+ end_module: true
738
+ }.merge(options)
739
+ $tester.align_to_last
740
+ # cycle(:microcode => "#{$dut.end_of_pattern_label}:") if $dut.end_of_pattern_label
741
+ if options[:end_in_ka]
742
+ keep_alive(options)
743
+ else
744
+ if options[:end_with_halt]
745
+ $tester.cycle microcode: 'halt'
746
+ else
747
+ if options[:end_module]
748
+ $tester.cycle microcode: 'end_module' unless options[:subroutine_pat]
749
+ else
750
+ $tester.cycle
751
+ end
752
+ end
753
+ end
754
+ microcode '}'
755
+ end
756
+
757
+ # Returns an array of subroutines called while generating the current pattern
758
+ def called_subroutines
759
+ @called_subroutines ||= []
760
+ end
761
+
762
+ # Returns an array of subroutines created by the current pattern
763
+ def local_subroutines # :nodoc:
764
+ @local_subroutines ||= []
765
+ end
766
+
767
+ # This is an internal method use by Origen which returns a fully formatted vector
768
+ # You can override this if you wish to change the output formatting at vector level
769
+ def format_vector(vec)
770
+ timeset = vec.timeset ? "> #{vec.timeset.name}" : ''
771
+ pin_vals = vec.pin_vals ? "#{vec.pin_vals} ;" : ''
772
+ if vec.repeat > 1
773
+ microcode = "repeat #{vec.repeat}"
774
+ else
775
+ microcode = vec.microcode ? vec.microcode : ''
776
+ end
777
+ if vec.pin_vals && ($_testers_enable_vector_comments || vector_comments)
778
+ comment = " // #{vec.number}:#{vec.cycle} #{vec.inline_comment}"
779
+ else
780
+ comment = vec.inline_comment.empty? ? '' : " // #{vec.inline_comment}"
781
+ end
782
+
783
+ "#{microcode.ljust(65)}#{timeset.ljust(31)}#{pin_vals}#{comment}"
784
+ end
785
+
786
+ # Override this to force the formatting to match the v1 J750 model (easier diffs)
787
+ def push_microcode(code) # :nodoc:
788
+ stage.store(code.ljust(65) + ''.ljust(31))
789
+ end
790
+ alias_method :microcode, :push_microcode
791
+
792
+ # All vectors generated with the supplied block will have all pins set
793
+ # to the repeat previous state. Any pins that are changed state within
794
+ # the block will still update to the supplied value.
795
+ # ==== Example
796
+ # # All pins except invoke will be assigned the repeat previous code
797
+ # # in the generated vector. On completion of the block they will
798
+ # # return to their previous state, except for invoke which will
799
+ # # retain the value assigned within the block.
800
+ # $tester.repeat_previous do
801
+ # $top.pin(:invoke).drive(1)
802
+ # $tester.cycle
803
+ # end
804
+ def repeat_previous
805
+ pinmap = Origen.pin_bank.pins
806
+ pinmap.each { |id, pin| pin.repeat_previous = true }
807
+ yield
808
+ pinmap.each { |id, pin| pin.repeat_previous = false }
809
+ end
810
+
811
+ def ignore_fails(*pins)
812
+ pins.each(&:suspend)
813
+ yield
814
+ pins.each(&:resume)
815
+ end
816
+
817
+ def enable_flag(options = {})
818
+ options = { flagnum: 4, # default flag to use
819
+ }.merge(options)
820
+
821
+ if options[:flagnum] > @flags.length
822
+ abort "ERROR! Invalid flag value passed to 'enable_flag' method!\n"
823
+ end
824
+ flagname = @flags[options[:flagnum] - 1]
825
+ update_vector(microcode: "#{@microcode[:enable]}(#{flagname})")
826
+ end
827
+
828
+ def set_flag(options = {})
829
+ options = { flagnum: 4, # default flag to use
830
+ }.merge(options)
831
+
832
+ if options[:flagnum] > @flags.length
833
+ abort "ERROR! Invalid flag value passed to 'set_flag' method!\n"
834
+ end
835
+ flagname = @flags[options[:flagnum] - 1]
836
+ update_vector(microcode: "#{@microcode[:set_flag]}(#{flagname})")
837
+ end
838
+
839
+ def cycle(options = {})
840
+ # handle overlay if requested
841
+ ovly_style = nil
842
+ if options.key?(:overlay)
843
+ ovly_style = options[:overlay][:overlay_style].nil? ? @overlay_style : options[:overlay][:overlay_style]
844
+ overlay_str = options[:overlay][:overlay_str]
845
+
846
+ # route the overlay request to the appropriate method
847
+ case ovly_style
848
+ when :subroutine, :default
849
+ subroutine_overlay(overlay_str, options)
850
+ ovly_style = :subroutine
851
+ when :label
852
+ options[:dont_compress] = true
853
+ unless @overlay_history.key?(overlay_str)
854
+ label "#{overlay_str}", true
855
+ @overlay_history[overlay_str] = { is_label: true }
856
+ end
857
+ when :digsrc
858
+ if ultraflex?
859
+ cur_pin_state = options[:overlay][:pins].state.to_sym
860
+ options[:overlay][:pins].drive_mem
861
+ options = digsrc_overlay(options)
862
+ else
863
+ ovly_style = overlay_style_warn(options[:overlay][:overlay_str], options)
864
+ end
865
+ else
866
+ ovly_style = overlay_style_warn(options[:overlay][:overlay_str], options)
867
+ end # case ovly_style
868
+ else
869
+ @overlay_subr = nil
870
+ end # of handle overlay
871
+
872
+ options_overlay = options.delete(:overlay) if options.key?(:overlay)
873
+ unless ovly_style == :subroutine
874
+ if @mask_vector
875
+ # tack on masking opcodes
876
+ super(options.merge(microcode: "#{options[:microcode]} #{@microcode[:mask_vector]}"))
877
+ else
878
+ super(options)
879
+ end
880
+ end # unless ovly_style
881
+
882
+ unless options_overlay.nil?
883
+ options_overlay[:pins].state = cur_pin_state if ovly_style == :digsrc
884
+ # stage = :body if ovly_style == :subroutine # always set stage back to body in case subr overlay was selected
885
+ end
886
+ end
887
+
888
+ # Warn user of unsupported overlay style
889
+ def overlay_style_warn(overlay_str, options)
890
+ Origen.log.warn("Unrecognized overlay style :#{@overlay_style}, defaulting to subroutine")
891
+ Origen.log.warn('Available overlay styles :label, :subroutine') if j750? || j750_hpt?
892
+ Origen.log.warn('Available overlay styles :digsrc, :digsrc_subroutine, :label, :subroutine') if ultraflex?
893
+ subroutine_overlay(overlay_str, options)
894
+ @overlay_style = :subroutine # Just give 1 warning
895
+ end
896
+
897
+ # Call this method at the start of any digsrc overlay operations, this method
898
+ # takes care of all the microcodes and delays that's needed for digsrc overlay
899
+ # Required arguments:
900
+ # pins
901
+ # Optionsal arguments:
902
+ # options[:dssc_mode] = :single or :dual, anything else wil be
903
+ # treated as if it's operating in :quad mode
904
+ def digsrc_start(pins, options = {})
905
+ options = {
906
+ dssc_mode: :single # defaults dssc_mode to single mode
907
+ }.merge(options)
908
+ if pins.size > 1
909
+ microcode "((#{format_multiple_instrument_pins(pins)}):DigSrc = Start)"
910
+ else
911
+ microcode "((#{pin}):DigSrc = Start)"
912
+ end
913
+ if options[:dssc_mode] == :single
914
+ $tester.cycle(repeat: 145) # minimum of 144 cycles, adding 1 for safey measures
915
+ elsif options[:dssc_mode] == :dual
916
+ $tester.cycle(repeat: 289) # minimum of 288 cycles, adding 1 for safety measures
917
+ else
918
+ $tester.cycle(repeat: 577) # minimum of 577 cycles, adding 1 for safety measures
919
+ end
920
+ end
921
+
922
+ # Call this method at the end of each digscr overlay operation to clear the pattern
923
+ # memory pipeline, so that the pattern is ready to do the next digsrc overlay operation.
924
+ # Required arguments:
925
+ # pins
926
+ def digsrc_stop(pins, options = {})
927
+ if pins.size > 1
928
+ microcode "((#{format_multiple_instrument_pins(pins)}):DigSrc = Stop)"
929
+ else
930
+ microcode "((#{pins}):DigSrc = Stop)"
931
+ end
932
+ end
933
+
934
+ # Call this method before each tester cycle to insert the digsrc overlay microcode
935
+ def digsrc_send(pins)
936
+ microcode "((#{format_multiple_instrument_pins(pins)}):DigSrc = SEND)"
937
+ end
938
+
939
+ # Call this method before each tester cycle to inser the digcap overlay microcode
940
+ def digcap_store(pins)
941
+ microcode "((#{format_multiple_instrument_pins(pins)}):DigCap = STORE)"
942
+ end
943
+
944
+ def apply_digsrc_settings(options = {})
945
+ options.merge!(digsrc_width: 1) if options[:digsrc_width].nil? # default to digsrc 1
946
+ options.merge!(digsrc_bit_order: :lsb) if options[:digsrc_bit_order].nil? # default to lsb
947
+ options.merge!(digsrc_mode: :serial) if options[:digsrc_mode].nil? # default to serial mode
948
+ options.merge!(digsrc_format: :binary) if options[:digsrc_format].nil? # default to binary
949
+ options.merge!(digsrc_site_uniqueness: :unique_sites) if options[:digsrc_site_uniqueness].nil? # default to unique sites
950
+ options.merge!(digsrc_data_type: :default) if options[:digsrc_data_type].nil? # default to default
951
+ options.merge!(digsrc_auto_cond: :auto_cond_disable) if options[:digsrc_auto_cond].nil? # default to disable
952
+ @digsrc_settings = options
953
+ end
954
+
955
+ def apply_digcap_settings(options = {})
956
+ options.merge!(digcap_width: 8) if options[:digcap_width].nil? # default to digcap 8
957
+ options.merge!(digcap_bit_order: :lsb) if options[:digcap_bit_order].nil? # default to lsb
958
+ options.merge!(digcap_mode: :serial) if options[:digcap_mode].nil? # default to serial mode
959
+ options.merge!(digcap_site_uniqueness: :unique_sites) if options[:digcap_site_uniqueness].nil? # default to unique sites
960
+ options.merge!(digcap_format: :binary) if options[:digcap_format].nil? # default to binary
961
+ options.merge!(digcap_data_type: :default) if options[:digcap_data_type].nil? # default to default
962
+ options.merge!(digcap_auto_cond: :auto_cond_disable) if options[:digcap_auto_cond].nil? # default to disable
963
+ options.merge!(digcap_auto_trig_enable: :auto_trig_disable) if options[:digcap_auto_trig_enable].nil? # default to disable
964
+ options.merge!(digcap_store_stv: :store_stv_disable) if options[:digcap_store_stv].nil? # default to disable
965
+ options.merge!(digcap_receive_data: :store_stv_disable) if options[:digcap_receive_data].nil? # default to logic
966
+ @digcap_settings = options
967
+ end
968
+
969
+ # Call this method if there are more than one pin/pin groups used with an instrument,
970
+ # this method will format an array of pins into the correct format required by igxl
971
+ # pattern microcodes.
972
+ def format_multiple_instrument_pins(pins, options = {})
973
+ return_value = ''
974
+ pins.each do |pin|
975
+ return_value += "#{pin}"
976
+ return_value += ',' unless pins.last == pin
977
+ end
978
+ return_value
979
+ end
980
+
981
+ def mask_fails(setclr)
982
+ @mask_vector = setclr
983
+ end
984
+
985
+ # Similar to push_microcode, but for the instrument statement in the pattern header
986
+ #
987
+ # @example
988
+ # tester.push_instrument 'SAR_IN_1', 'UltraSource'
989
+ # # results in the below line added
990
+ # # instruments = {
991
+ # # SAR_IN_1:UltraSource;
992
+ # # }
993
+ def push_instrument(pin_spec, instrument_def)
994
+ @pushed_instrument_configs[pin_spec] = instrument_def
995
+ end
996
+
997
+ # Implement subroutine overlay, called by tester.cycle
998
+ def subroutine_overlay(sub_name, options = {})
999
+ if @overlay_subr != sub_name
1000
+ # unless last staged vector already has the subr call do the following
1001
+ i = -1
1002
+ i -= 1 until stage.bank[i].is_a?(OrigenTesters::Vector)
1003
+ if stage.bank[i].microcode !~ /call #{sub_name}/
1004
+
1005
+ # check for repeat on new last vector, unroll 1 if needed
1006
+ if stage.bank[i].repeat > 1
1007
+ v = OrigenTesters::Vector.new
1008
+ v.pin_vals = stage.bank[i].pin_vals
1009
+ v.timeset = stage.bank[i].timeset
1010
+ stage.bank[i].repeat -= 1
1011
+ stage.store(v)
1012
+ i = -1
1013
+ end
1014
+
1015
+ # mark last vector as dont_compress
1016
+ stage.bank[i].dont_compress = true
1017
+ # insert subroutine call
1018
+ call_subroutine sub_name
1019
+ end # if microcode not placed
1020
+ @overlay_subr = sub_name
1021
+ end
1022
+
1023
+ # stage = sub_name
1024
+ end # subroutine_overlay
1025
+
1026
+ # Perform digsrc overlay (called by tester.cycle)
1027
+ def digsrc_overlay(options = {})
1028
+ options[:overlay] = { change_data: true }.merge(options[:overlay])
1029
+ pin_name = dut.pin(options[:overlay][:pins]).name
1030
+ repeat_count = options[:repeat].nil? ? 1 : options[:repeat]
1031
+
1032
+ if options[:overlay][:change_data]
1033
+ # add the send microcode
1034
+ microcode "((#{pin_name}):DigSrc = SEND)"
1035
+
1036
+ # keep track of amount of digsrc used for header comment
1037
+ if @overlay_history[pin_name].nil?
1038
+ @overlay_history[pin_name] = { count: repeat_count, is_digsrc: true }
1039
+ else
1040
+ @overlay_history[pin_name][:count] += repeat_count
1041
+ end
1042
+
1043
+ # ensure no unwanted repeats on the send vector
1044
+ options[:dont_compress] = true
1045
+
1046
+ # ensure start microcode is placed at the beginning of the pattern
1047
+ if @overlay_history[pin_name][:start_applied].nil?
1048
+ # insert start microcode at the beginning of the pattern
1049
+ stage.insert_from_start "((#{pin_name}):DigSrc = Start)", 0
1050
+ @overlay_history[pin_name][:start_applied] = true
1051
+
1052
+ # get the first vector of the pattern
1053
+ i = 0
1054
+ i += 1 until stage.bank[i].is_a?(OrigenTesters::Vector)
1055
+ first_vector = stage.bank[i]
1056
+
1057
+ # insert a copy of the first vector with no repeats
1058
+ unless first_vector.inline_comment == 'added for digsrc start opcode'
1059
+ v = OrigenTesters::Vector.new
1060
+ v.pin_vals = stage.bank[i].pin_vals
1061
+ v.timeset = stage.bank[i].timeset
1062
+ v.inline_comment = 'added for digsrc start opcode'
1063
+ v.dont_compress = true
1064
+ stage.insert_from_start v, i
1065
+
1066
+ # decrement repeat count of previous first vector if > 1
1067
+ first_vector.repeat -= 1 if first_vector.repeat > 1
1068
+ end
1069
+
1070
+ # get cycle count up to this point, add repeat to beginning if needed
1071
+ cycle_count = -1
1072
+ stage.bank.each { |v| cycle_count += v.repeat if v.is_a?(OrigenTesters::Vector) }
1073
+ if cycle_count < @dssc_send_delay
1074
+ d = OrigenTesters::Vector.new
1075
+ d.pin_vals = first_vector.pin_vals
1076
+ d.timeset = first_vector.timeset
1077
+ d.inline_comment = 'added for dssc start to send delay'
1078
+ d.repeat = @dssc_send_delay - cycle_count
1079
+
1080
+ # get the first vector of the pattern
1081
+ i = 0
1082
+ i += 1 until stage.bank[i].is_a?(OrigenTesters::Vector)
1083
+
1084
+ # insert new vector after the first vector
1085
+ stage.insert_from_start d, i + 1
1086
+ end
1087
+
1088
+ end # of place start microcode
1089
+
1090
+ end # if options[:change_data]
1091
+ options
1092
+ end # digsrc overlay
1093
+ end
1094
+ end
1095
+ end