xilinx-provision 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.project +17 -0
- data/.rspec +1 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +36 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +57 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/bin/xilinx-provision +10 -0
- data/bin/xilinx-provision-setup +11 -0
- data/lib/xilinx/provision.rb +25 -0
- data/lib/xilinx/provision/cable_driver.rb +95 -0
- data/lib/xilinx/provision/cable_firmware.rb +88 -0
- data/lib/xilinx/provision/impact.rb +157 -0
- data/lib/xilinx/provision/udev.rb +46 -0
- data/spec/fixtures/ethernet_ping.bit +0 -0
- data/spec/fixtures/impact_detect +75 -0
- data/spec/fixtures/snippet.rules +3 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/xilinx/provision/cable_driver_spec.rb +54 -0
- data/spec/xilinx/provision/cable_firmware_spec.rb +55 -0
- data/spec/xilinx/provision/impact_spec.rb +85 -0
- data/spec/xilinx/provision/udev_spec.rb +41 -0
- data/spec/xilinx/provision_spec.rb +26 -0
- metadata +184 -0
data/.document
ADDED
data/.project
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<projectDescription>
|
3
|
+
<name>xilinx-provision</name>
|
4
|
+
<comment></comment>
|
5
|
+
<projects>
|
6
|
+
</projects>
|
7
|
+
<buildSpec>
|
8
|
+
<buildCommand>
|
9
|
+
<name>com.aptana.ide.core.unifiedBuilder</name>
|
10
|
+
<arguments>
|
11
|
+
</arguments>
|
12
|
+
</buildCommand>
|
13
|
+
</buildSpec>
|
14
|
+
<natures>
|
15
|
+
<nature>com.aptana.ruby.core.rubynature</nature>
|
16
|
+
</natures>
|
17
|
+
</projectDescription>
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source 'http://rubygems.org'
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem 'activesupport', '>= 2.3.5'
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem 'rdoc', '>= 3.6.1'
|
10
|
+
gem 'rspec', '~> 2.6.0'
|
11
|
+
gem 'bundler', '~> 1.0.14'
|
12
|
+
gem 'jeweler', '~> 1.6.1'
|
13
|
+
gem 'rcov', '>= 0', :platform => :mri
|
14
|
+
|
15
|
+
gem 'ether_ping', '~> 0.3.1'
|
16
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
diff-lcs (1.1.2)
|
5
|
+
ether_ping (0.3.1)
|
6
|
+
ethernet (>= 0.1.0)
|
7
|
+
ethernet (0.1.3)
|
8
|
+
ffi (>= 1.0.0)
|
9
|
+
ffi (1.0.9)
|
10
|
+
git (1.2.5)
|
11
|
+
jeweler (1.6.2)
|
12
|
+
bundler (~> 1.0)
|
13
|
+
git (>= 1.2.5)
|
14
|
+
rake
|
15
|
+
rake (0.9.1)
|
16
|
+
rcov (0.9.9)
|
17
|
+
rdoc (3.6.1)
|
18
|
+
rspec (2.6.0)
|
19
|
+
rspec-core (~> 2.6.0)
|
20
|
+
rspec-expectations (~> 2.6.0)
|
21
|
+
rspec-mocks (~> 2.6.0)
|
22
|
+
rspec-core (2.6.3)
|
23
|
+
rspec-expectations (2.6.0)
|
24
|
+
diff-lcs (~> 1.1.2)
|
25
|
+
rspec-mocks (2.6.0)
|
26
|
+
|
27
|
+
PLATFORMS
|
28
|
+
ruby
|
29
|
+
|
30
|
+
DEPENDENCIES
|
31
|
+
bundler (~> 1.0.14)
|
32
|
+
ether_ping (~> 0.3.1)
|
33
|
+
jeweler (~> 1.6.1)
|
34
|
+
rcov
|
35
|
+
rdoc (>= 3.6.1)
|
36
|
+
rspec (~> 2.6.0)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Massachusetts Institute of Technology
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
= xilinx-provision
|
2
|
+
|
3
|
+
Automates the tasks involved in uploading a bitfile to a Xilinx FPGA board.
|
4
|
+
|
5
|
+
== Disclaimer
|
6
|
+
|
7
|
+
The authors are not affiliated in any way with Xilinx, Inc. We are sharing this code so that other researches won't have to duplicate the effort.
|
8
|
+
|
9
|
+
== Features
|
10
|
+
|
11
|
+
The gem automates the following tasks:
|
12
|
+
* builds a recent version of the USB cable driver
|
13
|
+
* writes udev rules for the USB cable driver
|
14
|
+
* writes udev rules for uploading firmware to the cable
|
15
|
+
* uploads a bitfile to a FPGA
|
16
|
+
|
17
|
+
== Usage
|
18
|
+
|
19
|
+
After installing the ruby gem, perform a one-time setup to get the USB cable set up.
|
20
|
+
|
21
|
+
sudo xilinx-provision-setup
|
22
|
+
|
23
|
+
Then upload a bitfile to your FPGA using
|
24
|
+
|
25
|
+
xilinx-provision path/to/bitfile
|
26
|
+
|
27
|
+
Notice that the setup command requires root access, but normal operation does not.
|
28
|
+
|
29
|
+
To program FPGAs automatically, use the following Ruby code.
|
30
|
+
|
31
|
+
require 'xilinx/provision'
|
32
|
+
Xilinx::Provision.fpga 'path/to/bitfile'
|
33
|
+
|
34
|
+
For advanced usage, see the examples in the bin/ and spec/ directories.
|
35
|
+
|
36
|
+
== Dependencies
|
37
|
+
|
38
|
+
Right now, the gem works in Debian-based Linux distributions. It should be easy to extend it to other Linux distributions.
|
39
|
+
|
40
|
+
I have no interest in making the gem work on Windows, but I would welcome patches that do so.
|
41
|
+
|
42
|
+
The gem assumes Xilinx ISE is installed. Any edition will work, including the WebPACK free edition. Download the software from:
|
43
|
+
http://www.xilinx.com/support/download/index.htm
|
44
|
+
|
45
|
+
== Contributing to xilinx-provision
|
46
|
+
|
47
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
48
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
49
|
+
* Fork the project
|
50
|
+
* Start a feature/bugfix branch
|
51
|
+
* Commit and push until you are happy with your contribution
|
52
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
53
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
54
|
+
|
55
|
+
== Copyright
|
56
|
+
|
57
|
+
Copyright (c) 2011 Massachusetts Institute of Technology. See LICENSE.txt for further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "xilinx-provision"
|
18
|
+
gem.homepage = "http://github.com/csail/xilinx-provision"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Deploys bitfiles to Xilinx FPGAs}
|
21
|
+
gem.description = %Q{Wraps the impact CLI tool in the Xilinx ISE}
|
22
|
+
gem.email = "victor@costan.us"
|
23
|
+
gem.authors = ["Victor Costan"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rspec/core'
|
29
|
+
require 'rspec/core/rake_task'
|
30
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
31
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
32
|
+
end
|
33
|
+
|
34
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
35
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
36
|
+
spec.rcov = true
|
37
|
+
end
|
38
|
+
|
39
|
+
task :default => :spec
|
40
|
+
|
41
|
+
require 'rdoc/task'
|
42
|
+
Rake::RDocTask.new do |rdoc|
|
43
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
44
|
+
|
45
|
+
rdoc.rdoc_dir = 'rdoc'
|
46
|
+
rdoc.title = "xilinx-provision #{version}"
|
47
|
+
rdoc.rdoc_files.include('README*')
|
48
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# :nodoc: namespace
|
2
|
+
module Xilinx
|
3
|
+
|
4
|
+
# Documentation here.
|
5
|
+
module Provision
|
6
|
+
# Programs an FPGA chip on a JTAG chain.
|
7
|
+
#
|
8
|
+
# The options argument accepts the following keys:
|
9
|
+
# :cable_port:: set to :auto by default
|
10
|
+
#
|
11
|
+
# Raises an exception if programming fails, returns true otherwise.
|
12
|
+
def self.fpga(bitfile, options = {})
|
13
|
+
if output = Xilinx::Provision::Impact.program_fpga(bitfile, options)
|
14
|
+
raise "Failed to program device!\nCommand output:\n#{output}"
|
15
|
+
end
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end # namespace Xilinx::Provision
|
19
|
+
|
20
|
+
end # namespace Xilinx
|
21
|
+
|
22
|
+
require 'xilinx/provision/cable_driver.rb'
|
23
|
+
require 'xilinx/provision/cable_firmware.rb'
|
24
|
+
require 'xilinx/provision/impact.rb'
|
25
|
+
require 'xilinx/provision/udev.rb'
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'English'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'tmpdir'
|
4
|
+
|
5
|
+
# :nodoc namespace
|
6
|
+
module Xilinx
|
7
|
+
|
8
|
+
# :nodoc namespace
|
9
|
+
module Provision
|
10
|
+
|
11
|
+
# Drives the setup of the USB cable driver needed to talk to Xilinx boards.
|
12
|
+
module CableDriver
|
13
|
+
# Performs all the setup needed for the USB cable driver.
|
14
|
+
#
|
15
|
+
# Returns a false value in case of success, or a string with error information
|
16
|
+
# if something goes wrong.
|
17
|
+
def self.setup
|
18
|
+
if output = build_prerequisites
|
19
|
+
return "Error while obtaining driver prerequisites:\n#{output}"
|
20
|
+
elsif output = build(path)
|
21
|
+
return "Error while building driver:\n#{output}"
|
22
|
+
elsif output = configure_udev
|
23
|
+
return "Error while configuring cable driver udev rules\n#{output}"
|
24
|
+
elsif output = Xilinx::Provision::Udev.reload_rules
|
25
|
+
return "Error while loading cable driver udev rules\n#{output}"
|
26
|
+
end
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
# Installs the packages needed to build the cable driver.
|
31
|
+
#
|
32
|
+
# Returns a false value for success, and a string containing error output if
|
33
|
+
# the build goes wrong.
|
34
|
+
def self.build_prerequisites
|
35
|
+
if File.exist?(`which apt-get`.strip)
|
36
|
+
# The literal `apt-get ...` doesn't use Kernel.` and can't be stubbed.
|
37
|
+
output = Kernel.`(
|
38
|
+
'apt-get install -y git-core libusb-dev build-essential fxload 2>&1')
|
39
|
+
$CHILD_STATUS.to_i == 0 ? nil : output
|
40
|
+
else
|
41
|
+
"Unsupported OS / distribution\n"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Builds the cable driver.
|
46
|
+
#
|
47
|
+
# Assumes the build requirements have been installed by build_prerequisites.
|
48
|
+
#
|
49
|
+
# Args:
|
50
|
+
# target_path:: directory that will contain the driver
|
51
|
+
#
|
52
|
+
# Returns the command's output.
|
53
|
+
def self.build(target_path)
|
54
|
+
target_path = File.expand_path target_path
|
55
|
+
Dir.mktmpdir do |temp_dir|
|
56
|
+
Dir.chdir temp_dir do
|
57
|
+
output = `git clone -q #{git_url} 2>&1`
|
58
|
+
return output if $CHILD_STATUS.to_i != 0
|
59
|
+
Dir.chdir 'usb-driver' do
|
60
|
+
output = `make all 2>&1`
|
61
|
+
return output if $CHILD_STATUS.to_i != 0
|
62
|
+
FileUtils.cp 'libusb-driver.so', target_path
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
|
69
|
+
# Sets up the udev daemon to allow non-root access to the USB cable.
|
70
|
+
def self.configure_udev
|
71
|
+
Xilinx::Provision::Udev.add_rules udev_rules, '71-xilinx-usb-cable'
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
|
75
|
+
# Rules for the udev daemon to allow non-root access to the USB cable.
|
76
|
+
#
|
77
|
+
# Returns an array of rules to be written to a udev file.
|
78
|
+
def self.udev_rules
|
79
|
+
['ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="03fd", MODE="666"']
|
80
|
+
end
|
81
|
+
|
82
|
+
# The path to the driver file.
|
83
|
+
def self.path
|
84
|
+
File.expand_path '../libusb-driver.so', Xilinx::Provision::Impact.path
|
85
|
+
end
|
86
|
+
|
87
|
+
# The URL printed when no ISE installation is found.
|
88
|
+
def self.git_url
|
89
|
+
'git://git.zerfleddert.de/usb-driver'
|
90
|
+
end
|
91
|
+
end # namespace Xilinx::Provision::CableDriver
|
92
|
+
|
93
|
+
end # namespace Xilinx::Provision
|
94
|
+
|
95
|
+
end # namespace Xilinx
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# :nodoc namespace
|
2
|
+
module Xilinx
|
3
|
+
|
4
|
+
# :nodoc namespace
|
5
|
+
module Provision
|
6
|
+
|
7
|
+
# Finds firmware files for the Xilinx USB cable and sets up automatic uploading.
|
8
|
+
#
|
9
|
+
# The USB cables are weird beasts. A cable contains a small FPGA that must be
|
10
|
+
# programmed every time the cable is powered up, which happens on every
|
11
|
+
# connection to the computer.
|
12
|
+
#
|
13
|
+
# Xilinx ISE ships with the firmware for all cable types, but it doesn't
|
14
|
+
# automatically upload the firmware when needed. Udev to the rescue!
|
15
|
+
module CableFirmware
|
16
|
+
# Performs all the setup needed for automated firmware upload.
|
17
|
+
#
|
18
|
+
# Returns a false value in case of success, or a string with error information
|
19
|
+
# if something goes wrong.
|
20
|
+
def self.setup
|
21
|
+
if output = configure_udev
|
22
|
+
return "Error while configuring firmware upload udev rules\n#{output}"
|
23
|
+
elsif output = Xilinx::Provision::Udev.reload_rules
|
24
|
+
return "Error while loading firmware upload udev rules\n#{output}"
|
25
|
+
end
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
# Sets up the udev daemon to allow non-root access to the USB cable.
|
30
|
+
def self.configure_udev
|
31
|
+
Xilinx::Provision::Udev.add_rules udev_rules,
|
32
|
+
'71-xilinx-usb-firmware-upload'
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
|
36
|
+
# Rules for the udev daemon to allow non-root access to the USB cable.
|
37
|
+
#
|
38
|
+
# Returns an array of rules to be written to a udev file.
|
39
|
+
def self.udev_rules
|
40
|
+
return nil unless path = rules_path
|
41
|
+
old_rules = File.read(rules_path).split("\n")
|
42
|
+
upgrade_rules old_rules, path
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns a
|
46
|
+
def self.upgrade_rules(old_rules, rules_path)
|
47
|
+
rules_dir = File.dirname rules_path
|
48
|
+
old_rules.map do |old_rule|
|
49
|
+
rule = old_rule.dup
|
50
|
+
# Update old udev syntax.
|
51
|
+
[['TEMPNODE', 'tempnode'], ['SYSFS', 'ATTRS'],
|
52
|
+
['BUS', 'SUBSYSTEMS']].each { |from, to| rule.gsub! from, to }
|
53
|
+
|
54
|
+
# Change firmware file references to point inside Xilinx ISE. It's very
|
55
|
+
# rude to copy crap straigt into /usr/share, Xilinx!
|
56
|
+
rule.gsub!(/ \S+\.hex /) do |filepath|
|
57
|
+
firmware_name = File.basename filepath.strip
|
58
|
+
" #{File.join(rules_dir, firmware_name)} "
|
59
|
+
end
|
60
|
+
|
61
|
+
rule
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# The path to the firmware upload rules file that ships with ISE.
|
66
|
+
#
|
67
|
+
# This file is written in old-style udev, so it needs to be converted.
|
68
|
+
#
|
69
|
+
# Returns a path to the rules file, or nil if the file cannot be found.
|
70
|
+
def self.rules_path
|
71
|
+
dir_path = Xilinx::Provision::Impact.path
|
72
|
+
until dir_path == '/' || dir_path.empty?
|
73
|
+
dir_path = File.dirname dir_path
|
74
|
+
matches = Dir[File.join(dir_path, '**', '*.rules')]
|
75
|
+
next if matches.empty?
|
76
|
+
if matches.length > 1
|
77
|
+
better_matches = Dir[File.join(dir_path, '**', 'xusbdfwu.rules')]
|
78
|
+
matches = better_matches unless better_matches.empty?
|
79
|
+
end
|
80
|
+
return matches.sort.last
|
81
|
+
end
|
82
|
+
nil
|
83
|
+
end
|
84
|
+
end # namespace Xilinx::Provision::CableFirmware
|
85
|
+
|
86
|
+
end # namespace Xilinx::Provision
|
87
|
+
|
88
|
+
end # namespace Xilinx
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
|
3
|
+
# :nodoc namespace
|
4
|
+
module Xilinx
|
5
|
+
|
6
|
+
# :nodoc namespace
|
7
|
+
module Provision
|
8
|
+
|
9
|
+
# Runs the impact tool.
|
10
|
+
module Impact
|
11
|
+
# Programs an FPGA chip on a JTAG chain.
|
12
|
+
#
|
13
|
+
# The options argument accepts the following keys:
|
14
|
+
# :cable_port:: set to :auto by default
|
15
|
+
#
|
16
|
+
# Returns a false value for success, or a string containing error output if
|
17
|
+
# something goes wrong.
|
18
|
+
def self.program_fpga(bitfile, options = {})
|
19
|
+
options = { :mode => :bscan }.merge options
|
20
|
+
options[:cable_port] ||= :auto
|
21
|
+
devices = identify_chain(options)
|
22
|
+
|
23
|
+
bitfile = File.expand_path bitfile
|
24
|
+
batch = [
|
25
|
+
'identify',
|
26
|
+
"assignFile -position #{devices.length} -file #{bitfile}",
|
27
|
+
"program -position #{devices.length}",
|
28
|
+
'cleanCableLock',
|
29
|
+
'closeCable'
|
30
|
+
]
|
31
|
+
options.merge! :batch => batch
|
32
|
+
output = run options
|
33
|
+
$CHILD_STATUS.to_i == 0 ? nil : output
|
34
|
+
end
|
35
|
+
|
36
|
+
# Scans the JTAG chain and returns the devices on it.
|
37
|
+
#
|
38
|
+
# The options argument accepts the following keys:
|
39
|
+
# :cable_port:: set to :auto by default
|
40
|
+
#
|
41
|
+
# Returns the command's output.
|
42
|
+
def self.identify_chain(options = {})
|
43
|
+
batch = ['identify', 'cleanCableLock', 'closeCable']
|
44
|
+
options = {:mode => :bscan, :cable_port => :auto, :batch => batch}
|
45
|
+
parse_identify run(options)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Extracts a JTAG chain from an impact identify command.
|
49
|
+
#
|
50
|
+
# Args:
|
51
|
+
# output:: the impact command output, obtained from Impact#run
|
52
|
+
#
|
53
|
+
# Returns an array of hashes with the following keys:
|
54
|
+
# name:: the device name, e.g. "Xilinx xc5vlx110t"
|
55
|
+
# version:: number reported by impact
|
56
|
+
def self.parse_identify(output)
|
57
|
+
lines = output.split("\n").each(&:strip!)
|
58
|
+
lines.each_with_index do |line, index|
|
59
|
+
if /ident.*chain/i =~ line
|
60
|
+
lines = lines[index..-1]
|
61
|
+
break
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
device_id_regexp = /'(\d+)':.*manufacturer.* id.*=([^,]+),.*version.*(\d+)/i
|
66
|
+
devices = []
|
67
|
+
device = {}
|
68
|
+
lines.each do |line|
|
69
|
+
if match = device_id_regexp.match(line)
|
70
|
+
device[:index] = match[1].to_i
|
71
|
+
device[:name] = match[2].strip
|
72
|
+
device[:version] = match[3].to_i
|
73
|
+
end
|
74
|
+
if /^\-+$/ =~ line && !device.empty?
|
75
|
+
devices << device
|
76
|
+
device = {}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
devices
|
80
|
+
end
|
81
|
+
|
82
|
+
# Runs the impact tool and returns the status.
|
83
|
+
#
|
84
|
+
# The options argument accepts the following keys:
|
85
|
+
# :batch:: array of commands to be written to a batch file and executed
|
86
|
+
# :mode:: device configuration mode (try :bscan for JTAG boundary scan)
|
87
|
+
# :cable_port:: (try :auto)
|
88
|
+
#
|
89
|
+
# Returns the command's output.
|
90
|
+
def self.run(options = {})
|
91
|
+
unless command_line =
|
92
|
+
"LD_PRELOAD=#{Xilinx::Provision::CableDriver.path} " + path
|
93
|
+
raise "Xilinx ISE not found\nPlease download from #{download_url}"
|
94
|
+
end
|
95
|
+
|
96
|
+
batch = options[:batch] && options[:batch].dup
|
97
|
+
|
98
|
+
if options[:cable_port]
|
99
|
+
command_line << " -port #{options[:cable_port]}"
|
100
|
+
batch.unshift "setCable -port #{options[:cable_port]}" if batch
|
101
|
+
end
|
102
|
+
if options[:mode]
|
103
|
+
command_line << " -mode #{options[:mode]}"
|
104
|
+
batch.unshift "setMode -#{options[:mode]}" if batch
|
105
|
+
end
|
106
|
+
batch.push 'quit' if batch && batch.last != 'quit'
|
107
|
+
|
108
|
+
output = nil
|
109
|
+
Dir.mktmpdir do |temp_dir|
|
110
|
+
Dir.chdir temp_dir do
|
111
|
+
if options[:batch]
|
112
|
+
File.open('impact_batch', 'wb') do |f|
|
113
|
+
f.write batch.map { |line| line + "\n" }.join
|
114
|
+
end
|
115
|
+
command_line << ' -batch impact_batch'
|
116
|
+
end
|
117
|
+
command_line << ' 2>&1'
|
118
|
+
output = Kernel.`(command_line)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
output
|
122
|
+
end
|
123
|
+
|
124
|
+
# Path to the impact binary.
|
125
|
+
def self.path
|
126
|
+
@path ||= path!
|
127
|
+
end
|
128
|
+
|
129
|
+
# Cached path.
|
130
|
+
@path = nil
|
131
|
+
|
132
|
+
# Path to the impact binary.
|
133
|
+
#
|
134
|
+
# This method does not cache its result and is really slow.
|
135
|
+
def self.path!
|
136
|
+
paths = Dir['/opt/**/impact']
|
137
|
+
paths = Dir['/usr/**/impact'] if paths.empty?
|
138
|
+
|
139
|
+
# 1 is a Fixnum which is a pointer, so its size shows 32/64-bit
|
140
|
+
if 1.size == 8
|
141
|
+
paths = paths.select { |path| path.index '64' }
|
142
|
+
else
|
143
|
+
paths = paths.reject { |path| path.index '64' }
|
144
|
+
end
|
145
|
+
|
146
|
+
paths.sort.last
|
147
|
+
end
|
148
|
+
|
149
|
+
# The URL printed when no ISE installation is found.
|
150
|
+
def self.download_url
|
151
|
+
'http://www.xilinx.com/support/download/index.htm'
|
152
|
+
end
|
153
|
+
end # namespace Xilinx::Provision::Impact
|
154
|
+
|
155
|
+
end # namespace Xilinx::Provision
|
156
|
+
|
157
|
+
end # namespace Xilinx
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'English'
|
2
|
+
|
3
|
+
# :nodoc namespace
|
4
|
+
module Xilinx
|
5
|
+
|
6
|
+
# :nodoc namespace
|
7
|
+
module Provision
|
8
|
+
|
9
|
+
# Runs the impact tool.
|
10
|
+
module Udev
|
11
|
+
# Installs a group of udev rules.
|
12
|
+
def self.add_rules(rules, group_name)
|
13
|
+
file = File.join rules_path, group_name + '.rules'
|
14
|
+
File.open file, 'w' do |f|
|
15
|
+
f.write rules.map { |rule| rule + "\n" }.join
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Removes a group of udev rules.
|
20
|
+
def self.remove_rules(group_name)
|
21
|
+
file = File.join rules_path, group_name + '.rules'
|
22
|
+
File.unlink file if File.exist?(file)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Asks udev to reload its rules to reflect updates done by add_rules.
|
26
|
+
#
|
27
|
+
# Returns a false value for success, or a string containing error output if
|
28
|
+
# something goes wrong.
|
29
|
+
def self.reload_rules
|
30
|
+
output = `/etc/init.d/udev restart 2>&1`
|
31
|
+
$CHILD_STATUS.to_i == 0 ? nil : output
|
32
|
+
end
|
33
|
+
|
34
|
+
# Directory or file containing the udev rules.
|
35
|
+
def self.rules_path
|
36
|
+
if File.exist? '/etc/udev/rules.d'
|
37
|
+
return '/etc/udev/rules.d'
|
38
|
+
else
|
39
|
+
raise "Unsupported OS or distribution."
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end # module Xilinx::Provision::Udev
|
43
|
+
|
44
|
+
end # module Xilinx::Provision
|
45
|
+
|
46
|
+
end # module Xilinx
|
Binary file
|
@@ -0,0 +1,75 @@
|
|
1
|
+
Release 13.1 - iMPACT O.40d (lin64)
|
2
|
+
Copyright (c) 1995-2011 Xilinx, Inc. All rights reserved.
|
3
|
+
Preference Table
|
4
|
+
Name Setting
|
5
|
+
StartupClock Auto_Correction
|
6
|
+
AutoSignature False
|
7
|
+
KeepSVF False
|
8
|
+
ConcurrentMode False
|
9
|
+
UseHighz False
|
10
|
+
ConfigOnFailure Stop
|
11
|
+
UserLevel Novice
|
12
|
+
MessageLevel Detailed
|
13
|
+
svfUseTime false
|
14
|
+
SpiByteSwap Auto_Correction
|
15
|
+
AutoInfer false
|
16
|
+
SvfPlayDisplayComments false
|
17
|
+
AutoDetecting cable. Please wait.
|
18
|
+
Using windrvr6 driver.
|
19
|
+
Connecting to cable (Usb Port - USB21).
|
20
|
+
Checking cable driver.
|
21
|
+
File version of /opt/Xilinx/13.1/ISE_DS/ISE/bin/lin64/xusbdfwu.hex = 1030.
|
22
|
+
File version of /etc/hotplug/usb/xusbdfwu.fw/xusbdfwu.hex = 1030.
|
23
|
+
libusb-driver.so version: 2011-03-25 19:15:17.
|
24
|
+
Cable PID = 0008.
|
25
|
+
Max current requested during enumeration is 150 mA.
|
26
|
+
Type = 0x0005.
|
27
|
+
Cable Type = 3, Revision = 0.
|
28
|
+
Setting cable speed to 6 MHz.
|
29
|
+
Cable connection established.
|
30
|
+
Firmware version = 2401.
|
31
|
+
File version of /opt/Xilinx/13.1/ISE_DS/ISE/data/xusb_xp2.hex = 2401.
|
32
|
+
Firmware hex file version = 2401.
|
33
|
+
PLD file version = 200Dh.
|
34
|
+
PLD version = 200Dh.
|
35
|
+
Type = 0x0005.
|
36
|
+
ESN option: 0000149C444901.
|
37
|
+
Identifying chain contents...'0': : Manufacturer's ID = Xilinx xc5vlx110t, Version : 10
|
38
|
+
INFO:iMPACT:1777 -
|
39
|
+
Reading /opt/Xilinx/13.1/ISE_DS/ISE/virtex5/data/xc5vlx110t.bsd...
|
40
|
+
INFO:iMPACT:501 - '1': Added Device xc5vlx110t successfully.
|
41
|
+
----------------------------------------------------------------------
|
42
|
+
----------------------------------------------------------------------
|
43
|
+
'1': : Manufacturer's ID = Xilinx xccace, Version : 0
|
44
|
+
INFO:iMPACT:1777 -
|
45
|
+
Reading /opt/Xilinx/13.1/ISE_DS/ISE/acecf/data/xccace.bsd...
|
46
|
+
INFO:iMPACT:501 - '1': Added Device xccace successfully.
|
47
|
+
----------------------------------------------------------------------
|
48
|
+
----------------------------------------------------------------------
|
49
|
+
'2': : Manufacturer's ID = Xilinx xc95144xl, Version : 5
|
50
|
+
INFO:iMPACT:1777 -
|
51
|
+
Reading /opt/Xilinx/13.1/ISE_DS/ISE/xc9500xl/data/xc95144xl.bsd...
|
52
|
+
INFO:iMPACT:501 - '1': Added Device xc95144xl successfully.
|
53
|
+
----------------------------------------------------------------------
|
54
|
+
----------------------------------------------------------------------
|
55
|
+
'3': : Manufacturer's ID = Xilinx xcf32p, Version : 15
|
56
|
+
INFO:iMPACT:1777 -
|
57
|
+
Reading /opt/Xilinx/13.1/ISE_DS/ISE/xcfp/data/xcf32p.bsd...
|
58
|
+
INFO:iMPACT:501 - '1': Added Device xcf32p successfully.
|
59
|
+
----------------------------------------------------------------------
|
60
|
+
----------------------------------------------------------------------
|
61
|
+
'4': : Manufacturer's ID = Xilinx xcf32p, Version : 15
|
62
|
+
INFO:iMPACT:501 - '1': Added Device xcf32p successfully.
|
63
|
+
----------------------------------------------------------------------
|
64
|
+
----------------------------------------------------------------------
|
65
|
+
done.
|
66
|
+
Elapsed time = 0 sec.
|
67
|
+
Elapsed time = 0 sec.
|
68
|
+
----------------------------------------------------------------------
|
69
|
+
----------------------------------------------------------------------
|
70
|
+
----------------------------------------------------------------------
|
71
|
+
----------------------------------------------------------------------
|
72
|
+
----------------------------------------------------------------------
|
73
|
+
----------------------------------------------------------------------
|
74
|
+
----------------------------------------------------------------------
|
75
|
+
----------------------------------------------------------------------
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'xilinx/provision'
|
5
|
+
require 'ether_ping'
|
6
|
+
|
7
|
+
# Requires supporting files with custom matchers and macros, etc,
|
8
|
+
# in ./support/ and its subdirectories.
|
9
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe Xilinx::Provision::CableDriver do
|
4
|
+
describe 'build_prerequisites' do
|
5
|
+
before do
|
6
|
+
# Remove one a package without deps to validate that it reinstalls.
|
7
|
+
if File.exist? `which apt-get`.strip
|
8
|
+
`apt-get remove -y fxload 2>&1`
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should install the fxload binary' do
|
13
|
+
Xilinx::Provision::CableDriver.build_prerequisites.should be_nil
|
14
|
+
File.exist?(`which fxload`.strip).should be_true
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should forward build output if an error happens' do
|
18
|
+
Kernel.stub(:`) do
|
19
|
+
Kernel.system 'false'
|
20
|
+
'Error 42'
|
21
|
+
end
|
22
|
+
Xilinx::Provision::CableDriver.build_prerequisites.
|
23
|
+
should match(/Error 42/)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'build' do
|
28
|
+
before { Xilinx::Provision::CableDriver.build_prerequisites }
|
29
|
+
|
30
|
+
before { @temp_dir = Dir.mktmpdir }
|
31
|
+
after { FileUtils.rm_rf @temp_dir }
|
32
|
+
|
33
|
+
it 'should copy the USB driver to the given target' do
|
34
|
+
Xilinx::Provision::CableDriver.build(@temp_dir).should be_nil
|
35
|
+
Dir[File.join(@temp_dir, '*.so')].map { |entry| File.basename(entry) }.
|
36
|
+
should include('libusb-driver.so')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should forward build output if an error happens' do
|
40
|
+
Xilinx::Provision::CableDriver.should_receive(:git_url).and_return '::'
|
41
|
+
Xilinx::Provision::CableDriver.build(@temp_dir).
|
42
|
+
should match(/No such file or directory/i)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'path' do
|
47
|
+
let(:path) { Xilinx::Provision::CableDriver.path }
|
48
|
+
|
49
|
+
it 'should point to a valid directory' do
|
50
|
+
File.exist?(File.dirname(path)).should be_true
|
51
|
+
File.directory?(File.dirname(path)).should be_true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe Xilinx::Provision::CableFirmware do
|
4
|
+
describe 'rules_path' do
|
5
|
+
describe 'on the real system' do
|
6
|
+
let(:path) { Xilinx::Provision::CableFirmware.rules_path }
|
7
|
+
|
8
|
+
it 'should point to a valid file' do
|
9
|
+
File.exist?(path).should be_true
|
10
|
+
File.directory?(path).should be_false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'on the mock system' do
|
15
|
+
before { Xilinx::Provision::Impact.stub!(:path).and_return(__FILE__) }
|
16
|
+
|
17
|
+
it 'should find the mock rules file' do
|
18
|
+
Xilinx::Provision::CableFirmware.rules_path.
|
19
|
+
should match(/snippet.rules$/)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'udev rules' do
|
25
|
+
describe 'on the real system' do
|
26
|
+
let(:rules) { Xilinx::Provision::CableFirmware.udev_rules }
|
27
|
+
|
28
|
+
it 'should output a non-empty array' do
|
29
|
+
rules.should have_at_least(1).rule
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should only have strings in the array' do
|
33
|
+
rules.all? { |rule| rule.respond_to? :to_str }.should be_true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'on the mock system' do
|
38
|
+
before { Xilinx::Provision::Impact.stub!(:path).and_return(__FILE__) }
|
39
|
+
|
40
|
+
it 'should match the golden output' do
|
41
|
+
Xilinx::Provision::CableFirmware.udev_rules.should == [
|
42
|
+
'# version 0003',
|
43
|
+
'ATTRS{idVendor}=="03fd", ATTRS{idProduct}=="0008", MODE="666"',
|
44
|
+
%Q|SUBSYSTEMS=="usb", ACTION=="add", ATTRS{idVendor}=="03fd", ATTRS{idProduct}=="0007", RUN+="/sbin/fxload -v -t fx2 -I #{File.expand_path('../../../fixtures', __FILE__)}/xusbdfwu.hex -D $tempnode"|
|
45
|
+
]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'configure_udev' do
|
51
|
+
it 'should run happily' do
|
52
|
+
Xilinx::Provision::CableFirmware.configure_udev.should be_nil
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe Xilinx::Provision::Impact do
|
4
|
+
describe 'path' do
|
5
|
+
let(:path) { Xilinx::Provision::Impact.path }
|
6
|
+
|
7
|
+
it 'is a non-empty string' do
|
8
|
+
path.should be_kind_of String
|
9
|
+
path.should_not be_empty
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'can be executed, and outputs a Xilinx banner' do
|
13
|
+
Kernel.`(path + ' -help').should include('Xilinx')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'run' do
|
18
|
+
it 'should piece the impact command-line correctly' do
|
19
|
+
Xilinx::Provision::Impact.stub(:path).and_return('/path/to/impact')
|
20
|
+
Kernel.should_receive(:`).with 'LD_PRELOAD=/path/to/libusb-driver.so ' +
|
21
|
+
'/path/to/impact -port auto -mode bscan -batch impact_batch 2>&1'
|
22
|
+
lambda {
|
23
|
+
Xilinx::Provision::Impact.run :batch => ['identify'], :mode => :bscan,
|
24
|
+
:cable_port => :auto
|
25
|
+
}.should_not raise_error
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should run an identify correctly' do
|
29
|
+
Xilinx::Provision::Impact.run(:batch => ['identify'], :mode => :bscan,
|
30
|
+
:cable_port => :auto).should match(/identifying chain/i)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'parse_identify' do
|
35
|
+
describe 'on mock input' do
|
36
|
+
let(:output) do
|
37
|
+
Xilinx::Provision::Impact.parse_identify(File.read(
|
38
|
+
File.expand_path('../../../fixtures/impact_detect', __FILE__)))
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should find 5 devices' do
|
42
|
+
output.should have(5).devices
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should show the FPGA as device 0' do
|
46
|
+
output[0][:name].should == 'Xilinx xc5vlx110t'
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should identify the FPGA version' do
|
50
|
+
output[0][:name].should == 'Xilinx xc5vlx110t'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'identify_chain' do
|
56
|
+
it 'should find at least one device' do
|
57
|
+
Xilinx::Provision::Impact.identify_chain.should have_at_least(1).device
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'program_fpga' do
|
62
|
+
describe 'with the ethernet bitfile' do
|
63
|
+
let(:bitfile) do
|
64
|
+
File.expand_path('../../../fixtures/ethernet_ping.bit', __FILE__)
|
65
|
+
end
|
66
|
+
|
67
|
+
let(:return_value) do
|
68
|
+
Xilinx::Provision::Impact.program_fpga bitfile
|
69
|
+
end
|
70
|
+
|
71
|
+
let(:ethernet_device) do
|
72
|
+
'eth0'
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should return nil for success' do
|
76
|
+
return_value.should be_nil
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should make the FPGA respond to pings' do
|
80
|
+
client = EtherPing::Client.new ethernet_device, 0x88B5, '001122334455'
|
81
|
+
client.ping("abcd", 3).should be_kind_of(Numeric)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe Xilinx::Provision::Impact do
|
4
|
+
let(:path) { Xilinx::Provision::Udev.rules_path }
|
5
|
+
|
6
|
+
describe 'rules_path' do
|
7
|
+
it 'should point to a directory' do
|
8
|
+
File.directory?(path).should be_true
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'add_rules' do
|
13
|
+
before { Xilinx::Provision::Udev.add_rules ['ab', 'cd'], '99-spec-group' }
|
14
|
+
after { Xilinx::Provision::Udev.remove_rules '99-spec-group' }
|
15
|
+
|
16
|
+
let(:file_matches) { Dir[File.join(path, '99-spec-group*')] }
|
17
|
+
|
18
|
+
it 'should create a file' do
|
19
|
+
file_matches.should have(1).file
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should write the rules in the file' do
|
23
|
+
File.read(file_matches.first).should == "ab\ncd\n"
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'remove_rules' do
|
27
|
+
before { Xilinx::Provision::Udev.remove_rules '99-spec-group' }
|
28
|
+
|
29
|
+
it 'should remove the previously added file' do
|
30
|
+
Dir[File.join(path, '99-spec-group*')].should be_empty
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'reload_rules' do
|
36
|
+
it 'should execute happily' do
|
37
|
+
Xilinx::Provision::Udev.reload_rules
|
38
|
+
$CHILD_STATUS.to_i.should == 0
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.expand_path('../spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe Xilinx::Provision do
|
4
|
+
describe 'fpga' do
|
5
|
+
it 'delegates to Impact.program_fpga' do
|
6
|
+
Xilinx::Provision::Impact.should_receive(:program_fpga).
|
7
|
+
with('/path/to/bitfile', {}).and_return(nil)
|
8
|
+
Xilinx::Provision.fpga('/path/to/bitfile').should be_true
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'raises an exception if programming fails' do
|
12
|
+
Xilinx::Provision::Impact.should_receive(:program_fpga).
|
13
|
+
with('/path/to/bitfile', {}).and_return("42")
|
14
|
+
lambda {
|
15
|
+
Xilinx::Provision.fpga '/path/to/bitfile'
|
16
|
+
}.should raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'works with a real bitfile' do
|
20
|
+
lambda {
|
21
|
+
bitfile = File.expand_path '../../fixtures/ethernet_ping.bit', __FILE__
|
22
|
+
Xilinx::Provision.fpga bitfile
|
23
|
+
}.should_not raise_error
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: xilinx-provision
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Victor Costan
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-06-01 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
type: :development
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
hash: 29
|
28
|
+
segments:
|
29
|
+
- 3
|
30
|
+
- 6
|
31
|
+
- 1
|
32
|
+
version: 3.6.1
|
33
|
+
prerelease: false
|
34
|
+
version_requirements: *id001
|
35
|
+
name: rdoc
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
type: :development
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 23
|
44
|
+
segments:
|
45
|
+
- 2
|
46
|
+
- 6
|
47
|
+
- 0
|
48
|
+
version: 2.6.0
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: *id002
|
51
|
+
name: rspec
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
type: :development
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ~>
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 11
|
60
|
+
segments:
|
61
|
+
- 1
|
62
|
+
- 0
|
63
|
+
- 14
|
64
|
+
version: 1.0.14
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: *id003
|
67
|
+
name: bundler
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
type: :development
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 13
|
76
|
+
segments:
|
77
|
+
- 1
|
78
|
+
- 6
|
79
|
+
- 1
|
80
|
+
version: 1.6.1
|
81
|
+
prerelease: false
|
82
|
+
version_requirements: *id004
|
83
|
+
name: jeweler
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
type: :development
|
86
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
hash: 3
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
version: "0"
|
95
|
+
prerelease: false
|
96
|
+
version_requirements: *id005
|
97
|
+
name: rcov
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
type: :development
|
100
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ~>
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
hash: 17
|
106
|
+
segments:
|
107
|
+
- 0
|
108
|
+
- 3
|
109
|
+
- 1
|
110
|
+
version: 0.3.1
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *id006
|
113
|
+
name: ether_ping
|
114
|
+
description: Wraps the impact CLI tool in the Xilinx ISE
|
115
|
+
email: victor@costan.us
|
116
|
+
executables:
|
117
|
+
- xilinx-provision
|
118
|
+
- xilinx-provision-setup
|
119
|
+
extensions: []
|
120
|
+
|
121
|
+
extra_rdoc_files:
|
122
|
+
- LICENSE.txt
|
123
|
+
- README.rdoc
|
124
|
+
files:
|
125
|
+
- .document
|
126
|
+
- .project
|
127
|
+
- .rspec
|
128
|
+
- Gemfile
|
129
|
+
- Gemfile.lock
|
130
|
+
- LICENSE.txt
|
131
|
+
- README.rdoc
|
132
|
+
- Rakefile
|
133
|
+
- VERSION
|
134
|
+
- bin/xilinx-provision
|
135
|
+
- bin/xilinx-provision-setup
|
136
|
+
- lib/xilinx/provision.rb
|
137
|
+
- lib/xilinx/provision/cable_driver.rb
|
138
|
+
- lib/xilinx/provision/cable_firmware.rb
|
139
|
+
- lib/xilinx/provision/impact.rb
|
140
|
+
- lib/xilinx/provision/udev.rb
|
141
|
+
- spec/fixtures/ethernet_ping.bit
|
142
|
+
- spec/fixtures/impact_detect
|
143
|
+
- spec/fixtures/snippet.rules
|
144
|
+
- spec/spec_helper.rb
|
145
|
+
- spec/xilinx/provision/cable_driver_spec.rb
|
146
|
+
- spec/xilinx/provision/cable_firmware_spec.rb
|
147
|
+
- spec/xilinx/provision/impact_spec.rb
|
148
|
+
- spec/xilinx/provision/udev_spec.rb
|
149
|
+
- spec/xilinx/provision_spec.rb
|
150
|
+
homepage: http://github.com/csail/xilinx-provision
|
151
|
+
licenses:
|
152
|
+
- MIT
|
153
|
+
post_install_message:
|
154
|
+
rdoc_options: []
|
155
|
+
|
156
|
+
require_paths:
|
157
|
+
- lib
|
158
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
159
|
+
none: false
|
160
|
+
requirements:
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
hash: 3
|
164
|
+
segments:
|
165
|
+
- 0
|
166
|
+
version: "0"
|
167
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
168
|
+
none: false
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
hash: 3
|
173
|
+
segments:
|
174
|
+
- 0
|
175
|
+
version: "0"
|
176
|
+
requirements: []
|
177
|
+
|
178
|
+
rubyforge_project:
|
179
|
+
rubygems_version: 1.8.4
|
180
|
+
signing_key:
|
181
|
+
specification_version: 3
|
182
|
+
summary: Deploys bitfiles to Xilinx FPGAs
|
183
|
+
test_files: []
|
184
|
+
|