1 |
2 |
wfjm |
#!/usr/bin/perl -w
|
2 |
17 |
wfjm |
# $Id: config_wrapper 467 2013-01-02 19:49:05Z mueller $
|
3 |
2 |
wfjm |
#
|
4 |
17 |
wfjm |
# Copyright 2010-2013 by Walter F.J. Mueller
|
5 |
2 |
wfjm |
#
|
6 |
|
|
# This program is free software; you may redistribute and/or modify it under
|
7 |
|
|
# the terms of the GNU General Public License as published by the Free
|
8 |
|
|
# Software Foundation, either version 2, or at your option any later version.
|
9 |
|
|
#
|
10 |
|
|
# This program is distributed in the hope that it will be useful, but
|
11 |
|
|
# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
|
12 |
|
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
13 |
|
|
# for complete details.
|
14 |
|
|
#
|
15 |
|
|
# Revision History:
|
16 |
|
|
# Date Rev Version Comment
|
17 |
17 |
wfjm |
# 2013-01-02 467 1.1.7 jconfig: prepend '0x' to support 'jtag #2007'
|
18 |
|
|
# 2012-02-11 457 1.1.6 jconfig: use RETRO_FX2_VID/PID for USB VID/PID
|
19 |
15 |
wfjm |
# 2011-12-03 435 1.1.5 add nexys3 support;
|
20 |
12 |
wfjm |
# 2011-08-04 402 1.1.4 add atlys support;
|
21 |
|
|
# 2011-07-25 399 1.1.3 add nexys2-500 support; bsdl path for sp605
|
22 |
|
|
# 2011-07-18 395 1.1.2 cleanup bsdl path creation for jtag
|
23 |
|
|
# 2011-07-17 394 1.1.1 add bit->svf conversion and config with jtag
|
24 |
|
|
# 2011-07-11 393 1.1 renamed from impact_wrapper; add function parameter,
|
25 |
|
|
# old action with 'iconfig'
|
26 |
|
|
# 2011-07-01 386 1.0.3 support sp605/xc6slx45t
|
27 |
2 |
wfjm |
# 2010-05-24 294 1.0.2 support nexys2/xc3s1200e
|
28 |
|
|
# 2010-04-24 282 1.0.1 proper error exit for GetOptions()
|
29 |
|
|
# 2010-04-24 281 1.0 Initial version
|
30 |
|
|
#
|
31 |
|
|
|
32 |
|
|
use 5.005; # require Perl 5.005 or higher
|
33 |
|
|
use strict; # require strict checking
|
34 |
|
|
use FileHandle;
|
35 |
|
|
|
36 |
|
|
use Getopt::Long;
|
37 |
|
|
|
38 |
|
|
my %opts = ();
|
39 |
|
|
|
40 |
12 |
wfjm |
GetOptions(\%opts, "help", "dry_run", "board=s", "path=s") or exit 1;
|
41 |
2 |
wfjm |
|
42 |
12 |
wfjm |
# setup defaults for board and path
|
43 |
|
|
if (not defined $opts{board}) {
|
44 |
|
|
$opts{board} = "s3board";
|
45 |
|
|
}
|
46 |
|
|
if (not defined $opts{path}) {
|
47 |
|
|
$opts{path} = "xc3s1000" if $opts{board} eq "s3board";
|
48 |
|
|
$opts{path} = "xc3s1200e" if $opts{board} eq "nexys2";
|
49 |
15 |
wfjm |
$opts{path} = "xc6slx16" if $opts{board} eq "nexys3";
|
50 |
12 |
wfjm |
$opts{path} = "xc6slx45" if $opts{board} eq "atlys";
|
51 |
|
|
$opts{path} = "xc6slx45t" if $opts{board} eq "sp605";
|
52 |
|
|
}
|
53 |
2 |
wfjm |
|
54 |
|
|
sub print_help;
|
55 |
12 |
wfjm |
sub run_command;
|
56 |
2 |
wfjm |
|
57 |
12 |
wfjm |
|
58 |
2 |
wfjm |
autoflush STDOUT 1 if (-p STDOUT); # autoflush if output into pipe
|
59 |
|
|
|
60 |
|
|
if (exists $opts{help}) {
|
61 |
|
|
print_help;
|
62 |
|
|
exit 0;
|
63 |
|
|
}
|
64 |
|
|
|
65 |
|
|
my $board = $opts{board};
|
66 |
|
|
my $ipath = $opts{path};
|
67 |
|
|
|
68 |
|
|
$ipath =~ s/-.*$//; # trim all after first '-'
|
69 |
|
|
|
70 |
12 |
wfjm |
# now setup JTAG chain config
|
71 |
2 |
wfjm |
|
72 |
12 |
wfjm |
my @plist;
|
73 |
|
|
my $pfpga;
|
74 |
2 |
wfjm |
|
75 |
12 |
wfjm |
#
|
76 |
|
|
# Note: when new targets are added update also the blist logic below
|
77 |
|
|
#
|
78 |
|
|
if ($board eq "s3board" && $ipath eq "xc3s200") { # S3BOARD-200
|
79 |
|
|
@plist = ($ipath, "xcf02s");
|
80 |
|
|
$pfpga = 1;
|
81 |
|
|
} elsif ($board eq "s3board" && $ipath eq "xc3s1000") { # S3BOARD-1200
|
82 |
|
|
@plist = ($ipath, "xcf04s");
|
83 |
|
|
$pfpga = 1;
|
84 |
|
|
|
85 |
|
|
} elsif ($board eq "nexys2" && $ipath eq "xc3s1200e") { # nexys2-1200
|
86 |
|
|
@plist = ($ipath, "xcf04s");
|
87 |
|
|
$pfpga = 1;
|
88 |
|
|
} elsif ($board eq "nexys2" && $ipath eq "xc3s500e") { # nexys2-500
|
89 |
|
|
@plist = ($ipath, "xcf04s");
|
90 |
|
|
$pfpga = 1;
|
91 |
|
|
|
92 |
15 |
wfjm |
} elsif ($board eq "nexys3" && $ipath eq "xc6slx16") { # nexys3
|
93 |
|
|
@plist = ($ipath);
|
94 |
|
|
$pfpga = 1;
|
95 |
|
|
|
96 |
12 |
wfjm |
} elsif ($board eq "atlys" && $ipath eq "xc6slx45") { # atlys
|
97 |
|
|
@plist = ($ipath);
|
98 |
|
|
$pfpga = 1;
|
99 |
|
|
|
100 |
|
|
} elsif ($board eq "sp605" && $ipath eq "xc6slx45t") { # sp605
|
101 |
|
|
@plist = ("xccace", $ipath);
|
102 |
|
|
$pfpga = 2;
|
103 |
2 |
wfjm |
} else {
|
104 |
15 |
wfjm |
print STDERR
|
105 |
|
|
"config_wrapper-E: only s3board/nexys2,3/atlys/sp605 supported\n";
|
106 |
2 |
wfjm |
exit 1;
|
107 |
|
|
}
|
108 |
|
|
|
109 |
12 |
wfjm |
my @blist;
|
110 |
|
|
foreach my $part (@plist) {
|
111 |
|
|
if ($part =~ m/^xcf/) { push @blist, "xcf/data" } # proms
|
112 |
|
|
elsif ($part =~ m/^xc3s\d*$/) { push @blist, "spartan3/data" } # s-3
|
113 |
|
|
elsif ($part =~ m/^xc3s\d*e$/) { push @blist, "spartan3e/data" } # s-3e
|
114 |
|
|
elsif ($part =~ m/^xc6slx\d*t?$/) { push @blist, "spartan6/data" }# s-6 lx
|
115 |
|
|
elsif ($part =~ m/^xccace$/) { push @blist, "acempm/data" } # sys-ace
|
116 |
|
|
else {
|
117 |
|
|
print STDERR "config_wrapper-E: no bsdl path known for $part\n";
|
118 |
|
|
exit 1;
|
119 |
|
|
}
|
120 |
|
|
}
|
121 |
|
|
|
122 |
|
|
my $cmd = shift @ARGV;
|
123 |
2 |
wfjm |
my $file = shift @ARGV;
|
124 |
|
|
|
125 |
12 |
wfjm |
if (! defined $cmd) {
|
126 |
|
|
print STDERR "config_wrapper-E: no command specified\n";
|
127 |
|
|
exit 1;
|
128 |
|
|
}
|
129 |
|
|
|
130 |
2 |
wfjm |
if (! defined $file) {
|
131 |
12 |
wfjm |
print STDERR "config_wrapper-E: no bit or svf file specified\n";
|
132 |
2 |
wfjm |
exit 1;
|
133 |
|
|
}
|
134 |
|
|
if (! -r $file) {
|
135 |
12 |
wfjm |
print STDERR "config_wrapper-E: input file not found or readable\n";
|
136 |
2 |
wfjm |
exit 1;
|
137 |
|
|
}
|
138 |
|
|
|
139 |
12 |
wfjm |
my $xilpath = $ENV{XILINX};
|
140 |
|
|
if (! defined $xilpath) {
|
141 |
|
|
print STDERR "config_wrapper-E: XILINX environment variable not defined\n";
|
142 |
|
|
exit 1;
|
143 |
|
|
}
|
144 |
2 |
wfjm |
|
145 |
12 |
wfjm |
# ----- iconfig action --------------------------------------------------------
|
146 |
|
|
if ($cmd eq "iconfig") {
|
147 |
2 |
wfjm |
|
148 |
12 |
wfjm |
my $tmpfile = "tmp_config_wrapper.cmd";
|
149 |
|
|
open (OFILE, ">$tmpfile") or die "Couldn't open tmp cmd file: $!";
|
150 |
2 |
wfjm |
|
151 |
12 |
wfjm |
print OFILE "setMode -bs\n";
|
152 |
|
|
print OFILE "setCable -p auto\n";
|
153 |
|
|
for (my $i = 0; $i<=$#plist; $i++) {
|
154 |
|
|
printf OFILE "addDevice -p %d -part %s\n", $i+1, $plist[$i];
|
155 |
|
|
}
|
156 |
|
|
printf OFILE "assignFile -p %d -file %s\n", $pfpga, $file;
|
157 |
|
|
printf OFILE "program -p %d -verify\n", $pfpga;
|
158 |
|
|
print OFILE "quit\n";
|
159 |
2 |
wfjm |
|
160 |
12 |
wfjm |
close (OFILE) or die "Couldn't close tmp cmd file: $!";
|
161 |
|
|
|
162 |
|
|
my $rc = run_command("impact -batch", $tmpfile);
|
163 |
|
|
exit $rc;
|
164 |
|
|
|
165 |
|
|
# ----- jconfig action --------------------------------------------------------
|
166 |
|
|
} elsif ($cmd eq "jconfig") {
|
167 |
|
|
|
168 |
|
|
my $bpath = join ";", map "$xilpath/$_",@blist;
|
169 |
|
|
|
170 |
|
|
my $tmpfile = "tmp_config_wrapper.cmd";
|
171 |
|
|
open (OFILE, ">$tmpfile") or die "Couldn't open tmp cmd file: $!";
|
172 |
|
|
|
173 |
|
|
# the UrJtag and Xilinx impact have different chain and part number schemes
|
174 |
|
|
# impact: 1-based, 1 is first in chain;
|
175 |
|
|
# UrJtag: 0-based, 0 is last in chain;
|
176 |
|
|
# e.g. on Digilent Nexys2:
|
177 |
|
|
# impact: (1) FPGA (2) PROM
|
178 |
|
|
# UrJtag: (1) FPGA (0) PROM
|
179 |
|
|
|
180 |
|
|
my $jtag_part = $#plist + 1 - $pfpga;
|
181 |
|
|
|
182 |
17 |
wfjm |
# handle USB VID/PID of board
|
183 |
|
|
# taken from RETRO_FX2_VID and RETRO_FX2_PID environment variables
|
184 |
|
|
# in the retro11 project the default is:
|
185 |
|
|
# VID: 16c0 (VOTI)
|
186 |
|
|
# PID: 03ef (VOTI free for internal lab use 1007)
|
187 |
|
|
#
|
188 |
|
|
# !! Important Note on Usage of this USB VID/PID !!
|
189 |
|
|
# This VID/PID is owned by VOTI, a small dutch company. Usage is granted
|
190 |
|
|
# for 'internal lab use only' by VOTI under the conditions:
|
191 |
|
|
# - the gadgets in which you use those PIDs do not leave your desk
|
192 |
|
|
# - you won't complain to VOTI if you get in trouble with duplicate PIDs
|
193 |
|
|
# (for instance because someone else did not follow the previous rule).
|
194 |
|
|
# See also http://www.voti.nl/pids/pidfaq.html
|
195 |
|
|
#
|
196 |
|
|
|
197 |
|
|
my $fx2_vid = $ENV{RETRO_FX2_VID};
|
198 |
|
|
my $fx2_pid = $ENV{RETRO_FX2_PID};
|
199 |
|
|
$fx2_vid = "16c0" unless defined $fx2_vid;
|
200 |
|
|
$fx2_pid = "03ef" unless defined $fx2_pid;
|
201 |
|
|
|
202 |
|
|
# give vid/pid with 0x prefix. jtag #2007 requires this, #1502 tolerates
|
203 |
|
|
print OFILE "cable usbblaster vid=0x$fx2_vid pid=0x$fx2_pid\n";
|
204 |
12 |
wfjm |
printf OFILE "bsdl path %s\n", $bpath;
|
205 |
|
|
print OFILE "detect\n";
|
206 |
|
|
printf OFILE "part %d\n", $jtag_part;
|
207 |
|
|
printf OFILE "svf %s\n", $file;
|
208 |
|
|
|
209 |
|
|
close (OFILE) or die "Couldn't close tmp cmd file: $!";
|
210 |
|
|
|
211 |
|
|
my $rc = run_command("jtag", $tmpfile);
|
212 |
|
|
exit $rc;
|
213 |
|
|
|
214 |
|
|
# ----- bit2svf action --------------------------------------------------------
|
215 |
|
|
} elsif ($cmd eq "bit2svf") {
|
216 |
|
|
my $ofile = $file;
|
217 |
|
|
$ofile =~ s/\.bit/\.svf/;
|
218 |
|
|
|
219 |
|
|
my $tmpfile = "tmp_config_wrapper.cmd";
|
220 |
|
|
open (OFILE, ">$tmpfile") or die "Couldn't open tmp cmd file: $!";
|
221 |
|
|
|
222 |
|
|
print OFILE "setMode -bs\n";
|
223 |
|
|
printf OFILE "setCable -port svf -file %s\n", $ofile;
|
224 |
|
|
printf OFILE "addDevice -p 1 -file %s\n", $file;
|
225 |
|
|
print OFILE "program -p 1\n";
|
226 |
|
|
print OFILE "quit\n";
|
227 |
|
|
|
228 |
|
|
close (OFILE) or die "Couldn't close tmp cmd file: $!";
|
229 |
|
|
|
230 |
|
|
my $rc = run_command("impact -batch", $tmpfile);
|
231 |
|
|
exit $rc;
|
232 |
|
|
}
|
233 |
|
|
|
234 |
|
|
print STDERR "config_wrapper-E: command must be bit2svf, iconfig or jconfig\n";
|
235 |
|
|
exit 1;
|
236 |
|
|
|
237 |
|
|
#-------------------------------------------------------------------------------
|
238 |
|
|
|
239 |
|
|
sub run_command {
|
240 |
|
|
|
241 |
|
|
my ($cmd, $tmpfile) = @_;
|
242 |
|
|
|
243 |
|
|
my $wrc;
|
244 |
|
|
if (defined $opts{dry_run}) {
|
245 |
|
|
print STDOUT "$cmd\n";
|
246 |
|
|
$wrc = system "/bin/sh", "-c", "cat $tmpfile";
|
247 |
2 |
wfjm |
} else {
|
248 |
12 |
wfjm |
$wrc = system "/bin/sh", "-c", "$cmd $tmpfile";
|
249 |
2 |
wfjm |
}
|
250 |
|
|
|
251 |
12 |
wfjm |
my $rc = 0;
|
252 |
|
|
if ($wrc != 0) {
|
253 |
|
|
my $rc = int($wrc/256);
|
254 |
|
|
if ($rc == 0) {
|
255 |
|
|
my $sig = $wrc % 256;
|
256 |
|
|
print STDERR "config_wrapper-I $cmd aborted by signal $sig\n";
|
257 |
|
|
$rc = 1;
|
258 |
|
|
} else {
|
259 |
|
|
print STDERR "config_wrapper-I $cmd failed (rc=$rc) $?\n";
|
260 |
|
|
}
|
261 |
|
|
}
|
262 |
2 |
wfjm |
|
263 |
12 |
wfjm |
unlink $tmpfile or die "Couldn't delete tmp cmd file: $!";
|
264 |
|
|
return $rc;
|
265 |
|
|
}
|
266 |
2 |
wfjm |
|
267 |
|
|
#-------------------------------------------------------------------------------
|
268 |
|
|
|
269 |
|
|
sub print_help {
|
270 |
12 |
wfjm |
print "usage: config_wrapper [--help] [--board=b] [--path=p] cmd file\n";
|
271 |
|
|
print " cmd bit2svf or iconfig or jconfig\n";
|
272 |
2 |
wfjm |
print " --help this message\n";
|
273 |
12 |
wfjm |
print " --dry_run print impact command list\n";
|
274 |
2 |
wfjm |
print " --board=b type of board\n";
|
275 |
|
|
print " --path=p type of fpga\n";
|
276 |
|
|
}
|