origen_testers 0.19.0 → 0.19.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/config/application.rb +34 -1
  3. data/config/version.rb +1 -1
  4. data/lib/origen_testers/flow.rb +1 -0
  5. data/lib/origen_testers/interface.rb +28 -0
  6. data/lib/origen_testers/pattern_compilers/v93k.rb +3 -1
  7. data/lib/origen_testers/smartest_based_tester/base.rb +14 -1
  8. data/lib/origen_testers/smartest_based_tester/base/test_methods/ac_tml.rb +10 -10
  9. data/lib/origen_testers/test/interface.rb +3 -0
  10. data/pattern/tester_overlay.rb +12 -1
  11. data/program/_erase.rb +1 -1
  12. data/program/components/_prb1_main.rb +3 -3
  13. data/program/test.rb +2 -2
  14. data/templates/origen_guides/pattern/common.md.erb +376 -0
  15. data/templates/origen_guides/pattern/creating.md.erb +133 -0
  16. data/templates/origen_guides/pattern/custom.md.erb +5 -0
  17. data/templates/origen_guides/pattern/documenting.md.erb +431 -0
  18. data/templates/origen_guides/pattern/introduction.md.erb +38 -0
  19. data/templates/origen_guides/pattern/j750.md.erb +10 -0
  20. data/templates/origen_guides/pattern/name.md.erb +511 -0
  21. data/templates/origen_guides/pattern/pins.md.erb +125 -0
  22. data/templates/origen_guides/pattern/registers.md.erb +300 -0
  23. data/templates/origen_guides/pattern/running.md.erb +105 -0
  24. data/templates/origen_guides/pattern/timing.md.erb +281 -0
  25. data/templates/origen_guides/pattern/ultraflex.md.erb +10 -0
  26. data/templates/origen_guides/pattern/v93k.md.erb +41 -0
  27. data/templates/origen_guides/program/code.md.erb +78 -0
  28. data/templates/origen_guides/program/custom.md.erb +5 -0
  29. data/templates/origen_guides/program/doc.md.erb +402 -0
  30. data/templates/origen_guides/program/flowapi.md.erb +249 -0
  31. data/templates/origen_guides/program/flows.md.erb +429 -0
  32. data/templates/origen_guides/program/generating.md.erb +97 -0
  33. data/templates/origen_guides/program/interface.md.erb +248 -0
  34. data/templates/origen_guides/program/introduction.md.erb +56 -0
  35. data/templates/origen_guides/program/j750.md.erb +514 -0
  36. data/templates/origen_guides/program/philosophy.md.erb +99 -0
  37. data/templates/origen_guides/program/resources.md.erb +141 -0
  38. data/templates/origen_guides/program/ultraflex.md.erb +5 -0
  39. data/templates/origen_guides/program/v93k.md.erb +456 -0
  40. data/templates/web/layouts/_guides.html.erb +10 -0
  41. data/templates/web/partials/_placeholder.md.erb +10 -0
  42. metadata +33 -5
@@ -0,0 +1,38 @@
1
+ % render "layouts/guides.html" do
2
+
3
+ Origen was initially conceived to be a pattern generator and as you would
4
+ expect it provides
5
+ powerful APIs to generate tester patterns from your device models.
6
+ These APIs endeavour to abstract as much of the underlying ATE API as possible
7
+ so that quite often all that is required to switch ATE platforms is to change
8
+ the tester model instantiated by the environment.
9
+
10
+ With Origen, an application can also easily create custom tester
11
+ drivers which (for example) can be used to generate patterns in a format that
12
+ can be run on
13
+ the bench (as a J-Link command file for example) or in a functional
14
+ simulation - basically generating your pattern as a Verilog stimulus file.
15
+
16
+ Origen is a simulation-less pattern generation tool and it is therefore very
17
+ quick and lightweight compared to more traditional simulation-based pattern generation
18
+ workflows.
19
+ When combined with the growing number of quality [Origen plugins](<%= path "plugins" %>)
20
+ that are available to provide common hardware (e.g. JTAG) and protocol drivers
21
+ (e.g. ARM Debug, Nexus), the speed of pattern development that can be
22
+ achieved with Origen is unrivaled. With a bit of practice you can literally go from
23
+ nothing to a working pattern for a new application within 10 minutes.
24
+
25
+ #### Use Simulations for What They Are Good At
26
+
27
+ Simulations still have their place, after all they are the only way to get pre-silicon
28
+ feedback on whether a given pattern will actually work or not.
29
+ An Origen-based workflow can still make heavy use of simulations for pre-silicon
30
+ validation of test IP, however the downsides of requiring a simulation to actually
31
+ generate a pattern (workflow complexity, slow generation times) are removed.
32
+
33
+ This leads to much quicker turn around of pattern changes, which means that they can be regenerated
34
+ in real time while debugging on the tester.
35
+
36
+ <img src="<%= path "img/pattern_workflow.png" %>" style="display: block; margin: auto; width: 400px; height: 306px;">
37
+
38
+ % end
@@ -0,0 +1,10 @@
1
+ % render "layouts/guides.html" do
2
+
3
+ This page will be used to document any J750-only APIs related to pattern generation,
4
+ however the goal is to have as few of these as possible so that Origen pattern source code can re-target
5
+ automatically to any supported platform.
6
+
7
+ There are no significant APIs in this category currently, therefore refer to the
8
+ [Common Pattern API](<%= path "guides/pattern/common" %>) which can fully target the J750.
9
+
10
+ % end
@@ -0,0 +1,511 @@
1
+ % render "layouts/guides.html" do
2
+
3
+ In a large application the number of pattern source files can grow very large, for example in the
4
+ flagship Origen application we grew to having more than 1500 pattern source files
5
+ at one time!
6
+ In such a case even if you follow the
7
+ [golden rules for building maintainable patterns](<%= path "guides/pattern/creating" %>)
8
+ the fact that there are so many of them becomes a maintenance concern by itself and
9
+ worries start to creep in about whether all of the patterns really implement a given operation
10
+ in exactly the same way.
11
+
12
+ Even if you don't have so many patterns it can still become tedious to have to manually
13
+ create the pattern every time a new test is added or modified, wouldn't it be nice if
14
+ the pattern just created itself?!
15
+
16
+ With Origen this is possible as long as your patterns lend themselves to being fully described
17
+ by a naming convention. In short if it is possible to uniquely describe your pattern behavior
18
+ with a name then it is possible to synthesize that pattern from that name - this is goal of
19
+ sourceless pattern generation with Origen.
20
+
21
+ This feature is particularly powerful when combined with the
22
+ [Origen program generator](<%= path "guides/program/introduction" %>), since it means that
23
+ your test program flow file becomes the only place where you define a test and the program
24
+ generator will output a list of required pattern names. This can then be passed to the pattern
25
+ generator which can synthesize all of the patterns without needing to create any pattern
26
+ sources at all.
27
+ Once you have invested some time in building a test program interface and sourceless
28
+ pattern capability you can get to the point where to create a new test all you need to do
29
+ is add a single line to the test flow and you are done! That level of automation and
30
+ efficiency is simply not possible from any other test engineering framework.
31
+
32
+ #### Enabling Name-Based Generation
33
+
34
+ This feature is enabled via the <code>before_pattern_lookup</code>
35
+ [callback](<%= path "guides/misc/callbacks" %>) which will be called immediately
36
+ before Origen looks for a pattern source for the given pattern generation request.
37
+ If this method returns false then Origen will cease processing that pattern and will
38
+ assume that the application has dealt with the request. If the method returns
39
+ the requested pattern name then the regular pattern lookup and generation flow
40
+ will proceed as normal.
41
+
42
+ It is recommended that you create a dedicated class called a pattern dispatcher within
43
+ your application which will handle deciding whether or not a pattern request
44
+ can be synthesized without a source file and then if so handle the synthesis and
45
+ generation.
46
+
47
+ Add these lines to your <code>application.rb</code> file to engage a pattern dispatcher
48
+ (where MyApp is your application's namespace):
49
+
50
+ ~~~ruby
51
+ # config/application.rb
52
+ def before_pattern_lookup(requested_pattern)
53
+ MyApp::PatternDispatcher.new.dispatch_or_return(requested_pattern)
54
+ end
55
+ ~~~
56
+
57
+ Then create an initial pattern dispatcher shell like this:
58
+
59
+ ~~~ruby
60
+ # lib/my_app/pattern_dispatcher.rb
61
+ module MyApp
62
+ class PatternDispatcher
63
+
64
+ def dispatch_or_return(requested_pattern)
65
+ requested_pattern
66
+ end
67
+
68
+ end
69
+ end
70
+ ~~~
71
+
72
+ This initial dispatcher simply returns the requested pattern name, therefore Origen will
73
+ behave as normal and look for a source file for every pattern request.
74
+
75
+ Even if you adopt sourceless pattern generation for your application it is likely that
76
+ you will still want to support conventional generation as well - having the ability
77
+ to quickly hack together a engineering pattern at short notice is something that is
78
+ most easily achieved by making a dedicated pattern source file.
79
+
80
+ So the first question is what should be the default behavior - sourceless or lookup?
81
+
82
+ If sourceless is the default then you can implement a convention where if a pattern
83
+ name contains 'custom' then a source file will be expected. If lookup is the default
84
+ then you could have the opposite convention where 'nosrc' in the pattern name means
85
+ that it should be generated without a source.
86
+
87
+ Let's go with sourceless being the default, here is how to modify the <code>dispatch_or_return</code>
88
+ method to do that:
89
+
90
+ ~~~ruby
91
+ def dispatch_or_return(requested_pattern)
92
+ # If the pattern name contains 'custom' just return the name to have Origen lookup a source file for it
93
+ if requested_pattern =~ /custom/
94
+ requested_pattern
95
+ else
96
+ generate(requested_pattern)
97
+ false # Return false to Origen to prevent std pattern dispatch
98
+ end
99
+ end
100
+
101
+ def generate(requested_pattern)
102
+ # Logic to generate the pattern to be added here
103
+ end
104
+ ~~~
105
+
106
+ Now you can see the influence of the pattern dispatcher for the first time, any requests
107
+ containing 'custom' will be processed as normal and any requests without this will
108
+ do nothing.
109
+
110
+ #### How to Generate a Pattern
111
+
112
+ A pattern can be generated from within the dispatcher in much the same way as it is
113
+ generated within a regular pattern source file.
114
+
115
+ Here our <code>generate</code> method will now produce an empty pattern:
116
+
117
+ ~~~ruby
118
+ def generate(requested_pattern)
119
+ Pattern.create(name: requested_pattern) do
120
+ # Logic to generate the pattern to be added here
121
+ end
122
+ end
123
+ ~~~
124
+
125
+ Within the <code>Pattern.create</code> block you can call the exact same methods
126
+ that you would use in a regular pattern source, the difference of course is that
127
+ here we want to dynamically create them based on the name rather than hard-coding
128
+ them for a specific pattern.
129
+
130
+ By going this route you also have to currently pick up a bit more responsibility
131
+ for pre-processing the requested pattern name. For example via the regular
132
+ dispatch mechanism Origen will clean up the name to remove things like a path,
133
+ file extension, and pre and post-fixes that may or may not be present. In other
134
+ words Origen allows you to very flexible over what name you request, for example
135
+ these are equivalent:
136
+
137
+ ~~~text
138
+ origen g bistcom
139
+ origen g output/p2/nvm_bistcom_debug.atp
140
+ ~~~
141
+
142
+ In due course the internal Origen methods may be exposed via an API, but for now
143
+ your pattern dispatcher will have to deal with it (if you want to continue to
144
+ have this flexibility).
145
+
146
+ Here is an example method that you can use for this:
147
+
148
+ ~~~ruby
149
+ def generate(requested_pattern)
150
+ requested_pattern = clean_pattern_name(requested_pattern)
151
+ Pattern.create(name: requested_pattern) do
152
+ # Logic to generate the pattern to be added here
153
+ end
154
+ end
155
+
156
+ def clean_pattern_name(name)
157
+ name = Pathname.new(name).basename.to_s # Strip path
158
+ name.sub!(/\..*/, "") # Strip any and all extensions
159
+ name.sub!(/^nvm_/, "") # Strip prefix, this will unique to your app, here 'nvm_' is removed
160
+ name.sub!(/_debug$/, "") # Strip postfix, again unique to your app, here '_debug' occurring at the end is removed
161
+ name
162
+ end
163
+ ~~~
164
+
165
+ Now you should be able to create (albeit empty) patterns via your dispatcher in the
166
+ same way as via the regular generator.
167
+
168
+ #### Renaming Your Patterns to Make Parsing Easier
169
+
170
+ To generate patterns by name you obviously need to have a comprehensive naming convention
171
+ from which the behavior of each pattern can be fully described, you may even have
172
+ this already in place.
173
+
174
+ However what is easy for a human to parse from a naming convention is not necessarily
175
+ easy for a computer.
176
+ For example your patterns may have the general format:
177
+
178
+ ~~~text
179
+ <parameter set>_<operation>_<identifier>_<block>
180
+ ~~~
181
+
182
+ Here are a couple of examples:
183
+
184
+ ~~~text
185
+ prb_pgm_ckbd_b0 # Program a checkerboard to block 0, using probe parameters
186
+ ft_pgm_ckbd_b0 # Program a checkerboard to block 0, using FT parameters
187
+ ~~~
188
+
189
+ That's fine, but what if these are allowed:
190
+
191
+ ~~~text
192
+ pgm_ckbd_b0 # Program a checkerboard to block 0, using default parameters
193
+ pgm_ckbd_20us_b0 # Program a checkerboard to block 0, using default parameters + 20us programming time
194
+ ~~~
195
+
196
+ Again easy enough to understand, but we have just introduced somethings that will be
197
+ difficult to interpret by our pattern dispatcher. Firstly how do we know if 'pgm'
198
+ is a reference to an operation or a parameter set?
199
+
200
+ One initial way to deal with it is to say that unspecified defaults are not allowed,
201
+ but that would quickly get out of hand as it would mean that every pattern would need
202
+ to declare every variable which is not realistic. So we need a way to unambiguously say
203
+ from the pattern name what each field represents.
204
+
205
+ Similarly in the 2nd example we have further qualified the program operation with '20us',
206
+ but again this is going to add a lot of complexity to our parser - what does that field
207
+ really represent? Is it program time, settling time, something else? Once again attaching
208
+ something to the field name is going to really help us out when it comes to parsing and
209
+ generating the pattern.
210
+
211
+ So how can we re-write these examples to make our lives easier. Well one of the existing
212
+ fields already has a good example for us. In the patterns above we have 'b0' which has
213
+ unwittingly created the convention that a block reference within a pattern will consist
214
+ of 'b' followed by a number. This is exactly the kind of thing that we can deal with easily.
215
+
216
+ So extending that convention to prefix each field with a short mnemonic describing what it
217
+ refers to we end up with:
218
+
219
+ ~~~text
220
+ paraprb_oppgm_patckbd_b0 # Program a checkerboard to block 0, using probe parameters
221
+ paraft_oppgm_patckbd_b0 # Program a checkerboard to block 0, using FT parameters
222
+ oppgm_patckbd_b0 # Program a checkerboard to block 0, using default parameters
223
+ oppgm_patckbd_tprog20_b0 # Program a checkerboard to block 0, using default parameters + 20us programming time
224
+ ~~~
225
+
226
+ So we have paid a penalty here with a pattern name that is a bit more verbose than it really
227
+ needs to be, but it is a small price to pay for being able to drop pattern sources
228
+ completely and to end up with a relatively simple pattern dispatcher.
229
+
230
+ #### Parsing the Pattern Name
231
+
232
+ To create an automated pattern dispatcher you are going to have to get familiar with
233
+ regular expressions (regexs). Providing a tutorial on this is beyond the scope of this guide, but
234
+ a Google search for 'regular expression tutorial' should yield many resources to learn
235
+ from.
236
+
237
+ The following website is highly recommended to keep close by while developing your
238
+ dispatcher - [www.rubular.com](http://www.rubular.com). Aside from having a quick reference
239
+ guide to the Ruby regex syntax it has a live panel which you can paste in your pattern name
240
+ and then experiment with the regex to ensure the correct thing is matched.
241
+ Best of all you can even save a given regex setup and
242
+ paste the link into into your code comments for future reference.
243
+
244
+ The parsing methods you will need to implement are very much dependent on your application and
245
+ naming convention, however a good way to get started is to
246
+ define a method to handle each field. This breaks down the parsing into manageable chunks
247
+ and also gives you a convenient place to set defaults.
248
+ Here are some examples
249
+ (here assuming that the requested pattern
250
+ has been assigned to an instance variable by upstream code):
251
+
252
+ ~~~ruby
253
+ # An example of a required field
254
+ def operation
255
+ if @requested_pattern =~ /(^|_)op(\w+?)(_|$)/
256
+ $2
257
+ else
258
+ raise "No operation was contained in pattern: #{@requested_pattern}"
259
+ end
260
+ end
261
+
262
+ # An example of an optional field with a default
263
+ def parameter_set
264
+ if @requested_pattern =~ /(^|_)para(\w+?)(_|$)/
265
+ $2
266
+ else
267
+ "default" # Use the 'default' parameter set if not specified
268
+ end
269
+ end
270
+
271
+ # An example of an optional field that returns nil if not present, a default
272
+ # may or may not be assigned later within the patgen logic
273
+ def block
274
+ if @requested_pattern =~ /(^|_)b(\w+?)(_|$)/
275
+ $2
276
+ end
277
+ end
278
+ ~~~
279
+
280
+ No doubt the regex code may look a bit daunting at first and unfortunately regexs are
281
+ unusual in that they tend to be easier to write than they are to read!
282
+ However we have basically used the same regex in all of the above examples and most likely
283
+ you could parse your entire pattern name like that.
284
+
285
+ Here is a walkthrough of how it works:
286
+
287
+ <div markdown="0">
288
+ <p>
289
+ <code> string =~ // </code> This is basic format of a regex, you can read this as
290
+ "does some section of the string match the rules inside //".
291
+ </p>
292
+ <p>
293
+ <code>/<strong style="font-size:18px">(^|_)</strong>para(\w+?)(_|$)/</code>
294
+ This means the start of the string (<code>^</code>) or an underscore...
295
+ </p>
296
+ <p>
297
+ <code>/(^|_)<strong style="font-size:18px">para</strong>(\w+?)(_|$)/</code>
298
+ ...followed by the op code that we are trying to match.
299
+ </p>
300
+ <p>
301
+ <code>/(^|_)para<strong style="font-size:18px">(\w+?)</strong>(_|$)/</code>
302
+ Then we have the section that we want to capture. <code>\w</code> means a
303
+ word character, that is a letter, number or unfortunately an underscore.
304
+ The <code>+</code> means one or more of the previous characters. Since the
305
+ <code>\w</code> rule includes underscores by default this will match as many
306
+ occurences as possible, so it would continue matching through the next underscore
307
+ and into the next field, this is called a 'greedy' match. To prevent this we
308
+ add the <code>?</code> which tells it to match as little as possible, sometimes
309
+ called a 'lazy' match.
310
+ This whole section is surrounded in parenthesis which means 'capture the values
311
+ that correspond to this section'.
312
+ </p>
313
+ <p>
314
+ <code>/(^|_)para(\w+?)<strong style="font-size:18px">(_|$)</strong>/</code>
315
+ Finally stop at the end of the string (<code>$</code>) or an underscore.
316
+ </p>
317
+ </div>
318
+
319
+ Our regex contains 3 sets of parenthesis, the part of the string that matched this
320
+ section is available at the end via the variables <code>$1</code>, <code>$2</code>
321
+ and <code>$3</code>. The field we want to capture is in position two and therefore
322
+ our parse methods return this.
323
+
324
+ Here are links to see each of these in action and for you to experiment with:
325
+
326
+ * [operation](http://www.rubular.com/r/VNrfGJMifl)
327
+ * [parameter_set](http://www.rubular.com/r/VN6Bj5MqPg)
328
+ * [block](http://www.rubular.com/r/s7pdwIdxVJ)
329
+
330
+ As a final optimization note, with ruby parameters can be used in regexs in the same
331
+ way they can be used as strings, so actually we could abstract the regex portion of the
332
+ code to a method like this:
333
+
334
+ ~~~ruby
335
+ def extract(op_code)
336
+ if @requested_pattern =~ /(^|_)#{op_code}(\w+?)(_|$)/
337
+ $2
338
+ end
339
+ end
340
+
341
+ def operation
342
+ extract("op") || raise("No operation was contained in pattern: #{@requested_pattern}")
343
+ end
344
+
345
+ def parameter_set
346
+ extract("para") || "default"
347
+ end
348
+
349
+ def block
350
+ extract("b")
351
+ end
352
+ ~~~
353
+
354
+ #### Putting it All Together
355
+
356
+ Now that we can generate a list of build options from the requested name we can start to
357
+ generate the pattern.
358
+
359
+ One of the first jobs of the dispatcher is to generate the list of options
360
+ that should be passed into <code>Pattern.create</code>, in our example let's say that
361
+ the parameter set option is passed into our startup method via <code>Pattern.create</code>.
362
+
363
+ We can now do this by simply calling our <code>parameter_set</code> method:
364
+
365
+ ~~~ruby
366
+ def generate(requested_pattern)
367
+ requested_pattern = clean_pattern_name(requested_pattern)
368
+ Pattern.create(name: requested_pattern, parameter_set: parameter_set) do
369
+ # Logic to generate the pattern to be added here
370
+ end
371
+ end
372
+ ~~~
373
+
374
+ What happens inside the pattern block very much depends on your application patgen API
375
+ and if you are creating this from scratch
376
+ some thought should be given to designing it to lend itself to pattern synthesis.
377
+ In the flagship Origen application where this technique was first developed the original
378
+ API was not at all designed with this in mind. This led to an extremely complex pattern
379
+ dispatcher being required to handle all of the corner cases.
380
+
381
+ To make life simpler for pattern synthesis it is recommended that the API is kept very simple
382
+ with only a few methods being made available and all customization of the operation being
383
+ done via an options hash.
384
+
385
+ So for example a good API to handle our program checkerboard example might be:
386
+
387
+ ~~~ruby
388
+ Pattern.create(params: :ft) do
389
+ $dut.nvm.pgm(pattern: :ckbd, tprog: 20, block: 0)
390
+ end
391
+ ~~~
392
+
393
+ Which could then be synthesized via the following method:
394
+
395
+ ~~~ruby
396
+ def generate(requested_pattern)
397
+ requested_pattern = clean_pattern_name(requested_pattern)
398
+ Pattern.create(name: requested_pattern, parameter_set: parameter_set) do
399
+ $dut.nvm.send operation, pattern: pattern,
400
+ tprog: tprog,
401
+ block: block
402
+ end
403
+ end
404
+ ~~~
405
+
406
+ Even simpler would be:
407
+
408
+ ~~~ruby
409
+ Pattern.create(params: :ft) do
410
+ $dut.nvm.execute(operation: :pgm, pattern: :ckbd, tprog: 20, block: block)
411
+ end
412
+ ~~~
413
+
414
+ And the equivalent synthesizer method:
415
+
416
+ ~~~ruby
417
+ def generate(requested_pattern)
418
+ requested_pattern = clean_pattern_name(requested_pattern)
419
+ Pattern.create(name: requested_pattern, parameter_set: parameter_set) do
420
+ $dut.nvm.execute operation: operation,
421
+ pattern: pattern,
422
+ tprog: tprog,
423
+ block: block
424
+ end
425
+ end
426
+ ~~~
427
+
428
+ A clear pattern is starting to emerge now that for every supported option we have
429
+ a matching method of the same name in our dispatcher, so we can optimize this a bit:
430
+
431
+ ~~~ruby
432
+ OPTIONS = %w(operation pattern tprog block)
433
+
434
+ def generate(requested_pattern)
435
+ requested_pattern = clean_pattern_name(requested_pattern)
436
+ options = {}
437
+ OPTIONS.each do |option|
438
+ options[:option] = self.send(option)
439
+ end
440
+ Pattern.create(name: requested_pattern, parameter_set: parameter_set) do
441
+ $dut.nvm.execute(options)
442
+ end
443
+ end
444
+ ~~~
445
+
446
+ Now if we want to add support for a new option we just add it to the <code>OPTIONS</code>
447
+ array and create the corresponding parse method.
448
+
449
+ We can probably go one better.
450
+
451
+ As we have seen the parser methods are all very similar, do we really need them?
452
+
453
+ Not really as long as we are willing to defer default setting and error checking to our
454
+ models (where it probably makes more sense anyway).
455
+
456
+ Here is a complete pattern dispatcher in around 30 lines of code, where if you want to
457
+ add support for another field in the future just add it to the <code>OPTIONS</code>
458
+ definition that maps the option name to the pattern name op code:
459
+
460
+ ~~~ruby
461
+ # lib/my_app/pattern_dispatcher.rb
462
+ module MyApp
463
+ class PatternDispatcher
464
+
465
+ OPTIONS = {
466
+ operation: "op",
467
+ pattern: "pat",
468
+ tprog: "tprog",
469
+ block: "b",
470
+ }
471
+
472
+ def generate(requested_pattern)
473
+ @requested_pattern = clean_pattern_name(requested_pattern)
474
+ options = {}
475
+ OPTIONS.each do |option, op_code|
476
+ options[:option] = extract(op_code)
477
+ end
478
+ Pattern.create(name: @requested_pattern, parameter_set: extract("para")) do
479
+ $dut.nvm.execute(options)
480
+ end
481
+ end
482
+
483
+ def extract(op_code)
484
+ if @requested_pattern =~ /(^|_)#{op_code}(\w+?)(_|$)/
485
+ $2
486
+ end
487
+ end
488
+
489
+ def dispatch_or_return(requested_pattern)
490
+ # If the pattern name contains 'custom' just return the name to have Origen lookup a source file for it
491
+ if requested_pattern =~ /custom/
492
+ requested_pattern
493
+ else
494
+ generate(requested_pattern)
495
+ false # Return false to Origen to prevent std pattern dispatch
496
+ end
497
+ end
498
+
499
+ def clean_pattern_name(name)
500
+ name = Pathname.new(name).basename.to_s # Strip path
501
+ name.sub!(/\..*/, "") # Strip any and all extensions
502
+ name.sub!(/^nvm_/, "") # Strip prefix, this will unique to your app, here 'nvm_' is removed
503
+ name.sub!(/_debug$/, "") # Strip postfix, again unique to your app, here '_debug' occurring at the end is removed
504
+ name
505
+ end
506
+
507
+ end
508
+ end
509
+ ~~~
510
+
511
+ % end