origen_testers 0.13.1 → 0.13.2

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