mirror of
git://projects.qi-hardware.com/wernermisc.git
synced 2024-11-15 09:16:14 +02:00
m1/tools/: xdltap and xdlfixes, to add taps to FPGA signals
This commit is contained in:
parent
94fd599ac9
commit
e397a87be6
@ -20,3 +20,34 @@ You need to have fjmem.bit somwehere. It searches for it under
|
|||||||
$HOME/.qi/milkymist/, where reflash_m1.sh caches it. You can also
|
$HOME/.qi/milkymist/, where reflash_m1.sh caches it. You can also
|
||||||
specify the location directly by setting the environment variable
|
specify the location directly by setting the environment variable
|
||||||
FJMEM_BIT.
|
FJMEM_BIT.
|
||||||
|
|
||||||
|
|
||||||
|
xdltap - Route nets from inside the FPGA to I/O pads
|
||||||
|
====================================================
|
||||||
|
|
||||||
|
xdltap adds routes from signals inside the FPGA to I/O pads. It
|
||||||
|
does this by converting the .ncd file generated by synthesis
|
||||||
|
|
||||||
|
xdltap signal=output ... [xdl-file]
|
||||||
|
|
||||||
|
The path to the signal to be tapped has to be fully qualified.
|
||||||
|
Note that not all signals are listed in the .pcf file. Some may
|
||||||
|
only show up in .xdl
|
||||||
|
|
||||||
|
The output is the name of a global net that has to be connected
|
||||||
|
to an input (!) pad.
|
||||||
|
|
||||||
|
Signal names containing < and > can be written with { and }, to
|
||||||
|
avoid extra escaping for the shell.
|
||||||
|
|
||||||
|
Since xdl chokes on its own .xdl files, xdlfixes applies a number
|
||||||
|
of ugly hacks to either avoid errors or to propagate them to a
|
||||||
|
later stage, where they can be ignored.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
map ... foo.ngd # generates foo.ncd
|
||||||
|
xdl -ncd2xdl foo.ncd # generates foo.xdl
|
||||||
|
xdltap usb/sie/rx_pending=exp{8} foo.xdl | xdlfixes >foo-dbg.xdl
|
||||||
|
xdl -xdl2ncd foo-dbg.xdl # generates foo-dbg.ncd
|
||||||
|
par ... foo-dbg.ncd ...
|
||||||
|
78
m1/tools/xdlfixes
Executable file
78
m1/tools/xdlfixes
Executable file
@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
#
|
||||||
|
# xdlfixes - Pro-process a Xilinx .xdl file such that xdl -xdl2ncd accepts it
|
||||||
|
#
|
||||||
|
# Written 2011 by Werner Almesberger
|
||||||
|
# Copyright 2011 by Werner Almesberger
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
sub usage
|
||||||
|
{
|
||||||
|
print STDERR "usage: $0 [infile]\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
&usage if $ARGV[0] =~ /^-/;
|
||||||
|
|
||||||
|
while (<>) {
|
||||||
|
#
|
||||||
|
# BUG: identifiers containing commas are generated by xdl -ncd2xdl
|
||||||
|
# but cannot be parsed by xdl -xdl2ncd. We therefore replace all the
|
||||||
|
# commas in identifiers with underscores.
|
||||||
|
#
|
||||||
|
|
||||||
|
$t = $_;
|
||||||
|
$s = "";
|
||||||
|
while ($t =~ /[^\\]"\S+"/) {
|
||||||
|
$s .= $`;
|
||||||
|
($q = $&) =~ y/,/_/;
|
||||||
|
$t = $';
|
||||||
|
$s .= $q;
|
||||||
|
}
|
||||||
|
$s .= $t;
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG: xdl -xdl2ncd does not seem to understand that inputs are not
|
||||||
|
# outputs. We have two choices here: define the output standard as
|
||||||
|
# "#OFF" or define it as "LVCMOS33".
|
||||||
|
#
|
||||||
|
# With "LVCMOS33", xdl will also insist on the slew rate and the drive
|
||||||
|
# strength.
|
||||||
|
#
|
||||||
|
# In any case, we end up with something the DRC of bitgen will reject.
|
||||||
|
# Luckily, bitgen has the option -d to turn off the DRC. It then
|
||||||
|
# cheerfully announces
|
||||||
|
#
|
||||||
|
# ERROR:Bitgen - Could not find programming information for I/O
|
||||||
|
# standard #OFF [...]
|
||||||
|
# The programming of the output buffers will not be correct.
|
||||||
|
#
|
||||||
|
# but the resulting mess appears to work regardless.
|
||||||
|
#
|
||||||
|
|
||||||
|
if ($_ =~ /^inst /) {
|
||||||
|
$s = $_;
|
||||||
|
while (!/;\s*$/) {
|
||||||
|
$_ = <>;
|
||||||
|
$s .= $_;
|
||||||
|
}
|
||||||
|
# $s =~ s/\bISTANDARD::LVCMOS33\b/$& OSTANDARD::LVCMOS33/;
|
||||||
|
# $s =~ s/\bISTANDARD::LVCMOS33\b/$& OSTANDARD::#OFF/;
|
||||||
|
$s =~ s/\bISTANDARD::LVCMOS33\b/$& OSTANDARD::#OFF/ unless
|
||||||
|
$s =~ /\bOSTANDARD:/;
|
||||||
|
# $s =~ s/\bINBUF:/OUTBUF::#OFF $&/;
|
||||||
|
# if ($s =~ /\bISTANDARD::LVCMOS33\b/) {
|
||||||
|
# $s =~ s/\bSLEW::#OFF\b/SLEW::SLOW/g;
|
||||||
|
# $s =~ s/\bDRIVEATTRBOX::#OFF\b/DRIVEATTRBOX::12/g;
|
||||||
|
# }
|
||||||
|
}
|
||||||
|
|
||||||
|
print $s || die "write: $!";
|
||||||
|
}
|
117
m1/tools/xdltap
Executable file
117
m1/tools/xdltap
Executable file
@ -0,0 +1,117 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
#
|
||||||
|
# xdltap - Route nets from inside the FPGA to I/O pads
|
||||||
|
#
|
||||||
|
# Written 2011 by Werner Almesberger
|
||||||
|
# Copyright 2011 by Werner Almesberger
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
sub change
|
||||||
|
{
|
||||||
|
local ($s, $v, $from, $to) = @_;
|
||||||
|
|
||||||
|
if (defined $from) {
|
||||||
|
die "${v}::$from not found in\n$s"
|
||||||
|
unless $s =~ /\b${v}::$from/;
|
||||||
|
return "$`${v}::$to$'";
|
||||||
|
} else {
|
||||||
|
die "${v}::... not found in\n$s"
|
||||||
|
unless $s =~ /\b${v}::\S+/;
|
||||||
|
return "$`${v}::$to$'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub change_var
|
||||||
|
{
|
||||||
|
local ($s, $from, $to) = @_;
|
||||||
|
|
||||||
|
die "${from}::... not found in\n$s"
|
||||||
|
unless $s =~ /\b${from}::/;
|
||||||
|
return "$`${to}::$'";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub reassign
|
||||||
|
{
|
||||||
|
local ($s, $from, $to) = @_;
|
||||||
|
|
||||||
|
$s =~ s/\bINBUF:${to}_IBUF:/OUTBUF:${to}_OBUF:/ ||
|
||||||
|
die "INBUF:${to}_IBUF: not found in\n$s";
|
||||||
|
$s =~ s/\bPULL:${to}_PULLDOWN:// ||
|
||||||
|
die "PULL:${to}_PULLDOWN: not found in\n$s";
|
||||||
|
$s =~ s/\bIMUX:[^:]+:I/IMUX::#OFF/ ||
|
||||||
|
die "IMUX:...:I not found in\n$s";
|
||||||
|
$s = &change($s, "BYPASS_MUX", "I", "#OFF");
|
||||||
|
$s = &change($s, "DRIVEATTRBOX", "#OFF", "12");
|
||||||
|
$s = &change($s, "OUSED", "#OFF", "0");
|
||||||
|
$s = &change($s, "PULLTYPE", "PULLDOWN", "#OFF");
|
||||||
|
$s = &change($s, "SLEW", "#OFF", "SLOW");
|
||||||
|
$s = &change($s, "SUSPEND", "#OFF", "3STATE");
|
||||||
|
$s = &change_var($s, "ISTANDARD", "OSTANDARD");
|
||||||
|
return $s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub usage
|
||||||
|
{
|
||||||
|
print STDERR <<"END"
|
||||||
|
usage: $0 [net=output ...] [file]
|
||||||
|
|
||||||
|
net fully qualified path to the signal in question, e.g.,
|
||||||
|
usb/sie/rx_pending
|
||||||
|
output name of the (input) connected to the output pin, e.g., exp<8>
|
||||||
|
|
||||||
|
For better shell compatibility, { and } can be used instead of < and >
|
||||||
|
END
|
||||||
|
;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
&usage if $ARGV[0] =~ /^-/;
|
||||||
|
|
||||||
|
while ($ARGV[0] =~ /=/) {
|
||||||
|
($from, $to) = ($`, $');
|
||||||
|
$to =~ tr/{}/<>/;
|
||||||
|
$from{$from} = $to;
|
||||||
|
$to{$to} = $from;
|
||||||
|
$need{$from} = $need{$to} = 1;
|
||||||
|
shift @ARGV;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (<>) {
|
||||||
|
if ($_ =~ /^inst "([^"]*)"/ && defined $to{$1}) {
|
||||||
|
die "" unless $need{$1};
|
||||||
|
delete $need{$1};
|
||||||
|
$s = $_;
|
||||||
|
while (!/;\s*$/) {
|
||||||
|
$_ = <>;
|
||||||
|
$s .= $_;
|
||||||
|
}
|
||||||
|
print &reassign($s, $to{$1}, $1) || die "write: $!";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
if (/^net "([^"]*)_IBUF"/ && defined $to{$1}) {
|
||||||
|
next if /;\s*$/;
|
||||||
|
while (<>) {
|
||||||
|
last if /;\s*$/;
|
||||||
|
}
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
print || die "write: $!";
|
||||||
|
if (/^net "([^"]*)"/) {
|
||||||
|
next unless defined $from{$1};
|
||||||
|
die unless $need{$1};
|
||||||
|
delete $need{$1};
|
||||||
|
print " inpin \"$from{$1}\" O,\n" || die "write: $!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
die "not found: ".join(", ", sort keys %need) if %need;
|
Loading…
Reference in New Issue
Block a user