1
0
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:
Werner Almesberger 2011-11-25 21:26:25 -03:00
parent 94fd599ac9
commit e397a87be6
3 changed files with 226 additions and 0 deletions

View File

@ -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
View 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
View 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;