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,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