origen_testers 0.19.0 → 0.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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,125 @@
1
+ % render "layouts/guides.html" do
2
+
3
+ The control of pin states represents the lowest level of Origen's pattern generation
4
+ API.
5
+
6
+ Generally for most modern applications you should need to do this very rarely
7
+ and mainly when creating mode entry and reset sequences for your
8
+ device.
9
+ For most applications a [plugin](<%= path "plugins" %>)
10
+ such as the [JTAG driver](http://origen-sdk.org/jtag) should be used to
11
+ abstract much of the lower level details about the values to be applied to a given
12
+ pin by a given test vector.
13
+ If your application uses a proprietary interface then it is recommended that you
14
+ create a dedicated class to implement the interface
15
+ protocol and to deal with all of the manipulation of pin states.
16
+
17
+ #### Basic Concept
18
+
19
+ All of Origen's vector-based tester models will support a <code>cycle</code> method
20
+ which will drive or expect the current values held by all pins for one clock cycle.
21
+ In other words the cycle method takes a snapshot of the current pin states and then
22
+ applies them to the DUT.
23
+
24
+ Origen's pin API provides models that represent a DUT's pins and pin groups
25
+ and methods with which to manipulate their states between tester cycles.
26
+
27
+ See the [Pins](<%= path "guides/models/pins" %>) section of
28
+ the [Models](<%= path "guides/models/introduction" %>) guide for details and examples
29
+ of how to add and manipulate pin states within your model logic.
30
+
31
+ #### Recommended Architecture
32
+
33
+ Here are the key components of the recommended architecture:
34
+
35
+ 1. All pins and aliases are defined within the top-level models only, the top-level model is the only object
36
+ that owns pins in the entire application for a given target setup.
37
+ 2. Functions should be added to the pins to represent the different functionality available
38
+ on the pins depending on the mode.
39
+ 3. The availability of the required functions is a contract between a given sub-model
40
+ and the top-level, i.e. the NVM models and test logic assume that all top-level models will
41
+ provide functions named *nvm_fail* and *nvm_done*.
42
+ 4. Each model only refers to the pins using the name/function that it understands.
43
+ 5. The test block/plugin that is primarily responsible for a given test pattern
44
+ can still control the pin order of the created pattern by using the <code>pin_pattern_order</code>
45
+ method.
46
+
47
+ The above approach has the benefits of encapsulating all pin definitions within the top-level model, so
48
+ that a device's TE could implement the details straight from the top-level DFT guide for example, while the lower level
49
+ modules can talk to the pins/signals that they know about.
50
+
51
+ Here is an example of how to implement this scheme in a top-level SoC model:
52
+
53
+ ~~~ruby
54
+ class MySoC
55
+ include Origen::TopLevel
56
+
57
+ def initialize(options)
58
+ instantiate_pins(options)
59
+ end
60
+
61
+ def instantiate_pins(options)
62
+ # Common pins required by all to support mode entry sequences
63
+ add_pin :tclk, reset: :drive_lo
64
+ add_pin :trst, reset: :drive_hi
65
+ add_pin :extal
66
+ add_pin :xtal, reset: :drive_lo
67
+ add_pin :tms
68
+ add_pin :tdo
69
+ add_pin :tdi
70
+ add_pin :resetb
71
+
72
+ add_pins :data, size: 8
73
+
74
+ # Add NVM BIST mode functions
75
+ pin(:extal).add_function :nvm_clk
76
+ pin(:data)[2].add_function :nvm_fail
77
+ pin(:data)[3].add_function :nvm_done
78
+ pin(:data)[4].add_function :nvm_invoke
79
+
80
+ # Add additional function groups here...
81
+ end
82
+ end
83
+ ~~~
84
+
85
+ #### Controlling the Pattern Pin Order
86
+
87
+ As a test engineer for a specific test module you may want more importance to be given to some pins
88
+ than others, or to otherwise order them to make them most readable for debugging the target module.
89
+
90
+ This can be achieved by calling the <code>pin_pattern_order</code> method:
91
+
92
+ ~~~ruby
93
+ class NVM
94
+ include Origen::Model
95
+
96
+ def initialize
97
+ # Unspecified pins will appear in arbitrary order at the end
98
+ pin_pattern_order :nvm_clk, :nvm_invoke, :nvm_done, :nvm_fail
99
+ end
100
+ end
101
+ ~~~
102
+
103
+ Aside from specifying the order of the pins this also specifies what the name should be, i.e. if a given
104
+ pin/pin group has multiple aliases then the one used to refer to the pin in the <code>pin_pattern_order</code>
105
+ is that one that will appear in the generated pattern.
106
+
107
+ By default any unspecified pins will appear in arbitrary order at the end. To include only the pins
108
+ specified then append the <code>:only</code> option at the end:
109
+
110
+ ~~~ruby
111
+ # Only include these pins in the output pattern and in this order
112
+ pin_pattern_order :nvm_clk, :nvm_invoke, :nvm_done, :nvm_fail, only: true
113
+ ~~~
114
+
115
+ Alternatively specific pins or pin groups can be excluded from appearing in the output file via
116
+ the <code>pin_pattern_exclude</code> method:
117
+
118
+ ~~~ruby
119
+ # Don't include these pins in the pattern
120
+ pin_pattern_exclude :porte, :portf
121
+ ~~~
122
+
123
+ An error will be raised if the same pin appears in both <code>pin_pattern_order</code> and <code>pin_pattern_exclude</code>.
124
+
125
+ % end
@@ -0,0 +1,300 @@
1
+ % render "layouts/guides.html" do
2
+
3
+ The majority of patterns are concerned with reading and writing to registers to make the
4
+ DUT do something and consequently
5
+ more than 90% of your time developing an Origen test application should be concerned with
6
+ writing code at the register level.
7
+
8
+ All test [transaction drivers](<%= path "plugins/#Transaction_Protocol_Drivers" %>)
9
+ such as the [ARM Debug driver](http://origen-sdk.org/arm_debug) are expected to support the basic
10
+ Origen register API. This allows the test engineer to develop code at register level and
11
+ independently of the underlying test communication protocol which can be easily changed
12
+ to something else as required.
13
+
14
+ #### Basic Concept
15
+
16
+ See the [Registers](<%= path "guides/models/registers" %>) section of
17
+ the [Models](<%= path "guides/models/introduction" %>) guide for details and examples
18
+ of how to add and manipulate register states within your model logic.
19
+
20
+ Interaction with the registers should be limited to the [model's controller](<%= path "guides/controllers/introduction" %>)
21
+ - no one else should reach into a model to manipulate its register state (this is not prevented
22
+ but recommended), and the controllers should instead expose interface methods for the outside
23
+ world to use. Internally such methods will work by manipulating registers in a sequence.
24
+
25
+ The <code>read!</code> and <code>write!</code> methods when called on a register (or bit) will
26
+ automatically fire off a request for the register to be written using the following
27
+ rules:
28
+
29
+ * If the model or controller that owns the register implements a <code>write_register</code> method
30
+ then call this with the target register passed in as the argument
31
+ * Otherwise if the object that owns the register implements an <code>owner</code> method,
32
+ then see if the object that this returns provides a suitable <code>write_register</code>
33
+ method
34
+ * If not then if a currently instantiated model includes the <code>Origen::TopLevel</code>
35
+ module then see if it (or its controller) has a <code>write_register</code> method available
36
+ * If the request has still not been fulfilled then raise an error
37
+
38
+ Read works in the same way except that it looks for a method called <code>read_register</code>.
39
+
40
+ What this all means is that within a controller you will build your
41
+ test logic from methods that look like this:
42
+
43
+ ~~~ruby
44
+ def measure_vref(setting=nil)
45
+ if setting
46
+ ss "Measure the Vref voltage for setting #{setting}"
47
+ vref.level.write(setting)
48
+ else
49
+ ss "Measure the default Vref voltage"
50
+ end
51
+ vref.test_enable.write!(1)
52
+ end
53
+
54
+ # From a pattern call like this:
55
+ Pattern.create do
56
+ $dut.nvm.measure_vref(5)
57
+ end
58
+ ~~~
59
+
60
+ The actual mechanism for how the registers are written is abstracted away from the
61
+ test logic itself and therefore the test logic is generally independent from the communication
62
+ protocol. This is a very powerful concept that allows plugins to be created that provide
63
+ test sequences for a specific silicon module and these can then be re-used on DUTs that
64
+ employ completely different register access protocols.
65
+
66
+ #### Recommended Architecture
67
+
68
+ This is the recommended architecture for modern Origen applications that will lend itself
69
+ to working well within a plugin-based environment.
70
+
71
+ Define registers in the child models that own them and create test methods to manipulate them
72
+ in the controller:
73
+
74
+ ~~~ruby
75
+ class NVM
76
+ include Origen::Model
77
+
78
+ def initialize
79
+ reg :vref, 0x0003, size: 16 do |reg|
80
+ reg.bit 15, :test_enable
81
+ reg.bit 7..0, :level
82
+ end
83
+ end
84
+ end
85
+
86
+ class NVMController
87
+ include Origen::Controller
88
+
89
+ def measure_vref(setting=nil)
90
+ if setting
91
+ ss "Measure the Vref voltage for setting #{setting}"
92
+ vref.level.write(setting)
93
+ else
94
+ ss "Measure the default Vref voltage"
95
+ end
96
+ vref.test_enable.write!(1)
97
+ end
98
+ end
99
+ ~~~
100
+
101
+ Defer how to actually write the register to the top-level SoC controller and normally this would
102
+ be done via one of the available protocol plugins.
103
+ Here for example is an SoC which will write the register via the [Nexus protocol](http://origen-sdk.org/nexus):
104
+
105
+ ~~~ruby
106
+ class MySoC
107
+ include Origen::TopLevel # Indicate to Origen that this model represents a top-level device object
108
+ end
109
+
110
+ class MySoCController
111
+ include Origen::Controller
112
+ include Nexus
113
+
114
+ # Process register reads using the Nexus protocol
115
+ def read_register(reg, options={})
116
+ nexus.read_register(reg, options)
117
+ end
118
+
119
+ # As above for write requests
120
+ def write_register(reg, options={})
121
+ nexus.write_register(reg, options)
122
+ end
123
+ end
124
+ ~~~
125
+
126
+ And that is all that is required, Origen takes care of the hook up and the behind the scenes
127
+ communication to make it all work.
128
+
129
+ Another target may then instantiate a different SoC model which could use a completely different
130
+ protocol like [ARM Debug](http://origen-sdk.org/arm_debug), in which case the NVM test module would
131
+ still work although the generated pattern would look completely different.
132
+
133
+ #### Bit Level Access
134
+
135
+ All registers support bit level updates, we have seen an example of this already:
136
+
137
+ ~~~ruby
138
+ vref.test_enable.write!(1)
139
+ ~~~
140
+
141
+ What this will do is update the value held by the given bits and then send the parent
142
+ register object to the <code>write_register</code> method for processing.
143
+ All other bits in the register will maintain the state that they had prior to this
144
+ operation commencing.
145
+
146
+ Since it is not generally possible to update only a subset of bits on a device the entire
147
+ register will still be updated on silicon.
148
+ However in the case of performing a bit-level read things get a bit more interesting.
149
+
150
+ The equivalent read operation will update the data values of the bits in the same way, but
151
+ it will also set a flag on those bits marking that they have been requested for read.
152
+
153
+ ~~~ruby
154
+ vref.test_enable.read!(1)
155
+ ~~~
156
+
157
+ The protocol driver can then look out for this flag when generating the readout vectors
158
+ and only enable a compare on the vectors that correspond to the bits marked for read.
159
+ Generally this takes a lot of the cognitive overhead out of writing patterns since you
160
+ can mentally disregard the state of all bits except the ones that you care about.
161
+
162
+ All standard Origen protocol plugins are expected to support this feature.
163
+
164
+ The same is true for store (meaning capture the value on the tester) or overlay operations:
165
+
166
+ ~~~ruby
167
+ # Capture the value of the level bits
168
+ vref.level.store!
169
+
170
+ # Dynamically overlay the value written to the level bits
171
+ vref.level.overlay("vref_setting")
172
+ vref.write!
173
+ ~~~
174
+
175
+ #### Combining Multiple Bit Level Accesses Into A Single Transaction
176
+
177
+ Multiple individual bits within a register can be accessed/manipulated within a single
178
+ transaction by making multiple bit-level calls to `read` (or `write`), followed by a single
179
+ register-level `read!` (or `write!`) operation:
180
+
181
+ ~~~ruby
182
+ my_reg.my_bits_x.read(1)
183
+ my_reg.my_bits_z.read(0b101)
184
+ my_reg.read!
185
+ ~~~
186
+
187
+ Sometimes you will see application code that combines the final transaction request with the
188
+ final bit-level operation, this will do the same thing as the above example:
189
+
190
+ ~~~ruby
191
+ my_reg.my_bits_x.read(1)
192
+ my_reg.my_bits_z.read!(0b101)
193
+ ~~~
194
+
195
+ If you prefer, an equivalent block form API is also available, this is equivalent to the above example:
196
+
197
+ ~~~ruby
198
+ my_reg.read! do |reg|
199
+ reg.my_bits_x.read(1)
200
+ reg.my_bits_z.read(0b101)
201
+ end
202
+ ~~~
203
+
204
+ #### Writing a Driver
205
+
206
+ Generally the code for an existing driver should be reviewed to see how to go about this,
207
+ the [JTAG driver](http://origen-sdk.org/jtag) would be a good example to look at,
208
+ but here are some basic pointers on good driver design.
209
+
210
+ All drivers should implement read and write register methods:
211
+
212
+ ~~~ruby
213
+ def write_register(reg, options={})
214
+ end
215
+
216
+ def read_register(reg, options={})
217
+ end
218
+ ~~~
219
+
220
+ The write methods are usually fairly simple, here is a basic example of how to do a parallel
221
+ and a serial protocol write:
222
+
223
+ ~~~ruby
224
+ # Writing on a parallel port, let's say we have a 16-bit register and the
225
+ # data needs to be written on a pin group called data which is 8-bits
226
+ def write_register(reg, options={})
227
+ pin(:din).drive(1) # Let's say when this pin is high data is captured
228
+ # Drive the data in MSB -> LSB order
229
+ pins(:data).drive!(reg[15..8].data)
230
+ pins(:data).drive!(reg[7..0].data)
231
+ pin(:din).drive(0) # Turn off capture
232
+ end
233
+
234
+ # Writing on a serial port, same as above only this time the :data port is
235
+ # only 1-bit wide
236
+ def read_register(reg, options={})
237
+ pin(:din).drive(1) # Let's say when this pin is high data is captured
238
+ # Drive the data in MSB -> LSB order
239
+ reg.shift_out_left do |bit|
240
+ pin(:data).drive!(bit.data)
241
+ end
242
+ pin(:din).drive(0) # Turn off capture
243
+ end
244
+ ~~~
245
+
246
+ Read methods are usually a bit more involved to implement the bit-specific read and
247
+ capture operations.
248
+ Here is a parallel and serial protocol example which supports bit-level read operations:
249
+
250
+ ~~~ruby
251
+ # Reading on a parallel port, let's say we have a 16-bit register and the
252
+ # data needs to be read on a pin group called data which is 8-bits
253
+ def write_register(reg, options={})
254
+ pin(:dout).drive(1) # Let's say when this pin is high data is presented
255
+
256
+ # Compare the data in MSB
257
+ 8.times do |i|
258
+ bit = reg.bit(i + 8)
259
+ if bit.is_to_be_read?
260
+ pins(:data)[i].assert(bit.data)
261
+ else
262
+ pins(:data)[i].dont_care
263
+ end
264
+ end
265
+ $tester.cycle
266
+
267
+ # Now the data in LSB
268
+ 8.times do |i|
269
+ bit = reg.bit(i)
270
+ if bit.is_to_be_read?
271
+ pins(:data)[i].assert(bit.data)
272
+ else
273
+ pins(:data)[i].dont_care
274
+ end
275
+ end
276
+ $tester.cycle
277
+
278
+ pin(:dout).drive(0) # Turn off read out
279
+ end
280
+
281
+ # Reading on a serial port, same as above only this time the :data port is
282
+ # only 1-bit wide
283
+ def read_register(reg, options={})
284
+ pin(:dout).drive(1) # Let's say when this pin is high data is presented
285
+
286
+ # Drive the data in MSB -> LSB order
287
+ reg.shift_out_left do |bit|
288
+ if bit.is_to_be_read?
289
+ pin(:data).assert!(bit.data)
290
+ else
291
+ pin(:data).dont_care!
292
+ end
293
+ end
294
+
295
+ pin(:dout).drive(0) # Turn off read out
296
+ end
297
+ ~~~
298
+
299
+
300
+ % end
@@ -0,0 +1,105 @@
1
+ % render "layouts/guides.html" do
2
+
3
+ The pattern generator is launched via the Origen generate command, see the command line
4
+ help to get details of the most up to date options:
5
+
6
+ ~~~text
7
+ origen generate -h
8
+ ~~~
9
+
10
+ As this is such a commonly used command it has a short cut alias:
11
+
12
+ ~~~text
13
+ origen g -h
14
+ ~~~
15
+
16
+ The generator can be run on a single file:
17
+
18
+ ~~~text
19
+ origen g pattern/ram/march.rb
20
+ ~~~
21
+
22
+ It can also be run without a path and by just supplying a name, Origen is also pretty flexible
23
+ with regards to file extensions and pre and post fixes and in most cases it should do a good
24
+ job of finding the pattern that you want:
25
+
26
+ ~~~text
27
+ origen g march
28
+ ~~~
29
+
30
+ It can also run on a whole directory:
31
+
32
+ ~~~text
33
+ origen g pattern/ram
34
+ ~~~
35
+
36
+ Pattern list files can also be used, by convention these should be kept in the list directory
37
+ and should have the extension <code>.list</code>:
38
+
39
+ ~~~text
40
+ origen g list/production.list
41
+ ~~~
42
+
43
+ Here is an example of a list file:
44
+
45
+ ~~~text
46
+ # List files can be commented like this
47
+ # Simply list the name of the patterns that you would use on the command line
48
+ march.rb
49
+ data_retention.rb
50
+ # List files can also call other lists
51
+ probe.list
52
+ ~~~
53
+
54
+ By default the generated patterns will be put in <code>output</code> or whatever directory
55
+ is returned by the <code>config.output_directory</code> attribute in <code>application.rb</code>.
56
+
57
+ Submit to the LSF by appending <code>-l</code> and optionally interactively
58
+ wait for completion:
59
+
60
+ ~~~text
61
+ origen g list/production.list -l -w
62
+ ~~~
63
+
64
+ #### Regression Testing
65
+
66
+ Every time Origen generates a pattern it will check to see if it has generated it before, and
67
+ if so it will compare the current version to the previous version and alert if there is a
68
+ difference. This can be used to check for regressions when making changes that you don't want
69
+ to affect the output, or to verify that the change is what you intended in cases where you
70
+ are intentionally modifying the output.
71
+
72
+ The diff is a smart diff and will not care about any changes to comments, only about changes
73
+ that will affect the pattern's operation.
74
+
75
+ In the case of a difference being found Origen will automatically present you with the diff command
76
+ to run if you want to view the change.
77
+
78
+ To accept changes or to start tracking the differences in a pattern (or patterns) run the following command
79
+ after generating:
80
+
81
+ ~~~text
82
+ origen save all
83
+ ~~~
84
+
85
+ #### Programmatically Launching the Generator
86
+
87
+ If you start writing your own [commands](<%= path "guides/misc/commands" %>) you may want
88
+ to launch the generator from Ruby, do that as follows:
89
+
90
+ ~~~ruby
91
+ Origen.app.runner.launch action: :generate,
92
+ files: "list/production.list"
93
+ ~~~
94
+
95
+ This can be combined with [Target Loops](<%= path "guides/runtime/programming" %>) to run the
96
+ generator for multiple targets.
97
+
98
+ A generate job can also be posted to the LSF by supplying the same options that you would use
99
+ on the command line like this:
100
+
101
+ ~~~ruby
102
+ Origen.lsf.submit_origen_job("g march")
103
+ ~~~
104
+
105
+ % end