mirror of
git://projects.qi-hardware.com/wernermisc.git
synced 2024-11-15 07:15:00 +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
|
||||
specify the location directly by setting the environment variable
|
||||
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