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.
- data/.gitignore +17 -0
- data/.travis.yml +6 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +16 -0
- data/adept.gemspec +33 -0
- data/autotest/discover.rb +2 -0
- data/bin/bprog +110 -0
- data/firmware/.gitignore +73 -0
- data/firmware/epp_stream/Basys2_100_250General.ucf +21 -0
- data/firmware/epp_stream/epp_controller.vhd +210 -0
- data/firmware/epp_stream/epp_stream.xise +355 -0
- data/firmware/epp_stream/fifo.vhd +178 -0
- data/firmware/epp_stream/tests/fifo_testbench.vhdl +164 -0
- data/lib/adept/boards/basys2.rb +84 -0
- data/lib/adept/boards.rb +2 -0
- data/lib/adept/connection_provider.rb +30 -0
- data/lib/adept/data_formats/bitstream.rb +116 -0
- data/lib/adept/data_formats/data_factories.rb +33 -0
- data/lib/adept/data_formats.rb +2 -0
- data/lib/adept/device.rb +127 -0
- data/lib/adept/error.rb +4 -0
- data/lib/adept/jtag/connection.rb +404 -0
- data/lib/adept/jtag/device.rb +178 -0
- data/lib/adept/jtag/devices/fpga.rb +162 -0
- data/lib/adept/jtag/devices/null.rb +0 -0
- data/lib/adept/jtag/devices/platform_flash.rb +23 -0
- data/lib/adept/jtag/devices.rb +2 -0
- data/lib/adept/jtag/error.rb +8 -0
- data/lib/adept/jtag/tap_state.rb +67 -0
- data/lib/adept/jtag/tap_states.rb +52 -0
- data/lib/adept/jtag.rb +11 -0
- data/lib/adept/low_level/connection.rb +59 -0
- data/lib/adept/low_level/device.rb +43 -0
- data/lib/adept/low_level/device_error.rb +22 -0
- data/lib/adept/low_level/device_manager.rb +142 -0
- data/lib/adept/low_level/enhanced_parallel.rb +151 -0
- data/lib/adept/low_level/error_handler.rb +60 -0
- data/lib/adept/low_level/jtag.rb +379 -0
- data/lib/adept/low_level/library.rb +173 -0
- data/lib/adept/low_level.rb +4 -0
- data/lib/adept/version.rb +3 -0
- data/lib/adept.rb +11 -0
- data/spec/firmware/epp_loopback.bit +0 -0
- data/spec/lib/adept/data_formats/bitstream_spec.rb +95 -0
- data/spec/lib/adept/data_formats/data_factories_spec.rb +42 -0
- data/spec/lib/adept/device_spec.rb +88 -0
- data/spec/lib/adept/jtag/connection_spec.rb +433 -0
- data/spec/lib/adept/jtag/device_spec.rb +107 -0
- data/spec/lib/adept/jtag/devices/fpga_spec.rb +71 -0
- data/spec/lib/adept/low_level/enhanced_parallel_spec.rb +72 -0
- data/spec/lib/adept/low_level/jtag_spec.rb +204 -0
- data/spec/spec_helpers.rb +25 -0
- 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
|