#!/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;