ruby-adept 0.0.1

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 (55) hide show
  1. data/.gitignore +17 -0
  2. data/.travis.yml +6 -0
  3. data/Gemfile +10 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +16 -0
  7. data/adept.gemspec +33 -0
  8. data/autotest/discover.rb +2 -0
  9. data/bin/bprog +110 -0
  10. data/firmware/.gitignore +73 -0
  11. data/firmware/epp_stream/Basys2_100_250General.ucf +21 -0
  12. data/firmware/epp_stream/epp_controller.vhd +210 -0
  13. data/firmware/epp_stream/epp_stream.xise +355 -0
  14. data/firmware/epp_stream/fifo.vhd +178 -0
  15. data/firmware/epp_stream/tests/fifo_testbench.vhdl +164 -0
  16. data/lib/adept/boards/basys2.rb +84 -0
  17. data/lib/adept/boards.rb +2 -0
  18. data/lib/adept/connection_provider.rb +30 -0
  19. data/lib/adept/data_formats/bitstream.rb +116 -0
  20. data/lib/adept/data_formats/data_factories.rb +33 -0
  21. data/lib/adept/data_formats.rb +2 -0
  22. data/lib/adept/device.rb +127 -0
  23. data/lib/adept/error.rb +4 -0
  24. data/lib/adept/jtag/connection.rb +404 -0
  25. data/lib/adept/jtag/device.rb +178 -0
  26. data/lib/adept/jtag/devices/fpga.rb +162 -0
  27. data/lib/adept/jtag/devices/null.rb +0 -0
  28. data/lib/adept/jtag/devices/platform_flash.rb +23 -0
  29. data/lib/adept/jtag/devices.rb +2 -0
  30. data/lib/adept/jtag/error.rb +8 -0
  31. data/lib/adept/jtag/tap_state.rb +67 -0
  32. data/lib/adept/jtag/tap_states.rb +52 -0
  33. data/lib/adept/jtag.rb +11 -0
  34. data/lib/adept/low_level/connection.rb +59 -0
  35. data/lib/adept/low_level/device.rb +43 -0
  36. data/lib/adept/low_level/device_error.rb +22 -0
  37. data/lib/adept/low_level/device_manager.rb +142 -0
  38. data/lib/adept/low_level/enhanced_parallel.rb +151 -0
  39. data/lib/adept/low_level/error_handler.rb +60 -0
  40. data/lib/adept/low_level/jtag.rb +379 -0
  41. data/lib/adept/low_level/library.rb +173 -0
  42. data/lib/adept/low_level.rb +4 -0
  43. data/lib/adept/version.rb +3 -0
  44. data/lib/adept.rb +11 -0
  45. data/spec/firmware/epp_loopback.bit +0 -0
  46. data/spec/lib/adept/data_formats/bitstream_spec.rb +95 -0
  47. data/spec/lib/adept/data_formats/data_factories_spec.rb +42 -0
  48. data/spec/lib/adept/device_spec.rb +88 -0
  49. data/spec/lib/adept/jtag/connection_spec.rb +433 -0
  50. data/spec/lib/adept/jtag/device_spec.rb +107 -0
  51. data/spec/lib/adept/jtag/devices/fpga_spec.rb +71 -0
  52. data/spec/lib/adept/low_level/enhanced_parallel_spec.rb +72 -0
  53. data/spec/lib/adept/low_level/jtag_spec.rb +204 -0
  54. data/spec/spec_helpers.rb +25 -0
  55. metadata +240 -0
@@ -0,0 +1,433 @@
1
+ require 'adept'
2
+ require 'adept/jtag/tap_states'
3
+
4
+ #Pull the relevant modules into the main namespace, for convenience.
5
+ include Adept
6
+ include JTAG::TAPStates
7
+
8
+ #
9
+ # Tests for the basic JTAG test connection.
10
+ #
11
+ describe JTAG::Connection do
12
+
13
+ PathToShiftIR = ["01100".reverse.to_i(2)]
14
+ PathToShiftDR = ["0100".reverse.to_i(2)]
15
+
16
+ before :each do
17
+
18
+ #Stub over the core low-level methods, allowing us to test without a real device.
19
+ LowLevel::JTAG::stub!(:EnableEx => nil, :transmit_mode_select => "\x00", :transmit_data => "\x00", :transmit_constants => "\x00", :tick => nil, :receive => "\x00")
20
+
21
+ #Create a new mock adept device.
22
+ @device = mock(Adept::Device)
23
+ @device.stub!(:handle).and_return(1)
24
+
25
+ #Establish a new JTAG Connection...
26
+ @jtag = JTAG::Connection.new(@device)
27
+
28
+ #And place the device into its "reset" state.
29
+ @jtag.reset_target
30
+
31
+ end
32
+
33
+ describe "#path_to_state" do
34
+
35
+ it "should be able to correctly idenitfy the path to any given state" do
36
+
37
+ @jtag.instance_eval do
38
+
39
+ #Path from reset to data states.
40
+ path_to_state(SelectDR).should == "01"
41
+ path_to_state(ShiftDR).should == "0100"
42
+ path_to_state(Exit1DR).should == "0101"
43
+ path_to_state(PauseDR).should == "01010"
44
+ path_to_state(UpdateDR).should == "01011"
45
+
46
+ #Path from reset to instruction states.
47
+ path_to_state(SelectIR).should == "011"
48
+ path_to_state(ShiftIR).should == "01100"
49
+ path_to_state(Exit1IR).should == "01101"
50
+ path_to_state(PauseIR).should == "011010"
51
+ path_to_state(UpdateIR).should == "011011"
52
+
53
+ #Paths from Exit1DR
54
+ @tap_state = Exit1DR
55
+ path_to_state(Exit1IR).should == "11101"
56
+
57
+ end
58
+
59
+ end
60
+ end
61
+
62
+ #
63
+ # TAP State Setter
64
+ #
65
+ describe "#tap_state=" do
66
+
67
+ it "should ask the target device to move to the appropriate state" do
68
+ #Ensure that our virtual target is placed into the ShiftIR state.
69
+ LowLevel::JTAG::should_receive(:transmit_mode_select).with(kind_of(Numeric), PathToShiftIR, false, 5, false)
70
+ @jtag.tap_state = ShiftIR
71
+ end
72
+
73
+ it "should adjust the internal state" do
74
+ LowLevel::JTAG::stub!(:transmit_mode_select)
75
+ @jtag.tap_state = ShiftIR
76
+ @jtag.tap_state.should == ShiftIR
77
+ end
78
+
79
+ end
80
+
81
+ #
82
+ # Transmit TAP instruction
83
+ #
84
+ describe "#transmit_instruction" do
85
+
86
+ it "should move the target into the ShiftIR state before transmission" do
87
+
88
+ #Ensure that our virtual target is placed into the ShiftIR state _prior_ to transmission.
89
+ LowLevel::JTAG::should_receive(:transmit_mode_select).with(kind_of(Numeric), PathToShiftIR, false, 5, false).ordered
90
+ LowLevel::JTAG::should_receive(:transmit_data).ordered
91
+ @jtag.transmit_instruction([0x09], 6)
92
+
93
+ end
94
+
95
+ it "should transmit the relevant instruction" do
96
+ @jtag.should_receive(:transmit_and_advance).with(anything, [0x09], 6, anything)
97
+ @jtag.transmit_instruction([0x09], 6)
98
+ end
99
+
100
+ it "should put the device into the Exit1IR state after transmission." do
101
+
102
+ #Ensure that our virtual target is placed into the Exit1 state _after_ transmission.
103
+ LowLevel::JTAG::should_receive(:transmit_data).ordered
104
+ @jtag.should_receive(:tap_state=).with(any_args)
105
+ @jtag.should_receive(:tap_state=).with(Exit1IR)
106
+ @jtag.transmit_instruction([0x09], 6)
107
+ end
108
+
109
+ it "should leave the device in the Exit1IR state" do
110
+ @jtag.transmit_instruction([0x09], 6)
111
+ @jtag.tap_state.should == Exit1IR
112
+ end
113
+
114
+ it "should correctly one-pad instructions to the chain length, when requested" do
115
+
116
+ #Set an arbitrary chain length of 40
117
+ @jtag.instance_variable_set(:@chain_length, 40)
118
+
119
+ #And ensure that 33 ones are transmitted after the data itself.
120
+ @jtag.should_receive(:transmit_and_advance).with(false, "\xAA", 7, anything).ordered.and_return("\x00")
121
+ @jtag.should_receive(:transmit_and_advance).with(false, true, 33, anything).ordered.and_return("\x00\x00\x00\x00\x00")
122
+
123
+ @jtag.transmit_instruction("\xAA", 7, true)
124
+
125
+ end
126
+
127
+ it "should correctly prefix the transmitted instruction with ones, when requested" do
128
+
129
+ #And ensure that 20 ones are transmitted _before_ the instruction itself.
130
+ LowLevel::JTAG::should_receive(:transmit_constants).with(kind_of(Numeric), false, true, 20, false).ordered
131
+ LowLevel::JTAG::should_receive(:transmit_data).with(kind_of(Numeric), false, "\xAA", kind_of(Numeric), false).ordered
132
+
133
+ @jtag.transmit_instruction("\xAA", 7, false, 20)
134
+
135
+ end
136
+
137
+ it "should be able apply both a prefix and one-padding to a single instruction" do
138
+
139
+ #Set an arbitrary chain length of 40
140
+ @jtag.instance_variable_set(:@chain_length, 40)
141
+
142
+ #Ensure that the 20 prefix ones are transmitted first, then the instruction, then the 13 padding ones.
143
+ LowLevel::JTAG::should_receive(:transmit_constants).with(kind_of(Numeric), false, true, 20, false).ordered
144
+ LowLevel::JTAG::should_receive(:transmit_data).with(kind_of(Numeric), false, "\xAA", 7, false).ordered
145
+ LowLevel::JTAG::should_receive(:transmit_constants).with(kind_of(Numeric), anything, true, 12, false).ordered
146
+ LowLevel::JTAG::should_receive(:transmit_constants).with(kind_of(Numeric), anything, true, 1, false).ordered
147
+
148
+ @jtag.transmit_instruction("\xAA", 7, true, 20)
149
+
150
+ end
151
+
152
+ end
153
+
154
+ #
155
+ # Trasmit TAP data
156
+ #
157
+ describe "#transmit_data" do
158
+
159
+ it "should move the target into the ShiftDR state before transmission" do
160
+
161
+ #Ensure that our virtual target is placed into the ShiftIR state _prior_ to transmission.
162
+ LowLevel::JTAG::should_receive(:transmit_mode_select).with(kind_of(Numeric), PathToShiftDR, false, 4, false).ordered
163
+ LowLevel::JTAG::should_receive(:transmit_data).ordered
164
+
165
+ @jtag.transmit_data([0x09], 6)
166
+
167
+ end
168
+
169
+ it "should transmit the relevant data" do
170
+ @jtag.should_receive(:transmit_and_advance).with(anything, [0x09], 6, anything)
171
+ @jtag.transmit_instruction([0x09], 6)
172
+ end
173
+
174
+ it "should put the device into the Exit1DR state after transmission." do
175
+
176
+ #Ensure that our virtual target is placed into the Exit1 state _after_ transmission.
177
+ @jtag.should_receive(:tap_state=).with(any_args).ordered
178
+ LowLevel::JTAG::should_receive(:transmit_data).ordered
179
+ @jtag.should_receive(:tap_state=).with(Exit1DR).ordered
180
+
181
+ @jtag.transmit_data([0x09], 6)
182
+
183
+ end
184
+
185
+ it "should leave the device in the Exit1DR state" do
186
+ @jtag.transmit_data([0x09], 6)
187
+ @jtag.tap_state.should == Exit1DR
188
+ end
189
+
190
+ it "should correctly zero-pad data to the chain length, when requested" do
191
+
192
+ #Set an arbitrary device count.
193
+ @jtag.instance_variable_set(:@devices_in_chain, 3)
194
+
195
+ #And ensure that two zeroes are transmitted after the data itself, filling the bypass registers of
196
+ @jtag.should_receive(:transmit_and_advance).with(false, "\xAA", 7, anything).ordered.and_return("\x00")
197
+ @jtag.should_receive(:transmit_and_advance).with(false, false, 2, anything).ordered.and_return("\x00")
198
+
199
+ @jtag.transmit_data("\xAA", 7, true)
200
+
201
+ end
202
+
203
+ it "should correctly prefix the transmitted data with zeroes, when requested" do
204
+
205
+ #And ensure that 10 zeroes are transmitted _before_ the instruction itself.
206
+ LowLevel::JTAG::should_receive(:transmit_constants).with(kind_of(Numeric), false, false, 10, false).ordered
207
+ LowLevel::JTAG::should_receive(:transmit_data).with(kind_of(Numeric), false, "\xAA", anything, false).ordered
208
+
209
+ @jtag.transmit_data("\xAA", 7, false, 10)
210
+
211
+ end
212
+
213
+ it "should be able apply both a prefix and zero-padding to a single piece of data" do
214
+
215
+ #Set an arbitrary chain length of 40
216
+ @jtag.instance_variable_set(:@devices_in_chain, 10)
217
+
218
+ #Ensure that the 20 prefix ones are transmitted first, then the instruction, then the 4 padding zeroes.
219
+ LowLevel::JTAG::should_receive(:transmit_constants).with(kind_of(Numeric), false, false, 5, false).ordered
220
+ LowLevel::JTAG::should_receive(:transmit_data).with(kind_of(Numeric), false, "\xAA", 7, false).ordered
221
+ LowLevel::JTAG::should_receive(:transmit_constants).with(kind_of(Numeric), anything, false, 3, false).ordered
222
+ LowLevel::JTAG::should_receive(:transmit_constants).with(kind_of(Numeric), anything, false, 1, false).ordered
223
+
224
+ @jtag.transmit_data("\xAA", 7, true, 5)
225
+
226
+ end
227
+
228
+ end
229
+
230
+ #
231
+ # Receive TAP data
232
+ #
233
+ describe "#receive_data" do
234
+
235
+ it "should move the target into the ShiftDR state before receiving" do
236
+
237
+ #Ensure that our virtual target is placed into the ShiftIR state _prior_ to transmission.
238
+ LowLevel::JTAG::should_receive(:transmit_mode_select).with(kind_of(Numeric), PathToShiftDR, false, 4, false).ordered
239
+ LowLevel::JTAG::should_receive(:receive).ordered
240
+
241
+ @jtag.receive_data(6, true)
242
+
243
+ end
244
+
245
+ it "should receive the relevant data" do
246
+ LowLevel::JTAG::should_receive(:receive).with(kind_of(Numeric), false, false, 6, false)
247
+ @jtag.receive_data(6)
248
+ end
249
+
250
+ it "should put the device into the Exit1DR state after transmission." do
251
+
252
+ #Ensure that our virtual target is placed into the Exit1 state _after_ transmission.
253
+ @jtag.should_receive(:tap_state=).with(any_args).ordered
254
+ LowLevel::JTAG::should_receive(:receive).ordered
255
+ @jtag.should_receive(:tap_state=).with(Exit1DR).ordered
256
+
257
+ @jtag.receive_data(6)
258
+
259
+ end
260
+
261
+ it "should leave the device in the Exit1DR state" do
262
+ @jtag.receive_data(6)
263
+ @jtag.tap_state.should == Exit1DR
264
+ end
265
+
266
+ end
267
+
268
+ #
269
+ # Transmit data, and advance the TAP FSM by a single state.
270
+ #
271
+ describe "#transmit_and_advance" do
272
+
273
+ it "should send the data requested in two separate transmissions: one with all but the last bit, and one with the last bit" do
274
+ LowLevel::JTAG::should_receive(:transmit).with(kind_of(Numeric), anything, "\xFF", 7, anything).ordered.and_return("\x00")
275
+ LowLevel::JTAG::should_receive(:transmit).with(kind_of(Numeric), anything, true, 1, anything).ordered
276
+ @jtag.send(:transmit_and_advance, true, "\xFF", 8, JTAG::TAPStates::Idle)
277
+ end
278
+
279
+ it "should hold TMS at the provided constant for all but the last bit of the transmission" do
280
+ LowLevel::JTAG::should_receive(:transmit).with(kind_of(Numeric), true, anything, kind_of(Numeric), anything).ordered.and_return("\x00")
281
+ LowLevel::JTAG::should_receive(:transmit).with(any_args).ordered
282
+ @jtag.send(:transmit_and_advance, true, "\xFF", 8, JTAG::TAPStates::Idle)
283
+ end
284
+
285
+ it "should use the provided desired-state to determine the value of TMS during transmission of the final bit" do
286
+ LowLevel::JTAG::should_receive(:transmit).with(any_args).ordered.and_return("\x00")
287
+ LowLevel::JTAG::should_receive(:transmit).with(kind_of(Numeric), false, anything, 1, anything).ordered
288
+ @jtag.send(:transmit_and_advance, true, "\xFF", 8, JTAG::TAPStates::Idle)
289
+ end
290
+
291
+ it "should advance the TAP FSM according to the finite state machine" do
292
+ LowLevel::JTAG::stub!(:transmit => "\x00")
293
+ @jtag.send(:transmit_and_advance, true, "\xFF", 8, JTAG::TAPStates::Idle)
294
+ @jtag.tap_state.should == JTAG::TAPStates::Idle
295
+ end
296
+
297
+ it "should not vary TMS if the state to advance towards is nil" do
298
+ LowLevel::JTAG::should_receive(:transmit).with(kind_of(Numeric), true, anything, 8, anything).and_return("\x00")
299
+ @jtag.send(:transmit_and_advance, true, "\xFF", 8, nil)
300
+ end
301
+
302
+ it "should not advance the TAP FSM if the state to advance towards is nil" do
303
+ LowLevel::JTAG::stub!(:transmit => "\x00")
304
+ @jtag.send(:transmit_and_advance, true, "\xFF", 8, nil)
305
+ @jtag.tap_state.should == JTAG::TAPStates::Reset
306
+ end
307
+
308
+ it "should return the combined values of the first and second transmissions" do
309
+ LowLevel::JTAG::should_receive(:transmit).with(any_args).and_return("\x7F", "\x01")
310
+ @jtag.send(:transmit_and_advance, true, "\xAA", 8, JTAG::TAPStates::Idle).should == "\xFF"
311
+ end
312
+
313
+ end
314
+
315
+ describe "#add_bit_to_message" do
316
+
317
+ it "should be able to merge a bit into a string of bytes" do
318
+ @jtag.send(:add_bit_to_message, "\x7F", 7, true).should == "\xFF"
319
+ @jtag.send(:add_bit_to_message, "\x7F\xFF", 15, true).should == "\xFF\xFF"
320
+ @jtag.send(:add_bit_to_message, "\x7F\xFF", 15, false).should == "\x7F\xFF"
321
+ end
322
+
323
+ end
324
+
325
+ describe "#bit_of_message" do
326
+
327
+ it "should return the provided bit from a string message" do
328
+ @jtag.send(:bit_of_message, "\xAA\xAA", 0).should be_false
329
+ @jtag.send(:bit_of_message, "\xAA\xAA", 1).should be_true
330
+ @jtag.send(:bit_of_message, "\xAA\xAA", 14).should be_false
331
+ @jtag.send(:bit_of_message, "\xAA\xAA", 15).should be_true
332
+ end
333
+
334
+ it "should return any provided boolean value directly, no matter the bit number" do
335
+ @jtag.send(:bit_of_message, true, 0).should be_true
336
+ @jtag.send(:bit_of_message, false, 0).should be_false
337
+ @jtag.send(:bit_of_message, true, 8).should be_true
338
+ @jtag.send(:bit_of_message, false, 8).should be_false
339
+ end
340
+
341
+ end
342
+
343
+
344
+ #
345
+ # Run the target device's test.
346
+ #
347
+ describe "#run_test" do
348
+
349
+ it "should move the target into the Idle state prior to its main function" do
350
+
351
+ path_to_idle = [0]
352
+
353
+ #Ensure that our virtual target is placed into the ShiftIR state _prior_ to transmission.
354
+ LowLevel::JTAG::should_receive(:transmit_mode_select).with(kind_of(Numeric), path_to_idle, false, 1, false).ordered
355
+ LowLevel::JTAG::should_receive(:tick).ordered
356
+
357
+ @jtag.run_test(100)
358
+
359
+ end
360
+
361
+ it "should cause TCK to tick the specified number of times with TDO/TMS low" do
362
+ LowLevel::JTAG::should_receive(:tick).with(kind_of(Numeric), false, false, 100, false)
363
+ @jtag.run_test(100)
364
+ end
365
+
366
+ it "should leave the device in the Idle state" do
367
+ @jtag.run_test(100)
368
+ @jtag.tap_state.should == Idle
369
+ end
370
+
371
+ end
372
+
373
+ #
374
+ # Enumerate all connected devices, by IDCode.
375
+ #
376
+ describe "#connected_devices" do
377
+
378
+ it "should reset the device before proceeding" do
379
+ @jtag.should_receive(:reset_target).ordered
380
+ @jtag.should_receive(:receive_data).ordered.and_return("\x00\x00\x00\x00")
381
+
382
+ @jtag.connected_devices
383
+ end
384
+
385
+ it "should return an empty array when no devices are detected" do
386
+ @jtag.should_receive(:receive_data).and_return("\x00\x00\x00\x00")
387
+ @jtag.connected_devices.should == []
388
+ end
389
+
390
+ it "should return an array of devices if IDcodes are recieved" do
391
+ @jtag.should_receive(:receive_data).and_return("\x12\x34\x56\x78", "\xAB\xCD\xEF\xFF", "\x00\x00\x00\x00")
392
+ @jtag.connected_devices.each { |d| d.class.kind_of?(Device)}
393
+ end
394
+
395
+ it "should return devices with the appropriate ID codes" do
396
+ @jtag.should_receive(:receive_data).and_return("\x12\x34\x56\x78", "\xAB\xCD\xEF\xFF", "\x00\x00\x00\x00")
397
+ idcodes = @jtag.connected_devices.collect { |d| d.idcode }
398
+ idcodes.should == ["\xFF\xEF\xCD\xAB", "\x78\x56\x34\x12"]
399
+ end
400
+
401
+ it "should correctly determine the length of the instruction scan chain" do
402
+ @jtag.should_receive(:receive_data).and_return("\x93\x50\x04\xD5", "\x93\xA0\xC1\x11", "\x00\x00\x00\x00")
403
+ @jtag.connected_devices
404
+ @jtag.instance_variable_get(:@chain_length).should == 8 + 6
405
+ end
406
+
407
+ it "should be able to identify the devices on a Basys2 board" do
408
+
409
+ @jtag.should_receive(:receive_data).and_return("\x93\x50\x04\xD5", "\x93\xA0\xC1\x11", "\x00\x00\x00\x00")
410
+ devices = @jtag.connected_devices
411
+
412
+ #Check the ID Codes...
413
+ idcodes = devices.collect { |d| d.idcode }
414
+ idcodes.should == ["\x11\xC1\xA0\x93", "\xD5\x04\x50\x93"]
415
+
416
+ #... the types...
417
+ types = devices.collect { |d| d.class }
418
+ types.should == [JTAG::Devices::FPGA, JTAG::Devices::PlatformFlash]
419
+
420
+ #... the positions in the chain...
421
+ positions = devices.collect { |d| d.instance_variable_get(:@position_in_chain) }
422
+ positions.should == [1, 0]
423
+
424
+ #... and the chain widths.
425
+ widths = devices.collect { |d| d.instance_variable_get(:@chain_offset) }
426
+ widths.should == [8, 0]
427
+
428
+ end
429
+
430
+
431
+ end
432
+
433
+ end
@@ -0,0 +1,107 @@
1
+
2
+ require 'adept/jtag'
3
+
4
+ include Adept
5
+
6
+ #
7
+ # Tests for the JTAGDevice base module.
8
+ #
9
+ #
10
+ describe Device do
11
+
12
+ before :all do
13
+
14
+ #Create two simple test devices "stub" class.
15
+ class DeviceA < JTAG::Device
16
+ InstructionWidth = 6
17
+ Instructions = { :instruct => 0b101010 }
18
+ supports_idcode "abcdefff"
19
+ end
20
+
21
+ class DeviceB < JTAG::Device
22
+ InstructionWidth = 8
23
+ Instructions = { :instruct => 0b10101010 }
24
+ supports_idcode "01020304"
25
+ end
26
+
27
+ end
28
+
29
+ describe ".included" do
30
+
31
+ it "should keep track of all classes which extend JTAGDevice" do
32
+ device_types = JTAG::Device.instance_variable_get(:@device_types)
33
+ device_types.should include(DeviceA, DeviceB)
34
+ end
35
+
36
+ end
37
+
38
+ describe "#instruction_width" do
39
+
40
+ it "should return the correct instruction width a given device" do
41
+ DeviceA.new(nil, nil, 0, 0).instruction_width.should == 6
42
+ DeviceB.new(nil, nil, 0, 0).instruction_width.should == 8
43
+ end
44
+
45
+ end
46
+
47
+ describe "#device_from_idcode" do
48
+
49
+ it "should be able to create devices with the appropriate type given their IDCode" do
50
+ JTAG::Device.from_idcode("\xAB\xCD\xEF\xFF", nil, 0, 0).class.should == DeviceA
51
+ JTAG::Device.from_idcode("\x01\x02\x03\x04", nil, 0, 0).class.should == DeviceB
52
+ end
53
+
54
+ it "should create a generic JTAGDevice when its IDCode isn't recognized" do
55
+ JTAG::Device.from_idcode("\x00\x00\x00\x00", nil, 0, 0).class.should == JTAG::Device
56
+ end
57
+
58
+ end
59
+
60
+ describe "device communication functions" do
61
+
62
+ let(:connection) { mock(JTAG::Connection) }
63
+ let(:device) { DeviceB.new("\xAB\xCD\xEF\xFF", connection, 1, 6) }
64
+
65
+
66
+ describe "#instruction=" do
67
+
68
+ it "should set the target device's instruction, and place the rest of the chain into bypass" do
69
+ connection.should_receive(:transmit_instruction).with("\xAA", device.instruction_width, true, 6)
70
+ device.instruction = "\xAA"
71
+ end
72
+
73
+ it "should accept instructions in numeric format" do
74
+ connection.should_receive(:transmit_instruction).with("\xAA", device.instruction_width, true, 6)
75
+ device.instruction = 0b10101010
76
+ end
77
+
78
+ it "should accept symbolic names for known instructions" do
79
+ connection.should_receive(:transmit_instruction).with("\xAA", device.instruction_width, true, 6)
80
+ device.instruction = :instruct
81
+ end
82
+
83
+
84
+ end
85
+
86
+ describe "#transmit_data" do
87
+
88
+ it "should send the target device's data, prefixed with enough zeroes to pass through the preceeding devices' bypass registers" do
89
+ connection.should_receive(:transmit_data).with("\xAA", 7, true, kind_of(Numeric))
90
+ device.transmit_data("\xAA", 7)
91
+ end
92
+
93
+ end
94
+
95
+
96
+ describe "#receive_data" do
97
+
98
+ it "should receieve data from the target device by sending an appropriately long string of zeroes" do
99
+ connection.should_receive(:transmit_data).with(false, 7, true, kind_of(Numeric), anything)
100
+ device.receive_data(7)
101
+ end
102
+
103
+ end
104
+
105
+
106
+ end
107
+ end
@@ -0,0 +1,71 @@
1
+
2
+ require 'adept/jtag'
3
+
4
+ include Adept
5
+
6
+ #
7
+ # Tests for the JTAGDevice base module.
8
+ #
9
+ #
10
+ describe JTAG::Devices::FPGA do
11
+
12
+ let(:device) { JTAG::Devices::FPGA.new("\xA2\xC2\xA0\x93", mock(JTAG::Connection), 2, 8)}
13
+
14
+ describe "#verify_idcode" do
15
+
16
+ it "should send the Xilinx IDCode instruction" do
17
+
18
+ #Set up the device to recieve a valid IDCode.
19
+ device.stub!(:receive_data).and_return("\x93\xa0\xc2\xa2")
20
+ device.stub!(:run_test)
21
+ device.should_receive(:instruction=).with(:idcode)
22
+
23
+ device.verify_idcode
24
+ end
25
+
26
+ it "should throw an error when the FPGA returns an IDcode other than the one with which the device was created" do
27
+
28
+ #Set up the device to recieve a invalid IDCode.
29
+ device.stub!(:receive_data).and_return("\x00\xa0\xc2\xa2")
30
+ device.stub!(:run_test)
31
+ device.should_receive(:instruction=).with(:idcode)
32
+
33
+ expect { device.verify_idcode }.to raise_error(JTAG::Error)
34
+
35
+ end
36
+
37
+ it "should not throw an error when the FPGA and internal IDcode match" do
38
+
39
+ #Set up the device to recieve a invalid IDCode.
40
+ device.stub!(:receive_data).and_return("\x93\xa0\xc2\xa2")
41
+ device.stub!(:run_test)
42
+ device.should_receive(:instruction=).with(:idcode)
43
+
44
+ expect { device.verify_idcode }.to_not raise_error(JTAG::Error)
45
+
46
+ end
47
+
48
+ describe "online tests", :online => true do
49
+
50
+ before :all do
51
+ @real_board = Adept::Device.by_name('Basys2')
52
+ @real_connection = JTAG::Connection.new(@real_board, 0)
53
+ @real_device = @real_connection.connected_devices.first
54
+ end
55
+
56
+ after :all do
57
+ @real_connection.close
58
+ @real_board.close
59
+ end
60
+
61
+ it "should be able to verify the IDcode produced by a Basys2 board" do
62
+ expect { @real_device.verify_idcode }.to_not raise_error
63
+ end
64
+
65
+ it "should be able to detect the usercode of a design" do
66
+ @real_device.usercode.should == "FFFFFFFF"
67
+ end
68
+
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,72 @@
1
+ #
2
+ # These tests assume _one_ single connected Basys2-250K board!
3
+ #
4
+
5
+ require 'adept'
6
+ require 'adept/low_level'
7
+
8
+ require 'spec_helpers'
9
+ include SpecHelpers
10
+
11
+ #Pull the relevant modules into the main namespace, for convenience.
12
+ include Adept
13
+
14
+ describe LowLevel::EnhancedParallel do
15
+
16
+ subject { LowLevel::EnhancedParallel }
17
+
18
+ describe "on-line functionality", :online => true, :long => true do
19
+
20
+ #Program the Basys board with the EPP loopback program, for testing.
21
+ before :all do
22
+ preload_firmware 'epp_loopback'
23
+ end
24
+
25
+ before :each do
26
+ @device = Boards::Basys2.new
27
+ end
28
+
29
+ after :each do
30
+ @device.close
31
+ end
32
+
33
+ #Get an easy reference to the device's handle.
34
+ let(:handle) { @device.handle }
35
+
36
+
37
+ it "should detect that a Basys2 board supports EPP" do
38
+ subject.supported?(handle).should be_true
39
+ end
40
+
41
+ it "should detect exactly one EPP port on a Basys2 board" do
42
+ subject.port_count(handle).should == 1
43
+ end
44
+
45
+ it "should be able to open an EPP connectoin " do
46
+ subject.EnableEx(handle, 0)
47
+ end
48
+
49
+ it "should be able to _close_ an EPP connection" do
50
+ subject.EnableEx(handle, 0)
51
+ subject.Disable(handle)
52
+ end
53
+
54
+ describe "post-connection tests" do
55
+
56
+ before :each do
57
+ subject.EnableEx(handle, 0)
58
+ end
59
+
60
+ after :all do
61
+ subject.Disable(handle)
62
+ end
63
+
64
+ it "should be able to get/set the value of the given EPP register" do
65
+ subject.set_register_value(handle, 0, 123)
66
+ subject.get_register_value(handle, 0).should == 123
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+ end