URL
https://opencores.org/ocsvn/w11/w11/trunk
Subversion Repositories w11
Compare Revisions
- This comparison shows the changes necessary to convert path
/w11/tags/w11a_V0.7/tools/bin
- from Rev 32 to Rev 33
- ↔ Reverse comparison
Rev 32 → Rev 33
/create_disk
0,0 → 1,283
#!/usr/bin/perl -w |
# $Id: create_disk 692 2015-06-21 11:53:24Z mueller $ |
# |
# Copyright 2013-2014 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de> |
# |
# This program is free software; you may redistribute and/or modify it under |
# the terms of the GNU General Public License as published by the Free |
# Software Foundation, either version 2, or at your option any later version. |
# |
# This program is distributed in the hope that it will be useful, but |
# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY |
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
# for complete details. |
# |
# Revision History: |
# Date Rev Version Comment |
# 2015-06-21 692 1.1.2 use sysseek rather seek; add RM80 |
# 2015-04-06 665 1.1.1 add alias RM03 (for RM02) and RP05 (for RP04) |
# 2014-06-14 562 1.1 BUGFIX: repair --boot; add RM02,RM05,RP04,RP07 |
# 2013-05-20 521 1.0 First draft |
# |
|
use 5.10.0; # require Perl 5.10 or higher |
use strict; # require strict checking |
|
use Getopt::Long; |
use FileHandle; |
use Fcntl qw(:seek); |
|
my %opts = (); |
|
GetOptions(\%opts, "help", "typ=s", "ini=s", "bad", "boot" |
) |
or exit 1; |
|
sub do_inipatt; |
sub do_badtable; |
sub do_boot; |
sub print_help; |
|
# disk type table |
my %disktype = ( |
RK05 => {cyl=> 203, hd=> 2, sec=> 12, bps=> 512, bad=>0}, |
RL01 => {cyl=> 256, hd=> 2, sec=> 40, bps=> 256, bad=>1}, |
RL02 => {cyl=> 512, hd=> 2, sec=> 40, bps=> 256, bad=>1}, |
RM03 => {cyl=> 823, hd=> 5, sec=> 32, bps=> 512, bad=>1}, |
RM05 => {cyl=> 823, hd=> 19, sec=> 32, bps=> 512, bad=>1}, |
RM80 => {cyl=> 559, hd=> 14, sec=> 31, bps=> 512, bad=>1}, |
RP05 => {cyl=> 411, hd=> 19, sec=> 22, bps=> 512, bad=>1}, |
RP06 => {cyl=> 815, hd=> 19, sec=> 22, bps=> 512, bad=>1}, |
RP07 => {cyl=> 630, hd=> 32, sec=> 50, bps=> 512, bad=>1} |
); |
|
autoflush STDOUT 1 if (-p STDOUT); # autoflush if output into pipe |
|
if (exists $opts{help}) { |
print_help(1); |
exit 0; |
} |
|
if (scalar(@ARGV) != 1) { |
print STDERR "create_disk-E: specify one and only one output file\n"; |
print_help(0); |
exit 1; |
} |
|
my $fnam = shift @ARGV; |
|
if (-e $fnam) { |
print STDERR "create_disk-E: file '$fnam' exists already\n"; |
exit 1; |
} |
|
my $typ = uc($opts{typ}); |
|
$typ = "RM03" if defined $typ && $typ eq "RM02"; # RM02 is equivalent to RM03 |
$typ = "RP05" if defined $typ && $typ eq "RP04"; # RM04 is equivalent to RP05 |
|
unless (defined $typ && exists $disktype{$typ}) { |
print STDERR "create_disk-E: no or invalid --typ specification, use --help\n"; |
exit 1; |
} |
|
my $cyl = $disktype{$typ}{cyl}; |
my $hd = $disktype{$typ}{hd}; |
my $sec = $disktype{$typ}{sec}; |
my $bps = $disktype{$typ}{bps}; |
my $bad = $disktype{$typ}{bad}; |
|
if ($opts{bad} && !$bad) { |
print STDERR "create_disk-E: --bad not supported for type '$typ', abort\n"; |
exit 1; |
} |
|
my $nblk = $cyl*$hd*$sec; |
my $cap = $nblk * $bps; |
|
my $fh = new FileHandle; |
sysopen($fh, $fnam, O_RDWR|O_CREAT) |
or die "failed to create '$fnam': $!"; |
|
# seek to end, write 1 byte at end |
my $rc = sysseek($fh, $cap-1, SEEK_SET); |
if (not $rc) {die "seek failed: $!";} |
my $buf = pack('C1',0); |
$rc = syswrite($fh, $buf, length($buf)); |
if ($rc<=0) {die "write failed: $!";} |
|
# handle init patterns |
do_inipatt if $opts{ini}; |
|
# handle factory bad block table |
do_badtable if $opts{bad}; |
|
# write dummy boot block |
do_boot if $opts{boot}; |
|
#------------------------------------------------------------------------------- |
|
sub do_inipatt { |
my $ini = $opts{ini}; |
|
if ($ini eq 'zero' || $ini eq 'ones' || $ini eq 'dead') { |
my @dat; |
for (my $i=0; $i<$bps/4; $i++) { |
push @dat, 0,0 if $ini eq 'zero'; |
push @dat, -1,-1 if $ini eq 'ones'; |
push @dat, 0xdead,0xbeaf if $ini eq 'dead'; |
} |
my $buf = pack('v*',@dat); |
my $rc = sysseek($fh, 0, SEEK_SET); |
if (not $rc) {die "seek failed: $!";} |
for (my $i=0; $i<$nblk; $i++) { |
$rc = syswrite($fh, $buf, length($buf)); |
if ($rc<=0) {die "write failed: $!";} |
} |
|
} elsif ($ini eq 'test') { |
my $addr = 0; |
my $cur_sec = 0; |
my $cur_trk = 0; |
my $cur_cyl = 0; |
my $rc = sysseek($fh, 0, SEEK_SET); |
if (not $rc) {die "seek failed: $!";} |
for (my $i=0; $i<$nblk; $i++) { |
my @dat; |
for (my $i=0; $i<$bps/16; $i++) { |
push @dat, ($addr & 0xffff); |
push @dat, (($addr>>16) & 0xffff); |
push @dat, $cur_cyl, $cur_trk, $cur_sec; |
push @dat, $cyl, $hd, $sec; |
$addr += 16; |
} |
my $buf = pack('v*',@dat); |
$rc = syswrite($fh, $buf, length($buf)); |
if ($rc<=0) {die "write failed: $!";} |
$cur_sec += 1; |
if ($cur_sec >= $sec) { |
$cur_sec = 0; |
$cur_trk += 1; |
if ($cur_trk >= $hd) { |
$cur_trk = 0; |
$cur_cyl += 1; |
} |
} |
} |
|
} else { |
print STDERR "create_disk-W: unknown --ini mode '$ini', --ini ignored\n"; |
} |
return; |
} |
|
#------------------------------------------------------------------------------- |
|
sub do_badtable { |
my @dat; |
push @dat, 012345, 012345; # pack number |
push @dat, 0,0; # dummy c/s/h spec |
for (my $i=4; $i<$bps/2; $i++) { |
push @dat, -1; # end of table |
} |
my $buf = pack('v*',@dat); |
|
my $pos = $cap - $sec*$bps; # position of last track |
my $rc = sysseek($fh, $pos, SEEK_SET); |
if (not $rc) {die "seek failed: $!";} |
my $nsec = ($sec > 10) ? 10 : $sec; # write last track, at most 10 sec |
for (my $i=0; $i<$nsec; $i++) { |
$rc = syswrite($fh, $buf, length($buf)); |
if ($rc<=0) {die "write failed: $!";} |
} |
return; |
} |
|
#------------------------------------------------------------------------------- |
|
sub do_boot { |
my @dat; |
|
push @dat, 0012700, 0000100; # start: mov #text, r0 |
push @dat, 0105710; # 1$: tstb (r0) |
push @dat, 0001406; # beq 3$ |
push @dat, 0105737, 0177564; # 2$: tstb @#XCSR |
push @dat, 0100375; # bpl 2$ |
push @dat, 0112037, 0177566; # movb (r0)+,@#XBUF |
push @dat, 0000770; # br 1$ |
push @dat, 0000000; # 3$: halt |
|
my $buf = pack('v*',@dat); |
my $rc = sysseek($fh, 0, SEEK_SET); |
if (not $rc) {die "seek failed: $!";} |
$rc = syswrite($fh, $buf, length($buf)); |
if ($rc<=0) {die "write failed: $!";} |
|
$buf = "\r\n"; |
$buf .= "\r\n"; |
$buf .= "++======================================++\r\n"; |
$buf .= "|| This is not a hardware bootable disk ||\r\n"; |
$buf .= "++======================================++\r\n"; |
$buf .= "\r\n"; |
$buf .= "Disk image created with 'create_disk --typ=$typ':\r\n"; |
$buf .= sprintf " number of cylinders: %7d\r\n", $cyl; |
$buf .= sprintf " tracks per cylinder: %7d\r\n", $hd; |
$buf .= sprintf " sectors per track: %7d\r\n", $sec; |
$buf .= sprintf " block size: %7d\r\n", $bps; |
$buf .= sprintf " total number of sectors:%7d\r\n", $nblk; |
$buf .= sprintf " capacity in kByte: %7d\r\n", $cap/1024; |
$buf .= "\r\n"; |
$buf .= "CPU WILL HALT\r\n"; |
$buf .= "\r\n"; |
|
# NOTE: the text above almost fills the first 512 bytes !! |
# don't add more text, all has been said anyway !! |
|
$rc = sysseek($fh ,0100, SEEK_SET); |
if (not $rc) {die "seek failed: $!";} |
$rc = syswrite($fh, $buf, length($buf)); |
if ($rc<=0) {die "write failed: $!";} |
|
return; |
} |
|
#------------------------------------------------------------------------------- |
|
sub print_help { |
my ($ptyp) = @_; |
print "usage: create_disk [options] <file>\n"; |
print " --typ=<type> specified disk type, must be specified\n"; |
print " --ini=<pat> initialization pattern, can be\n"; |
print " --bad create factory bad block table on last track\n"; |
print " --boot write dummy boot block, print volume info and HALT\n"; |
print " --help print full help, with list --typ and --ini options\n"; |
return unless $ptyp; |
|
print "\n"; |
print "currently supported disk types:\n"; |
print " type #cyl #trk #sec bps tot_sec blocks -bad\n"; |
foreach my $typ (sort keys %disktype) { |
my $cyl = $disktype{$typ}{cyl}; |
my $hd = $disktype{$typ}{hd}; |
my $sec = $disktype{$typ}{sec}; |
my $bps = $disktype{$typ}{bps}; |
printf " %4s %4d %4d %4d %4d %7d %7d %3s\n", |
$typ, $cyl, $hd, $sec, $bps, |
($cyl*$hd*$sec), ($cyl*$hd*$sec*$bps)/1024, |
($disktype{$typ}{bad} ? 'yes' : ' no'); |
} |
|
print "\n"; |
print " RM02 is accepted as an alias for RM03 (same capacity)\n"; |
print " RP04 is accepted as an alias for RP05 (same capacity)\n"; |
|
print "\n"; |
print "currently supported initialization patterns:\n"; |
print " zero all zero (will cause explicit disk space allocation)\n"; |
print " ones all ones\n"; |
print " dead alternating 0xdead 0xbeaf pattern\n"; |
print " test writes unique groups of 8 16bit words\n"; |
print "\n"; |
print "For further details consults the create_disk man page.\n"; |
return; |
} |
create_disk
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: tap2file
===================================================================
--- tap2file (nonexistent)
+++ tap2file (revision 33)
@@ -0,0 +1,129 @@
+#!/usr/bin/perl -w
+# $Id: tap2file 686 2015-06-04 21:08:08Z mueller $
+#
+# Copyright 2015- by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Version Comment
+# 2015-06-03 686 1.0.1 add print_usage; cleanups
+# 2015-05-24 684 1.0 Initial version
+#
+# Expand a simh tape container file (.tap) to a set of files
+#
+# Usage: tap2file [--pref=pref] file
+#
+use 5.14.0; # require Perl 5.14 or higher
+use strict; # require strict checking
+
+use Getopt::Long;
+
+my %opts = ();
+
+GetOptions(\%opts, "pref=s", "help")
+ or die "bad options";
+
+sub close_ofile;
+sub print_usage;
+
+if (scalar(@ARGV) == 0 || exists $opts{help}) {
+ print_usage;
+ exit 0;
+}
+
+my $ifile = shift @ARGV;
+exit 0 unless defined $ifile;
+
+open(IFILE, "<$ifile") || die("Can't open $ifile: $!");
+
+my $basename = $ifile;
+$basename = $1 if $ifile =~ m|.*/(.*)|;
+my $fstem = $basename;
+$fstem = $1 if $basename =~ m|(.*)\..*|;
+
+my $pref = (exists $opts{pref}) ? $opts{pref} : "${fstem}_";
+
+my $nfile = 0;
+my $nrec = 0;
+my $rlmin = 0;
+my $rlmax = 0;
+my $ofile = "";
+
+my $block;
+my $nb;
+
+while ($nb = read(IFILE, $block, 4)) {
+ my $metabeg = unpack("V", $block);
+
+ if ($metabeg == 0x00000000) {
+ close_ofile;
+ $nfile += 1;
+ next;
+ }
+ if ($metabeg == 0xffffffff) {
+ last;
+ }
+
+ unless (defined fileno OFILE) {
+ $ofile = sprintf("%s%02d.dat", $pref,$nfile);
+ open(OFILE, ">$ofile") || die("Can't open $ofile: $!");
+ }
+
+ $nb = read(IFILE, $block, $metabeg);
+ print OFILE $block;
+ if ($nrec == 0) {
+ $rlmin = $metabeg;
+ $rlmax = $metabeg;
+ } else {
+ $rlmin = $metabeg if $metabeg < $rlmin;
+ $rlmax = $metabeg if $metabeg > $rlmin;
+ }
+ $nrec += 1;
+
+ $nb = read(IFILE, $block, 4);
+ my $metaend = unpack("V", $block);
+ if ($nb != 4 || not defined $metaend) {
+ printf "bad meta tag: beg=%8.8x\n", $metabeg;
+ last;
+ }
+ if ($metaend != $metabeg) {
+ printf "bad meta tags: beg=%8.8x end=%8.8x\n", $metabeg,$metaend;
+ last;
+ }
+}
+
+close_ofile;
+exit 0;
+
+# ----------------------------------------------------------------------------
+sub close_ofile {
+ return unless (defined fileno OFILE);
+ close(OFILE);
+ if ($rlmin == $rlmax) {
+ printf "%s: %6d records, length %5d\n",
+ $ofile, $nrec, $rlmin;
+ } else {
+ printf "%s: %6d records, length min=%5d, max=%5d\n",
+ $ofile, $nrec, $rlmin, $rlmax;
+ }
+ $nrec = 0;
+ $rlmin = 0;
+ $rlmax = 0;
+}
+
+# ----------------------------------------------------------------------------
+sub print_usage {
+ print "usage: tap2file [options] ifile\n";
+ print " ifile input tap file\n";
+ print " Options\n";
+ print " --pref=p use p as prefix for generated files\n";
+ print " --help this message\n";
+}
tap2file
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: file2tap
===================================================================
--- file2tap (nonexistent)
+++ file2tap (revision 33)
@@ -0,0 +1,119 @@
+#!/usr/bin/perl -w
+# $Id: file2tap 686 2015-06-04 21:08:08Z mueller $
+#
+# Copyright 2008-2015 by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Version Comment
+# 2015-06-03 686 1.1 fix -a option; support eom at end
+# 2008-12-07 175 1.0.1 remove some upperfluous 'my'
+# 2008-11-29 174 1.0 Initial version (import from tbird backup)
+#
+#
+# Create a simh tape container file (.tap) from a set of files
+#
+# Usage: file2tap -c name -b n file1 ... filen
+#
+# if -c name is omitted, stdout is used
+#
+
+use strict;
+use Fcntl qw(:seek O_RDWR);
+
+my $arg;
+my $cdone;
+my $blocksize = 512;
+my $nfile = 0;
+
+while ($arg = shift) {
+
+ if ($arg eq "-c") {
+ if (@ARGV) {
+ $arg = shift;
+ open(OFILE, ">$arg") || die ("Can't open output file $arg: $!");
+ $cdone = 1;
+ }
+
+ } elsif ($arg eq "-a") {
+ if (@ARGV) {
+ $arg = shift;
+ sysopen OFILE, $arg, O_RDWR || die ("Can't open output file $arg: $!");
+ my $buf;
+ my $len;
+
+ # check for EOM mark at end, if found, truncate it away
+ sysseek OFILE, -4, SEEK_END;
+ $len = sysread OFILE, $buf, 4;
+ if ($buf eq "\xff\xff\xff\xff") {
+ truncate OFILE, sysseek(OFILE, -4, SEEK_END);
+ }
+
+ # check for two EOF marks at end, if found, truncate 2nd away
+ sysseek OFILE, -8, SEEK_END;
+ $len = sysread OFILE, $buf, 8;
+ if ($buf ne "\x00\x00\x00\x00\x00\x00\x00\x00") {
+ die ("Didn't find double EOF at end of tap file");
+ }
+ truncate OFILE, sysseek(OFILE, -4, SEEK_END);
+
+ close OFILE;
+ open(OFILE, ">>$arg") || die ("Can't append to output file $arg: $!");
+ $cdone = 1;
+ }
+
+ } elsif ($arg eq "-b") {
+ if (@ARGV) {
+ $arg = shift;
+ $blocksize = 512 * int $arg;
+ }
+
+ } else {
+ if (!$cdone) {
+ open(OFILE, ">-") || die ("Can't open stdout: $!");
+ }
+
+ my @flist = split(",",$arg);
+ my $file;
+ foreach $file (@flist) {
+ add_file($file, $blocksize);
+ }
+ $nfile += 1;
+ end_file();
+ }
+}
+end_file();
+
+# ----------------------------------------------------------------------------
+sub end_file {
+ print OFILE "\x00\x00\x00\x00";
+}
+
+# ----------------------------------------------------------------------------
+sub add_file {
+ my($filename, $blocksize) = @_;
+ my($block, $bytes_read, $length, $nb);
+
+ open(FILE, $filename) || die("Can't open $filename: $!");
+ while($bytes_read = read(FILE, $block, $blocksize)) {
+ if($bytes_read < $blocksize) {
+ $block .= "\x00" x ($blocksize - $bytes_read);
+ }
+ $length = pack("V", $blocksize);
+ print OFILE $length, $block, $length;
+ $nb += 1;
+ }
+ close(FILE);
+ if ($cdone) {
+ printf "file: %3d records: %5d length: %5d file: $filename\n",
+ $nfile, $nb, $blocksize;
+ }
+}
file2tap
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: tbrun_tbwrri
===================================================================
--- tbrun_tbwrri (nonexistent)
+++ tbrun_tbwrri (revision 33)
@@ -0,0 +1,177 @@
+#!/bin/bash
+# $Id: tbrun_tbwrri 666 2015-04-12 21:17:54Z mueller $
+#
+# Copyright 2014-2015 by Walter F.J. Mueller
+# License disclaimer see LICENSE_gpl_v2.txt in $RETROBASE directory
+#
+# Revision History:
+# Date Rev Version Comment
+# 2015-04-11 666 1.1 add --fusp,--xon
+# 2014-12-27 622 1.0 Initial version
+#
+
+chkval ()
+{
+ if [[ $1 =~ --.* || $1 =~ -[a-z]* ]]; then
+ echo "tbrun_tbwrri-E: value forgotten prior to '$1'"
+ exit 1
+ fi
+}
+
+docmd ()
+{
+ echo "$1"
+ if [[ -z "$optdry" ]] ; then
+ eval "$1"
+ fi
+}
+
+optdry=""
+optlsuf=""
+optstack=""
+optghw=""
+opttbw=""
+optpack=""
+optrri=""
+optpcom=""
+optcuff=""
+optfusp=""
+optxon=""
+
+# handle options
+while (( $# > 0 )) ; do
+ case $1 in
+ -dry|--dry) optdry=$1 ; shift 1 ;;
+ -lsuf|--lsuf) optlsuf=$2 ; chkval $2 ; shift 2 ;;
+ -stack|--stack) optstack=$2 ; chkval $2 ; shift 2 ;;
+ -ghw|--ghw) optghw=$2 ; chkval $2 ; shift 2 ;;
+ -tbw|--tbw) opttbw=$2 ; chkval $2 ; shift 2 ;;
+ -pack|--pack) optpack=$2 ; chkval $2 ; shift 2 ;;
+ -rri|--rri) optrri=$2 ; chkval $2 ; shift 2 ;;
+ -cuff|--cuff) optcuff=$1 ; shift 1 ;;
+ -fusp|--fusp) optfusp=$1 ; shift 1 ;;
+ -xon|--xon) optxon=$1 ; shift 1 ;;
+ -pcom|--pcom) optpcom=$1 ; shift 1 ;;
+ -\?|-h*|--h*) opthelp=$1 ; shift 1 ;;
+ -*) echo "tbrun_tbwrri-E: invalid option '$1'"; exit 1 ;;
+ *) break;;
+ esac
+done
+
+# complain if no tbench defined
+if [[ -n "$opthelp" || $# -eq 0 ]] ; then
+ echo "Usage: tbrun_tbwrri [opts] testbench rricmds..."
+ echo " Options:"
+ echo " --dry dry run, print commands, don't execute"
+ echo " --lsuf suff use '_.log' as suffix for log file"
+ echo " --stack nnn use as ghdl stack size"
+ echo " --ghw fname write ghw file with name '.ghw'"
+ echo " --tbw opts append to tbw command"
+ echo " --pack plist add '--pack=<=plist>' option to ti_rri"
+ echo " --rri opts append to ti_rri command"
+ echo " --cuff use cuff and not serport"
+ echo " --fusp use 2nd serport"
+ echo " --xon use xon with 1st serport"
+ echo " --pcom print test comments"
+ exit 1
+fi
+
+# check that only one of --cuff --fusp or --xon given
+ncfxcount=0
+if [[ -n "$optcuff" ]] ; then ncfxcount=$(($ncfxcount+1)); fi
+if [[ -n "$optfusp" ]] ; then ncfxcount=$(($ncfxcount+1)); fi
+if [[ -n "$optxon" ]] ; then ncfxcount=$(($ncfxcount+1)); fi
+
+if (( $ncfxcount > 1 )) ; then
+ echo "tbrun_tbwrri-E: only one of --cuff,-fusp,--xon allowed"
+ exit 1
+fi
+
+tbench=$1
+shift 1
+
+tbenchname=$(basename $tbench)
+tbenchpath=$(dirname $tbench)
+
+# check for ghdl with _ssim, _fsim, _tsim
+isghdlxsim=""
+if [[ $tbench =~ _[sft]sim$ ]] ; then
+ isghdlxsim=true
+ logsuff=""
+fi
+
+# issue makes
+if [[ -n "$isghdlxsim" ]] ; then docmd "make -C $tbenchpath ghdl_tmp_clean"; fi
+docmd "make -C $tbenchpath $tbenchname"
+exitstat=$?
+if [[ -n "$isghdlxsim" ]] ; then docmd "make -C $tbenchpath ghdl_tmp_clean"; fi
+
+if (( $exitstat > 0 )) ; then exit $exitstat; fi
+
+# determine logfile name
+logsuff="_dsim"
+if [[ $tbenchname =~ _[sft]sim$ ]] ; then logsuff=""; fi
+if [[ -n "$optlsuf" ]] ; then logsuff="_$optlsuf"; fi
+
+logfile="${tbenchname}${logsuff}.log"
+
+# now build actual test command
+cmd="time ti_rri --run=\"tbw $tbench -fifo"
+if [[ -n "$opttbw" ]] ; then cmd+=" $opttbw"; fi
+if [[ -n "$optstack" ]] ; then cmd+=" --stack-max-size=$optstack"; fi
+if [[ -n "$optghw" ]] ; then
+ if [[ "$optghw" != *.ghw ]]; then optghw="$optghw.ghw"; fi
+ cmd+=" --wave=$optghw";
+fi
+cmd+=" 2>&1 | ghdl_assert_filter\""
+
+# Note: the following ensurs that we always have 'fifo=, 0 )) ; then fifoopts+=",noinit"; fi
+
+if [[ -n "$fifoopts" ]] ; then
+ cmd+=" --fifo=$fifoopts"
+else
+ cmd+=" --fifo"
+fi
+
+cmd+=" --logl=3"
+
+if [[ -n "$optpack" ]] ; then cmd+=" --pack=$optpack"; fi
+if [[ -n "$optrri" ]] ; then cmd+=" $optrri"; fi
+
+cmd+=" --"
+
+if [[ -n "$optcuff" ]] ; then
+ cmd+=" \"rlc oob -sbdata 8 0x4\"" # portsel = 0100 -> fx2
+ cmd+=" \"rlc oob -sbdata 16 0x4\"" # swi = 0100 -> fx2
+fi
+
+if [[ -n "$optfusp" ]] ; then
+ cmd+=" \"rlc oob -sbdata 8 0x1\"" # portsel = 0001 -> 2nd ser
+ cmd+=" \"rlc oob -sbdata 16 0x1\"" # swi = 0001 -> 2nd ser
+fi
+
+if [[ -n "$optxon" ]] ; then
+ cmd+=" \"rlc oob -sbdata 8 0x2\"" # portsel = 0010 -> 1st ser XON
+ cmd+=" \"rlc oob -sbdata 16 0x2\"" # swi = 0010 -> 1st ser XON
+fi
+
+if (( $ncfxcount > 0 )) ; then cmd+=" \"rlc init\""; fi
+
+while (( $# > 0 )) ; do
+ cmd+=" "
+ if [[ $1 =~ " " ]] ; then cmd+="\""; fi
+ cmd+="$1"
+ if [[ $1 =~ " " ]] ; then cmd+="\""; fi
+ shift 1
+done
+cmd+=" | tee $logfile"
+
+pcomtag=""
+if [[ -n "$optpcom" ]] ; then pcomtag="^\#|"; fi
+# FAIL, PASS, DONE come from tbs
+cmd+=" | egrep \"(${pcomtag}-[EFW]:|FAIL|PASS|DONE)\""
+docmd "$cmd"
tbrun_tbwrri
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: ticonv_pdpcp
===================================================================
--- ticonv_pdpcp (nonexistent)
+++ ticonv_pdpcp (revision 33)
@@ -0,0 +1,275 @@
+#!/usr/bin/perl -w
+# $Id: ticonv_pdpcp 675 2015-05-08 21:05:08Z mueller $
+#
+# Copyright 2013-2015 by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Version Comment
+# 2015-05-08 675 1.3.1 start/stop/suspend overhaul
+# 2015-04-03 661 1.3 adopt to new stat checking and mask polarity
+# 2014-12-27 622 1.2.1 use wmembe now
+# 2014-12-07 609 1.2 use rlink::anena (for rlink v4)
+# 2014-07-31 576 1.1 add --cmax option (default = 3); support .sdef
+# 2014-07-26 575 1.0.4 add --tout option (sets wtcpu timeout)
+# 2013-05-19 521 1.0.3 use -be subopt of -wibrb
+# 2013-04-12 504 1.0.2 renamed from pi2ti_pdpcp; fix [rm]wi handling
+# use wtcpu command; use wibrbbe command;
+# 2013-02-05 483 1.0.1 make cpucmd parametrizable
+# 2013-02-02 480 1.0 Initial version
+#
+
+use 5.005; # require Perl 5.005 or higher
+use strict; # require strict checking
+
+use Getopt::Long;
+
+my %opts = ();
+
+GetOptions(\%opts, "tout=f", "cmax=i"
+ )
+ or die "bad options";
+
+sub cmdlist_do;
+sub add_edata;
+
+my @cmdlist;
+
+if (scalar(@ARGV) != 2) {
+ print STDERR "ticonv_pdpcp-E: usage: ticonv_pdpcp \n";
+ exit 1;
+}
+
+my $cpu = $ARGV[0];
+my $fnam = $ARGV[1];
+my $tout = $opts{tout} || 10.;
+my $cmax = $opts{cmax} || 6;
+
+open IFILE, $fnam or die "failed to open '$fnam'";
+
+print "set old_statvalue [rlc get statvalue]\n";
+print "set old_statmask [rlc get statmask]\n";
+print "\n";
+
+print "rlc set statvalue 0x00\n";
+print "rlc set statmask \$rlink::STAT_DEFMASK\n";
+print "\n";
+
+while () {
+ chomp;
+ s/--.*//; # drop all -- style comments
+ s/\s*$//; # drop traing blanks
+ next if m/^#/;
+
+ # print "$_\n";
+
+ my $cmd = $_;
+
+ $cmd =~ s/^rsp/rr6/; # rsp -> rr6
+ $cmd =~ s/^rpc/rr7/; # rpc -> rr7
+ $cmd =~ s/^wsp/wr6/; # wsp -> wr6
+ $cmd =~ s/^wpc/wr7/; # wpc -> wr7
+
+ # C... comments -> write to rlc log --------------------------------
+ if ($cmd =~ /^C(.*)/) {
+ cmdlist_do();
+ my $msg = $1;
+ $msg =~ s/"/'/g;
+ $msg =~ s/\[/\{/g;
+ $msg =~ s/\]/\}/g;
+ print "rlc log \"C $msg\"\n";
+
+ # .tocmd,.tostp,.togo,.cerr,.merr -> ignore, like pi_rri -----------
+ } elsif ($cmd =~ /^\.(tocmd|tostp|togo|[cm]err)\s+(\d*)$/) {
+ print "# $cmd currently ignored\n";
+
+ # .mode mode -> accept only 'pdpcp', quit otherwise ----------------
+ } elsif ($cmd =~ /^\.mode\s+(.*)$/) {
+ if ($1 ne "pdpcp") {
+ print "# FAIL: $cmd not supported\n";
+ exit 1;
+ }
+
+ # .sdef s=ref[,msk] ------------------------------------------------
+ } elsif ($cmd =~ /^\.sdef\s+s=([01]+),?([01]*)$/) {
+ cmdlist_do();
+ my $ref_sdef = oct("0b$1");
+ my $msk_sdef = oct("0b$2");
+ $msk_sdef = 0 unless defined $msk_sdef; # nothing ignored if not defined
+ printf "rlc log \".sdef 0x%2.2x,0x%2.2x\"\n", $ref_sdef, $msk_sdef;
+ printf "rlc set statvalue 0x%2.2x\n", $ref_sdef;
+ printf "rlc set statmask 0x%2.2x\n", (0xff & ~$msk_sdef);
+
+ # .rlmon,.rbmon ----------------------------------------------------
+ } elsif ($cmd =~ /^\.(r[lb]mon)\s+(\d)$/) {
+ cmdlist_do();
+ print "rlc oob -$1 $2\n";
+
+ # .scntl -----------------------------------------------------------
+ } elsif ($cmd =~ /^\.scntl\s+(\d+)\s+(\d)$/) {
+ cmdlist_do();
+ print "rlc oob -sbcntl $1 $2\n";
+
+ # .anena (0|1) -> rlink::anena n -----------------------------------
+ } elsif ($cmd =~ /^\.anena\s+(\d)$/) {
+ cmdlist_do();
+ print "rlink::anena $1\n";
+ print "rlc exec -attn\n";
+
+ # .reset -----------------------------------------------------------
+ } elsif ($cmd =~ /^\.reset$/) {
+ cmdlist_do();
+ print "rlc exec -init 0 1\n";
+
+ # (write) data type commands: wrx,wps,wal,wah,wm,wmi,stapc ---
+ # Note: 'stapc' must be decoded before 'sta' !!
+ # Note: 'wibrb' must be handled separately
+ # Note: 'wmi' must be matched before 'wm'
+ } elsif ($cmd =~ /^(wr[0-7]|wps|wal|wah|wmi|wm|stapc)\s+([0-7]+)$/) {
+ push @cmdlist, "-$1 0$2";
+
+ # (write) data type commands: wmembe ---
+ } elsif ($cmd =~ /^wmembe\s+([01]+)/) {
+ my $val = oct("0b$1");
+ my $be = $val & 0x3;
+ my $stick = $val & 0x4;
+ if ($stick == 0) {
+ push @cmdlist, "-wmembe $be";
+ } else {
+ push @cmdlist, "-wmembe $be -stick";
+ }
+
+ # (read) [d=data] type commands: rrx,rps,rm,rmi --------------------
+ # Note: 'rmi' must be matched before 'rm'
+ } elsif ($cmd =~ /^(rr[0-7]|rps|rmi|rm)/) {
+ push @cmdlist, "-$1 ";
+ add_edata($');
+
+ # bwm n ------------------------------------------------------------
+ } elsif ($cmd =~ /^bwm\s+(\d+)$/) {
+ my $nw = $1;
+ push @cmdlist, "-bwm {";
+ for (my $i=0; $i<$nw;) {
+ my $dat = ;
+ $dat =~ s/--.*//;
+ $dat =~ s/\s*//g;
+ next if $dat =~ m/^#/;
+ $cmdlist[-1] .= " 0$dat";
+ $i++;
+ }
+ $cmdlist[-1] .= "}";
+ cmdlist_do();
+
+ # brm n ------------------------------------------------------------
+ } elsif ($cmd =~ /^brm\s+(\d+)$/) {
+ my $nw = $1;
+ push @cmdlist, "-brm $1";
+ my @data;
+ my @mask;
+ my $domask;
+ for (my $i=0; $i<$nw;) {
+ my $dat = ;
+ $dat =~ s/--.*//;
+ $dat =~ s/\s*//g;
+ next if $dat =~ m/^#/;
+ if ($dat =~ m/d=([0-7]+)/ ) {
+ push @data, "0$1";
+ push @mask, "0177777";
+ } elsif ($dat =~ m/d=-/) {
+ push @data, "0";
+ push @mask, "0";
+ $domask = 1;
+ } else {
+ exit 1;
+ }
+ $i++;
+ }
+ $cmdlist[-1] .= " -edata {" . join(" ",@data) . "}";
+ $cmdlist[-1] .= " {" . join(" ",@mask) . "}" if $domask;
+ cmdlist_do();
+
+ # wibr off data ---------------------------------------------------
+ } elsif ($cmd =~ /^(wibr)\s+([0-7]+)\s+([0-7]+)$/) {
+ push @cmdlist, "-$1 0$2 0$3";
+
+ # ribr off [d=data] ------------------------------------------------
+ } elsif ($cmd =~ /^(ribr)\s+([0-7]+)/) {
+ push @cmdlist, "-$1 0$2";
+ add_edata($');
+
+ # simple action commands: sta,sto,step,cres,bres -------------------
+ } elsif ($cmd =~ /^(sta|sto|step|cres|bres)$/) {
+ my %cmdmap = (sta => 'start',
+ sto => 'stop',
+ step => 'step',
+ cres => 'creset',
+ bres => 'breset');
+ push @cmdlist, sprintf "-%s", $cmdmap{$1};
+
+ # wtgo -> wtcpu ----------------------------------------------------
+ } elsif ($cmd =~ /^(wtgo)$/) {
+ cmdlist_do();
+ print "$cpu wtcpu $tout";
+ print "\n";
+
+ # wtlam apat -------------------------------------------------------
+ # Note: apat currently ignored !!
+ } elsif ($cmd =~ /^(wtlam)/) {
+ cmdlist_do();
+ print "$cpu wtcpu $tout";
+ print "\n";
+
+ # currently unimplemented commands ... -----------------------------
+ } elsif ($cmd =~ /^(\.wait)/) {
+ print "## TODO... $cmd\n";
+
+ } else {
+ print "# FAIL: no match for '$cmd'\n";
+ exit 1;
+ }
+
+ cmdlist_do() if scalar(@cmdlist) >= $cmax;
+
+}
+
+cmdlist_do();
+
+print "\n";
+print "rlc set statvalue \$old_statvalue\n";
+print "rlc set statmask \$old_statmask\n";
+
+exit 0;
+
+#-------------------------------------------------------------------------------
+sub add_edata {
+ my ($crest) = @_;
+ $crest =~ s/\s+//;
+ if ($crest =~ m/d=([0-7]+)/) {
+ $cmdlist[-1] .= " -edata 0$1";
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub cmdlist_do {
+ return unless scalar(@cmdlist);
+
+# printf "$cpu cp \\\n";
+ print "$cpu cp \\\n";
+ while (scalar(@cmdlist)) {
+ print " ";
+ print shift @cmdlist;
+ print " \\\n" if scalar(@cmdlist);
+ }
+ print "\n";
+ @cmdlist = ();
+ return;
+}
+
ticonv_pdpcp
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: vbomconv
===================================================================
--- vbomconv (nonexistent)
+++ vbomconv (revision 33)
@@ -0,0 +1,964 @@
+#!/usr/bin/perl -w
+# $Id: vbomconv 672 2015-05-02 21:58:28Z mueller $
+#
+# Copyright 2007-2015 by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Version Comment
+# 2015-02-15 646 1.11 add vivado support: add -xlpath, use instead
+# of XTWI_PATH; drop --ise_path; add @lib:unimacro;
+# drop --viv_vhdl; add --vsyn_prj, --dep_vsyn;
+# drop cygwin support;
+# 2014-07-26 575 1.10.1 use XTWI_PATH now (ise/vivado switch done later)
+# 2013-10-20 543 1.10 add --viv_vhdl
+# 2012-02-05 456 1.9.4 redo filename substitution (= and :); add --get_top
+# 2012-01-02 448 1.9.3 use in ghdl_m -fexplicit also when simprim used
+# 2011-11-27 433 1.9.2 use in ghdl_m -fexplicit when unisim used
+# 2011-08-13 405 1.9.1 always write 'vhdl' into xst prj files again; for
+# -xst_export: remove opt file export, add ucf_cpp
+# handling
+# 2011-06-26 385 1.9 add --ise_path, pass it to vbomconv --xst_prj
+# 2011-06-09 383 1.8.6 fix xst_vhdl.opt logic (use rtl/vlib now)
+# 2010-07-03 312 1.8.5 add --flist action
+# 2010-06-03 299 1.8.4 generate ucf->ncd dependencies in dep_xst
+# 2010-04-26 284 1.8.3 add _[sft]sim support for ISim
+# 2009-11-28 253 1.8.2 fixup print_help...;
+# 2009-11-22 252 1.8.1 add (export|dep)_isim, full ISim support;
+# add [isim] [sim], allow tag lists like [ghdl,isim];
+# --trace and messages to STDERR;
+# 2009-11-20 251 1.8 add isim_prj, first ISim support
+# 2008-03-09 124 1.7.3 add in .dep_(ghdl|xst) all dep on vbom dependencies
+# target now also dependant on .dep_ file
+# 2008-03-02 122 1.7.2 add @lib: directive to include UNISIM
+# 2007-12-17 102 1.7.1 fix @ucf_cpp logic.
+# 2007-12-16 101 1.7 add @ucf_cpp pseudo tag (handle cpp'ed ucf files)
+# 2007-11-25 98 1.6.1 drop trailing blanks on input lines
+# 2007-11-02 94 1.6 added (xst|ghdl)_export
+# 2007-10-26 92 1.5.1 emit '--no-vital-checks' for --ghdl_m for _[sft]sim
+# 2007-10-14 98 1.5 handle .exe files under cygwin properly
+# 2007-09-15 82 1.4 handle C source objects properly
+# 2007-08-10 72 1.3 add [xst], [ghdl] prefix support
+# 2007-07-22 68 1.2 add "tag = val"; list files in 'ready to analyse'
+# order; add --ghdl_a option
+# 2007-07-08 65 1.1 add "tag : names"; inferral of _[ft]sim vboms
+# 2007-07-06 64 1.0 Initial version
+
+use 5.005; # require Perl 5.005 or higher
+use strict; # require strict checking
+use FileHandle;
+
+use Getopt::Long;
+
+my %opts = ();
+
+GetOptions(\%opts, "help", "trace", "xlpath=s",
+ "dep_ghdl", "dep_xst", "dep_isim", "dep_vsyn",
+ "xst_prj", "isim_prj",
+ "vsyn_prj",
+ "ghdl_a", "ghdl_a_cmd",
+ "ghdl_i", "ghdl_i_cmd",
+ "ghdl_m", "ghdl_m_cmd",
+ "ghdl_export=s",
+ "xst_export=s",
+ "isim_export=s",
+ "get_top",
+ "flist") || exit 1;
+
+sub print_help;
+sub read_vbom;
+sub scan_vbom;
+sub copy_edir;
+sub write_vbomdep;
+sub canon_fname;
+
+my @vbom_queue; # list of pending vbom's
+my @srcfile_list; # list of sources in compile order
+my @xdcfile_list; # list of xdc files
+my %vbom_files; # key=vbom; val=full file list
+my %vbom_xdc; # key=vbom; val=xdc spec list
+my %vbom_done; # key=vbom; val=done flags
+my %vbom_rank; # key=vbom; val=vbom ranks
+my %srcfile_rank; # key=source file; val=file rank
+my %para_tbl; # substitution table
+my @ucf_cpp_list;
+my $is_ghdl = 0; # ghdl simulation target
+my $is_xst = 0; # XST synthesis target
+my $is_isim = 0; # ISim simulation target
+my $is_vsyn = 0; # vivado synthesis target
+my $is_vsim = 0; # vivado simulation target
+my $is_sim = 0; # simulation target (generic)
+my $is_any = 0; # ignore tags (for --flist)
+my $nactions = 0; # number of action commands
+my $top_vbom; # top level vbom (from argv)
+my $stem; # stem of $top_vbom
+my $top; # top level entity name
+my $top_done = 0; # @top seen
+my $has_unisim; # @lib:unisim seen or implied
+my $has_unimacro; # @lib:unimacro seen
+my $has_simprim; # @lib:simprim seen or implied
+my $is_ssim;
+my $is_fsim;
+my $is_tsim;
+my $do_trace = exists $opts{trace};
+my $level = 0; # vbom nesting level
+my $xst_writevhdl = 1;
+my $xlpath=$opts{xlpath};
+my $no_xlpath = ! defined $xlpath || $xlpath eq "";
+
+autoflush STDOUT 1; # autoflush, so nothing lost on exec later
+
+if (exists $opts{help}) {
+ print_help;
+ exit 0;
+}
+
+# ensure that one and only one vbom is specified
+
+if (scalar(@ARGV) != 1) {
+ print STDERR "vbomconv-E: only one vbom file name allowed\n\n";
+ print_help;
+ exit 1;
+}
+
+# check that only one action is defined, mark xst, gdhl, or isim class
+
+foreach (keys %opts) {
+ $nactions += 1 unless ($_ eq "trace" || $_ eq "xlpath");
+ $is_ghdl = 1 if ($_ eq "dep_ghdl");
+ $is_ghdl = 1 if ($_ =~ /^ghdl_/);
+
+ $is_xst = 1 if ($_ eq "dep_xst");
+ $is_xst = 1 if ($_ =~ /^xst_/);
+
+ $is_isim = 1 if ($_ eq "dep_isim");
+ $is_isim = 1 if ($_ =~ /^isim_/);
+
+ $is_vsyn = 1 if ($_ eq "dep_vsyn");
+ $is_vsyn = 1 if ($_ =~ /^vsyn_/);
+
+ $is_any = 1 if ($_ eq "flist");
+}
+
+$is_sim = $is_ghdl | $is_isim | $is_vsim;
+
+print STDERR "-- [ghdl] active\n" if $do_trace && $is_ghdl;
+print STDERR "-- [xst] active\n" if $do_trace && $is_xst;
+print STDERR "-- [isim] active\n" if $do_trace && $is_isim;
+print STDERR "-- [vsyn] active\n" if $do_trace && $is_vsyn;
+print STDERR "-- [vsim] active\n" if $do_trace && $is_vsim;
+print STDERR "-- [sim] active\n" if $do_trace && $is_sim;
+
+if ($nactions > 1) {
+ print STDERR "vbomconv-E: only one action qualifier allowed\n\n";
+ print_help;
+ exit 1;
+}
+
+$top_vbom = $ARGV[0];
+
+$top_vbom .= ".vbom" unless $top_vbom =~ m{\.vbom$};
+
+$stem = $top_vbom;
+$stem =~ s{\..*$}{};
+
+$top = $stem;
+$top =~ s{^.*/}{};
+
+# now prepare virtual _fsim and _tsim vbom's
+# they are inferred from the _ssim vbom's
+
+if ($top_vbom =~ m{_ssim\.vbom$}) { # detect _ssim
+ $is_ssim = 1;
+}
+if ($top_vbom =~ m{_fsim\.vbom$}) { # map _fsim -> _ssim
+ $is_fsim = 1;
+ $top_vbom =~ s{_fsim\.vbom$}{_ssim.vbom};
+}
+if ($top_vbom =~ m{_tsim\.vbom$}) { # map _tsim -> _ssim
+ $is_tsim = 1;
+ $top_vbom =~ s{_tsim\.vbom$}{_ssim.vbom};
+}
+
+# traverse all vbom's start with command line argument
+
+push @vbom_queue, $top_vbom;
+
+while (@vbom_queue) {
+ my $cur_vbom = shift @vbom_queue;
+ read_vbom($cur_vbom);
+}
+
+# traverse internal vbom representation to build file table
+
+$vbom_rank{$top_vbom} = {min=>1, max=>1};
+scan_vbom($top_vbom);
+
+# sort file table, build file list (decreasing rank)
+# sort first by decreasing rank and second by filename
+# second sort only to get stable sequence, independent of hash keys
+
+my @srcpair_list;
+foreach (keys %srcfile_rank) {
+ push @srcpair_list, [$srcfile_rank{$_}, $_];
+}
+
+@srcfile_list = map {$_->[1]}
+ sort {$b->[0] <=> $a->[0] || $a->[1] cmp $b->[1]}
+ @srcpair_list;
+
+# setup vbom list by rank
+my @vbom_rank_list;
+foreach (sort keys %vbom_rank) {
+ push @vbom_rank_list, [$vbom_rank{$_}{min}, $vbom_rank{$_}{max}, $_];
+}
+my @vbomfile_list_min = map {$_->[2]}
+ sort {$a->[0] <=> $b->[0] || $a->[1] cmp $b->[1]}
+ @vbom_rank_list;
+
+# setup xdc files list (if one @xdc: seen)
+foreach (@vbomfile_list_min) {
+ push @xdcfile_list, @{$vbom_xdc{$_}} if exists $vbom_xdc{$_};
+}
+
+# now generate output and actions, depending on options given
+
+# --trace ------------------------------------------------------------
+
+if ($do_trace) {
+ print STDERR "\n";
+ print STDERR "filename substitution table:\n";
+ foreach (sort keys %para_tbl) {
+ print STDERR " $_ = $para_tbl{$_}\n";
+ }
+
+ print STDERR "\n";
+ print STDERR "final vbom_rank table (sort by min rank):\n";
+ print STDERR " min max var vbom-name:\n";
+ foreach (sort {$a->[0] <=> $b->[0] || $a->[2] cmp $b->[2]} @vbom_rank_list) {
+ printf STDERR " %3d %3d %3d %s\n",
+ $_->[0], $_->[1], $_->[1]-$_->[0], $_->[2];
+ }
+
+ print STDERR "\n";
+ print STDERR "final srcfile_rank table (sort by rank):\n";
+ foreach (sort {$b->[0] <=> $a->[0] || $a->[1] cmp $b->[1]} @srcpair_list) {
+ printf STDERR " %5d %s\n", $_->[0], $_->[1];
+ }
+
+ print STDERR "\n";
+ print STDERR "properties:\n";
+ print STDERR " \@top: $top\n";
+}
+
+# --ghdh_a -- ghdl analysis command ----------------------------------
+
+if (exists $opts{ghdl_a} || exists $opts{ghdl_a_cmd}) {
+ if ($no_xlpath && ($has_unisim || $has_unimacro || $has_simprim) ) {
+ print STDERR "vbomconv-E: --xlpath required with ghdl_a or ghdl_a_cmd";
+ exit 1;
+ }
+
+ foreach (@srcfile_list) {
+ my $file = $_;
+ my $cmd = "ghdl -a";
+ $cmd .= " -P$xlpath/unisim" if $has_unisim;
+ $cmd .= " -P$xlpath/unimacro" if $has_unimacro;
+ $cmd .= " -P$xlpath/simprim" if $has_simprim;
+ $cmd .= " --ieee=synopsys";
+ $cmd .= " $file";
+ print "$cmd\n";
+ if (exists $opts{ghdl_a}) {
+ my $wrc = system "/bin/sh", "-c", $cmd;
+ if ($wrc != 0) {
+ my $rc = int($wrc/256);
+ if ($rc == 0) {
+ my $sig = $wrc % 256;
+ print STDERR "vbomconv-I: compilation aborted by signal $sig\n";
+ exit(1);
+ } else {
+ print STDERR "vbomconv-I: compilation failed (rc=$rc) $?\n";
+ exit($rc);
+ }
+ }
+ }
+ }
+}
+
+# --ghdh_i -- ghdl inspection command --------------------------------
+
+if (exists $opts{ghdl_i} || exists $opts{ghdl_i_cmd}) {
+ my %ghdl_work;
+
+ # read ghdl "work-obj93.cf" file. It has the format
+ # file . "" "" "ghdl -i or -a date>":
+ # entity at nn( nn) + nn on nn;
+ # architecture of at nn( nn) + nn on nn;
+
+ if (-r "work-obj93.cf") {
+ open (WFILE, "work-obj93.cf") or
+ die "can't open for read work-obj93.cf: $!";
+ while () {
+ if (m{^file \. \"(.*?)\"}) {
+ $ghdl_work{$1} = 1;
+ }
+ }
+ close (WFILE);
+ }
+
+ my $cmd = "ghdl -i";
+ my $nfile = 0;
+
+ foreach (@srcfile_list) {
+ next if /\.c$/; # skip C sources, only vhd handled
+ if (not exists $ghdl_work{$_}) {
+ $cmd .= " \\\n $_";
+ $nfile += 1;
+ }
+ }
+
+ if ($nfile) {
+ print "$cmd\n";
+ if (exists $opts{ghdl_i}) {
+ exec "/bin/sh", "-c", $cmd;
+ die "failed to exec /bin/sh -c $cmd: $!";
+ }
+ } else {
+ print "# $cmd ## all files already inspected\n";
+ }
+}
+
+# --ghdh_m -- ghdl make command --------------------------------------
+# Note: the 'buildin' make used by the -m option of ghdl does not
+# check for object files linked with -Wl, e.g. vhpi objects.
+# To force a re-elaboration the old executable is deleted first.
+# If used from make with proper dependencies, this will just do
+# the right thing.
+
+if (exists $opts{ghdl_m} || exists $opts{ghdl_m_cmd} ) {
+ my $cmd = "";
+
+ if ($no_xlpath && ($has_unisim || $has_unimacro || $has_simprim) ) {
+ print STDERR "vbomconv-E: --xlpath required with ghdl_m or ghdl_m_cmd";
+ exit 1;
+ }
+
+ if (-r $stem) { # check for old executable
+ $cmd .= "rm $stem\n" ; # rm to force elaboration
+ }
+
+ $cmd .= "ghdl -m";
+ $cmd .= " -o $stem";
+ # -fexplicit needed for ISE 13.1,13.3
+ $cmd .= ' -fexplicit' if $has_unisim or $has_unimacro or $has_simprim;
+ $cmd .= " -P$xlpath/unisim" if $has_unisim;
+ $cmd .= " -P$xlpath/unimacro" if $has_unimacro;
+ $cmd .= " -P$xlpath/simprim" if $has_simprim;
+ $cmd .= " --ieee=synopsys";
+ $cmd .= " --no-vital-checks" if $is_ssim or $is_fsim or $is_tsim;
+
+ foreach (@srcfile_list) {
+ next unless /\.c$/; # C source ?
+ my $ofile = $_; # copy to break alias for following s///
+ $ofile =~ s{^.*/}{}; # remove directory path
+ $ofile =~ s/\.c$/.o/; # add clause to link C source object file
+ $cmd .= " -Wl,$ofile";
+ }
+ $cmd .= " $top";
+ print "$cmd\n";
+ if (exists $opts{ghdl_m}) {
+ exec "/bin/sh", "-c", $cmd;
+ die "failed to exec /bin/sh -c $cmd: $!";
+ }
+}
+
+# --xst_prj ----------------------------------------------------------
+
+if (exists $opts{xst_prj}) {
+ ## $xst_writevhdl = 0; # needed in case "-use_new_parser yes" used
+ foreach (@srcfile_list) {
+ if ($xst_writevhdl) {
+ print "vhdl work $_\n";
+ } else {
+ print "work $_\n"; # for ISE S-6/V-6 compilations with '-ifmt VHDL'
+ }
+ }
+}
+
+# --isim_prj ---------------------------------------------------------
+
+if (exists $opts{isim_prj}) {
+ foreach (@srcfile_list) {
+ print "vhdl work $_\n";
+ }
+}
+
+# --vsyn_prj ---------------------------------------------------------
+
+if (exists $opts{vsyn_prj}) {
+ # setup sources
+ print "#\n";
+ print "# setup sources\n";
+ print "#\n";
+ print "set src_files {\n";
+ foreach (@srcfile_list) {
+ print " $_\n";
+ }
+ print "}\n";
+ print "\n";
+
+ print "set obj [get_filesets sources_1]\n";
+ print "add_files -norecurse -fileset \$obj \$src_files\n";
+ print "set_property \"top\" \"$top\" \$obj\n";
+
+ # setup constraints
+ print "#\n";
+ print "# setup constraints\n";
+ print "#\n";
+
+ print "set xdc_files {\n";
+ foreach (@xdcfile_list) {
+ print " $_\n";
+ }
+ print "}\n";
+ print "\n";
+
+ print "set obj [get_filesets constrs_1]\n";
+ print "add_files -norecurse -fileset \$obj \$xdc_files\n";
+
+ print "\n";
+}
+
+# --dep_ghdl ---------------------------------------------------------
+
+if (exists $opts{dep_ghdl}) {
+
+ my $stem_fsim = $stem;
+ my $stem_tsim = $stem;
+ $stem_fsim =~ s/_ssim$/_fsim/;
+ $stem_tsim =~ s/_ssim$/_tsim/;
+
+ print "#\n";
+ print "$stem : $stem.dep_ghdl\n";
+ if ($is_ssim) {
+ print "$stem_fsim : $stem.dep_ghdl\n";
+ print "$stem_tsim : $stem.dep_ghdl\n";
+ }
+ print "#\n";
+
+ foreach (@srcfile_list) {
+ if (/\.c$/) {
+ my $ofile = $_; # copy to break alias for following s///
+ $ofile =~ s{^.*/}{}; # remove directory path
+ $ofile =~ s/\.c$/.o/; # object file name
+ print "$stem : $ofile\n"; # depend on C source object file
+ # C source object compilation dependence
+ open (ODEPFILE, ">$ofile.dep_ghdl") or
+ die "can't write $ofile.dep_ghdl: $!";
+ print ODEPFILE "$ofile : $_\n";
+ print ODEPFILE "\t\$(COMPILE.c) \$(OUTPUT_OPTION) \$<\n";
+ close ODEPFILE;
+ } else {
+ print "$stem : $_\n";
+ }
+ }
+
+ if ($is_ssim) {
+
+ foreach (@srcfile_list) {
+ my $file = $_; # copy to break alias for following s///
+ if (/\.c$/) {
+ $file =~ s{^.*/}{}; # remove directory path
+ $file =~ s/\.c$/.o/; # depend on object file for C sources
+ } else {
+ $file =~ s/_ssim\.vhd$/_fsim.vhd/;
+ }
+ print "$stem_fsim : $file\n";
+ }
+
+ foreach (@srcfile_list) {
+ my $file = $_; # copy to break alias for following s///
+ if (/\.c$/) {
+ $file =~ s{^.*/}{}; # remove directory path
+ $file =~ s/\.c$/.o/; # depend on object file for C sources
+ } else {
+ $file =~ s/_ssim\.vhd$/_tsim.vhd/;
+ }
+ print "$stem_tsim : $file\n";
+ }
+
+ }
+
+ write_vbomdep("$stem.dep_ghdl");
+
+}
+
+# --dep_xst ----------------------------------------------------------
+
+if (exists $opts{dep_xst}) {
+ print "#\n";
+ print "$stem.ngc : $stem.dep_xst\n";
+ print "#\n";
+ foreach (@srcfile_list) {
+ print "$stem.ngc : $_\n";
+ }
+ # handle cpp preprocessed ucf's
+ foreach (@ucf_cpp_list) {
+ my $file = $_;
+ $file =~ s/\.ucf$//;
+ print "#\n";
+ print "$file.ncd : $file.ucf\n";
+ print "include $file.dep_ucf_cpp\n";
+ }
+ # handle plain ucf's
+ if (scalar(@ucf_cpp_list)==0 && -r "$stem.ucf") {
+ print "#\n";
+ print "$stem.ncd : $stem.ucf\n";
+ }
+ write_vbomdep("$stem.dep_xst");
+}
+
+# --dep_isim ---------------------------------------------------------
+
+if (exists $opts{dep_isim}) {
+ my $stem_isim = $stem . "_ISim";
+
+ $stem_isim =~ s/_ssim_ISim$/_ISim_ssim/ if ($is_ssim);
+
+ my $stem_fsim_isim = $stem_isim;
+ my $stem_tsim_isim = $stem_isim;
+ $stem_fsim_isim =~ s/_ssim$/_fsim/;
+ $stem_tsim_isim =~ s/_ssim$/_tsim/;
+
+ print "#\n";
+ print "$stem_isim : $stem.dep_isim\n";
+ if ($is_ssim) {
+ print "$stem_fsim_isim : $stem.dep_isim\n";
+ print "$stem_tsim_isim : $stem.dep_isim\n";
+ }
+ print "#\n";
+
+ foreach (@srcfile_list) {
+ print "$stem_isim : $_\n";
+ }
+
+ if ($is_ssim) {
+
+ foreach (@srcfile_list) {
+ my $file = $_; # copy to break alias for following s///
+ $file =~ s/_ssim\.vhd$/_fsim.vhd/;
+ print "$stem_fsim_isim : $file\n";
+ }
+
+ foreach (@srcfile_list) {
+ my $file = $_; # copy to break alias for following s///
+ $file =~ s/_ssim\.vhd$/_tsim.vhd/;
+ print "$stem_tsim_isim : $file\n";
+ }
+
+ }
+
+ write_vbomdep("$stem.dep_isim");
+}
+
+# --dep_vsyn ---------------------------------------------------------
+
+if (exists $opts{dep_vsyn}) {
+ print "#\n";
+ print "$stem.bit : $stem.dep_vsyn\n";
+ print "#\n";
+ my @files;
+ push @files, @srcfile_list;
+ push @files, @xdcfile_list;
+ foreach (@files) {
+ print "$stem.bit : $_\n";
+ }
+ print "#\n";
+ foreach (@files) {
+ print "${stem}_syn.dcp : $_\n";
+ }
+ print "#\n";
+ foreach (@files) {
+ print "${stem}_rou.dcp : $_\n";
+ }
+ write_vbomdep("$stem.dep_vsyn");
+}
+
+# --ghdl_export or xst_export or isim_export -------------------------
+
+if (exists $opts{ghdl_export} or
+ exists $opts{xst_export} or
+ exists $opts{isim_export}) {
+ my $edir;
+ $edir = $opts{ghdl_export} if exists $opts{ghdl_export};
+ $edir = $opts{xst_export} if exists $opts{xst_export};
+ $edir = $opts{isim_export} if exists $opts{isim_export};
+
+ if (not -d $edir) {
+ print STDERR "vbomconv-I: create target directory $edir\n";
+ system("mkdir -p $edir") == 0 or die "mkdir failed: $?";
+ } else {
+ print STDERR "vbomconv-I: target directory $edir already exists\n";
+ }
+
+ open(PFILE, ">$edir/$stem.prj") or die "can't write open $edir/$stem.prj: $!";
+
+ foreach (@srcfile_list) {
+ my $fname = $_;
+ my $fdpath = ".";
+ if (m{(.*)/(.*)}) {
+ $fname = $2;
+ $fdpath = $1;
+ }
+ copy_edir($_, $edir);
+ print PFILE "vhdl work $fname\n";
+ }
+
+ close(PFILE);
+
+ # Note: currently no xflow opt files exported !!
+ if (exists $opts{xst_export}) {
+ open(XFILE, ">$edir/$stem.xcf") or
+ die "can't write open $edir/$stem.xcf: $!";
+ close(XFILE);
+
+ foreach(glob("*.xcf")) { copy_edir($_, $edir); }
+
+ if (-r "$stem.ucf_cpp") {
+ system "/bin/sh", "-c", "make $stem.ucf";
+ }
+
+ foreach(glob("*.ucf")) { copy_edir($_, $edir); }
+ }
+
+}
+
+# --get_top ----------------------------------------------------------
+
+if (exists $opts{get_top}) {
+ print "$top\n";
+}
+
+# --flist ------------------------------------------------------------
+
+if (exists $opts{flist}) {
+
+ my @flist;
+
+ push @flist, @srcfile_list;
+ push @flist, sort keys %vbom_done;
+
+ if (scalar(@ucf_cpp_list)) {
+ foreach (@ucf_cpp_list) {
+ push @flist, $_."_cpp";
+ }
+ } else {
+ if (-r "$stem.ucf") {
+ push @flist, "$stem.ucf";
+ }
+ }
+
+ push @flist, @xdcfile_list;
+
+ foreach (sort @flist) {
+ my $fname = $_;
+ my $fdpath = ".";
+ if (m{(.*)/(.*)}) {
+ $fname = $2;
+ $fdpath = $1;
+ }
+ print "$fdpath/$fname\n";
+ }
+
+}
+
+#-------------------------------------------------------------------------------
+
+sub read_vbom {
+ my ($vbom) = @_;
+
+ print STDERR "-- open $vbom\n" if $do_trace;
+
+ open (IFILE, $vbom) or die "can't open for read $vbom: $!";
+
+ my $vbom_path = "";
+ my $vbom_file = $vbom;
+ if ($vbom =~ m{^(.*)/([a-zA-Z0-9_.]*)$}) {
+ $vbom_path = $1;
+ $vbom_file = $2;
+ }
+
+ $vbom_done{$vbom} += 1; # mark this vbom already read
+
+ while () {
+ chomp;
+ next if /^\s*#/; # drop comments
+ next if /^\s*$/; # drop empty lines
+
+ s/\s*$//; # drop trailing blanks
+
+ # process parameter definitions
+ if (m{([\w]+)\s*=\s*(.*)}) {
+ my $para = $1;
+ my $val = $2;
+ if ($val eq "") {
+ print STDERR "vbomconv-E: invalid \'$_\' in $vbom_file\n";
+ exit 1;
+ }
+ if (not exists $para_tbl{$para}) {
+ $para_tbl{$para} = canon_fname($vbom_path, $val);
+ print STDERR "--- define \${$para} = $val\n" if $do_trace;
+ } else {
+ print STDERR "--- ignore \${$para} = $val\n" if $do_trace;
+ }
+ next;
+ }
+
+ # process parameter substitutions
+ while (m{\$\{([\w]+)\s*(:=)?\s*(.*?)\}}) {
+ my $para = $1;
+ my $del = $2;
+ my $val = $3;
+ my $pre = $`;
+ my $post = $';
+ if (defined $del && $del eq ":=") {
+ if (not exists $para_tbl{$para}) {
+ $para_tbl{$para} = canon_fname($vbom_path, $val);
+ print STDERR "--- define \${$para := $val}\n" if $do_trace;
+ } else {
+ print STDERR "--- ignore \${$para := $val}\n" if $do_trace;
+ }
+ }
+ if (defined $para_tbl{$para}) {
+ if ($do_trace) {
+ print STDERR "--- use \${$para} -> $para_tbl{$para}\n";
+ } else {
+ ## print STDERR "vbomconv-I: \${$para} -> $para_tbl{$para}\n";
+ }
+ $_ = $pre . "!" . $para_tbl{$para} . $post;
+ } else {
+ print STDERR "vbomconv-E: undefined \${$para} in $vbom_file\n";
+ exit 1;
+ }
+ }
+
+ if (/^\[([a-z,]+)\]\s*(.+)$/) { # [xxx,yyy] tag seen
+ my $qual = $1;
+ my $name = $2;
+ my $keep = $is_any;
+ ## print STDERR "+++1 |$qual|$name|$vbom|\n";
+ foreach my $pref (split /,/,$qual) {
+ if ($pref =~ /^(ghdl|xst|isim|vsyn|vsim|sim)$/) {
+ $keep = 1 if ($pref eq "ghdl" && $is_ghdl);
+ $keep = 1 if ($pref eq "xst" && $is_xst);
+ $keep = 1 if ($pref eq "isim" && $is_isim);
+ $keep = 1 if ($pref eq "vsyn" && $is_vsyn);
+ $keep = 1 if ($pref eq "vsim" && $is_vsim);
+ $keep = 1 if ($pref eq "sim" && $is_sim);
+ } else {
+ print STDERR "vbomconv-W: unknown tag [$pref] in $vbom_file\n";
+ }
+ }
+ if (not $keep) {
+ print STDERR "--- drop \"$_\"\n" if $do_trace;
+ next;
+ }
+ $_ = $name; # remove [xxx] tag
+ }
+
+ my $tag;
+ my $val = $_;
+
+ # detect tag:val lines
+ if (m{^\s*(.*?)\s*:\s*(.*?)\s*$}) {
+ $tag = $1;
+ $val = $2;
+
+ # process @top: lines
+ if ($tag eq '@top') {
+ $top = $val unless $top_done;
+
+ # process @ucf_cpp: lines
+ } elsif ($tag eq '@ucf_cpp') {
+ push @ucf_cpp_list, $val;
+
+ # process @xdc: lines
+ } elsif ($tag eq '@xdc') {
+ push @{$vbom_xdc{$vbom}}, canon_fname($vbom_path, $val);
+
+ # process @lib: lines
+ } elsif ($tag eq '@lib') {
+ if ($val eq 'unisim') {
+ $has_unisim = 1;
+ } elsif ($val eq 'unimacro') {
+ $has_unimacro = 1;
+ } elsif ($val eq 'simprim') {
+ $has_simprim = 1;
+ } else {
+ print STDERR "vbomconv-E: invalid lib type \'$tag\' in $vbom_file\n";
+ exit 1;
+ }
+
+ # catch invalid @ tags
+ } else {
+ print STDERR "vbomconv-E: invalid \'$tag:\' line in $vbom_file\n";
+ exit 1;
+ }
+ next;
+ }
+
+ # now do _fsim, _tsim mapping
+ $val =~ s{_ssim\.vhd$}{_fsim.vhd} if $is_fsim;
+ $val =~ s{_ssim\.vhd$}{_tsim.vhd} if $is_tsim;
+
+ # process normal .vhd or .vbom file lines
+ # canonize file name unless not already done by filename substitution
+ my $fullname;
+ if ($val =~ m{^!(.*)$}) {
+ $fullname = $1;
+ } else {
+ $fullname = canon_fname($vbom_path, $val);
+ }
+
+ # determine whether additional libs needed
+ if ($fullname =~ m{_ssim\.vhd$}) { # ends in _ssim.vhd
+ $has_unisim = 1;
+ }
+ if ($fullname =~ m{_[ft]sim\.vhd$}) { # ends in _fsim.vhd or _tsim.vhd
+ $has_simprim = 1;
+ }
+
+ # build vbom table
+ push @{$vbom_files{$vbom}}, $fullname;
+ print STDERR "--- add $fullname\n" if $do_trace;
+
+ # if a vbom, queue if not not already read
+ if ($fullname =~ m{\.vbom$} && not exists $vbom_done{$fullname} ) {
+ push @vbom_queue, $fullname;
+ print STDERR "--- queue $fullname\n" if $do_trace;
+ }
+
+ }
+
+ $top_done = 1;
+
+ close (IFILE);
+}
+
+#-------------------------------------------------------------------------------
+
+sub scan_vbom {
+ my ($vbom) = @_;
+
+ $level += 1;
+ my $rank = 1000*$level + scalar(@{$vbom_files{$vbom}});
+ print STDERR "--> $level: $vbom\n" if $do_trace;
+
+ die "vbomcov-E excessive vbom stack depth \n" if $level>=1000;
+
+ if (exists $vbom_rank{$vbom}) {
+ $vbom_rank{$vbom}{min} = $level if $level < $vbom_rank{$vbom}{min};
+ $vbom_rank{$vbom}{max} = $level if $level > $vbom_rank{$vbom}{max};
+ } else {
+ $vbom_rank{$vbom} = {min=>$level, max=>$level};
+ }
+
+ foreach (@{$vbom_files{$vbom}}) {
+ my $file = $_;
+ $rank -= 1;
+ if (m{\.vbom$}) {
+ scan_vbom($file);
+ } else {
+ if (exists $srcfile_rank{$file}) {
+ if ($rank > $srcfile_rank{$file}) {
+ print STDERR " $file $srcfile_rank{$file} -> $rank\n" if $do_trace;
+ $srcfile_rank{$file} = $rank;
+ } else {
+ print STDERR " $file $srcfile_rank{$file} (keep)\n" if $do_trace;
+ }
+ } else {
+ $srcfile_rank{$file} = $rank;
+ print STDERR " $file $srcfile_rank{$file} (new)\n" if $do_trace;
+ }
+ }
+ }
+
+ print STDERR "<-- $level: $vbom\n" if $do_trace;
+ $level -= 1;
+
+}
+
+#-------------------------------------------------------------------------------
+
+sub copy_edir {
+ my ($file, $edir) = @_;
+ print "cp -p $file $edir\n";
+ system("cp -p $file $edir")==0 or die "cp -p failed: $?";
+}
+
+#-------------------------------------------------------------------------------
+
+sub write_vbomdep {
+ my ($target) = @_;
+ print "#\n";
+ print "# .dep_* on .vbom dependencies\n";
+ print "#\n";
+ foreach (sort keys %vbom_done) {
+ print "$target : $_\n";
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub canon_fname {
+ my ($vpath,$fname) = @_;
+ # get full relative file name (relative to cwd)
+ $fname = "$vpath/$fname" if $vpath ne "";
+
+ # remove 'inner' .., e.g. ../x/../y --> ../y
+ # this will also canonize the file names, thus same file same name
+
+ my @flist;
+ foreach (split "/",$fname) {
+ if (scalar(@flist) && $flist[$#flist] ne ".." && $_ eq "..") {
+ pop @flist;
+ } else {
+ push @flist, $_;
+ }
+ }
+
+ return join "/", @flist;
+}
+
+#-------------------------------------------------------------------------------
+
+sub print_help {
+ print "usage: vbomconf file.vbom\n";
+ print " --help this message\n";
+ print " --trace trace recursive processing of vbom's\n";
+ print " --dep_ghdl generate ghdl dependencies for make\n";
+ print " --dep_xst generate xst dependencies for make\n";
+ print " --dep_isim generate isim dependencies for make\n";
+ print " --dep_vsyn generate vsyn dependencies for make\n";
+ print " --ghdl_a generate and execute ghdl -a (analyse)\n";
+ print " --ghdl_a_cmd like ghdl_a, but only print command, no exec\n";
+ print " --ghdl_i generate and execute ghdl -i (inspect)\n";
+ print " --ghdl_i_cmd like ghdl_i, but only print command, no exec\n";
+ print " --ghdl_m generate and execute ghdl -m (make)\n";
+ print " --ghdl_m_cmd like ghdl_m, but only print command, no exec\n";
+ print " --xst_prj generate xst project file\n";
+ print " --isim_prj generate isim project file\n";
+ print " --vsyn_prj generate vivado synthesis project definition\n";
+ print " --ghdl_export=s export all ghdl source files into directory s\n";
+ print " --xst_export=s export all xst source files into directory s\n";
+ print " --isim_export=s export all isim source files into directory s\n";
+ print " --get_top return top level entity name\n";
+ print " --flist list all files touched by vbom for all tags\n";
+}
vbomconv
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: tmuconv
===================================================================
--- tmuconv (nonexistent)
+++ tmuconv (revision 33)
@@ -0,0 +1,920 @@
+#!/usr/bin/perl -w
+# $Id: tmuconv 676 2015-05-09 16:31:54Z mueller $
+#
+# Copyright 2008-2015 by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Version Comment
+# 2010-10-22 334 1.0.9 adapt to ibus V2 signals: req,we,dip->aval,re,we,rmw
+# 2010-06-26 309 1.0.8 add ibimres.cacc/racc handling
+# 2010-04-26 284 1.0.7 add error check for GetOptions
+# 2009-09-19 240 1.0.6 add more VFETCH addr defs; add 2nd DL11 defs
+# 2009-06-04 223 1.0.5 add IIST and PC11 defs
+# 2009-05-03 212 1.0.4 add defs for mmu par/pdr's and some unibus dev's
+# 2008-12-14 177 1.0.3 add -t_ru; use dp_ireg_we_last; add ibus names
+# 2008-11-30 174 1.0.2 SPUSH and VFETCH tags for em cycles; psw in id lines
+# 2008-04-25 138 1.0.1 show ccc/scc for code 000257/000277 in disassembler
+# 2008-04-19 137 1.0 Initial version
+#
+# Current fields in tmu_ofile:
+# clkcycle:d
+# cpu:o
+# dp.pc:o
+# dp.psw:o
+# dp.ireg:o
+# dp.ireg_we:b
+# dp.ireg_we_last:b
+# dp.dsrc:o
+# dp.ddst:o
+# dp.dtmp:o
+# dp.dres:o
+# dp.gpr_adst:o
+# dp.gpr_mode:o
+# dp.gpr_bytop:b
+# dp.gpr_we:b
+# vm.ibmreq.aval:b
+# vm.ibmreq.re:b
+# vm.ibmreq.we:b
+# vm.ibmreq.rmw:b
+# vm.ibmreq.be0:b
+# vm.ibmreq.be1:b
+# vm.ibmreq.cacc:b
+# vm.ibmreq.racc:b
+# vm.ibmreq.addr:o
+# vm.ibmreq.din:o
+# vm.ibsres.ack:b
+# vm.ibsres.busy:b
+# vm.ibsres.dout:o
+# co.cpugo:b
+# co.cpususp:b
+# co.suspint:b
+# co.suspext:b
+# sy.emmreq.req:b
+# sy.emmreq.we:b
+# sy.emmreq.be:b
+# sy.emmreq.cancel:b
+# sy.emmreq.addr:o
+# sy.emmreq.din:o
+# sy.emsres.ack_r:b
+# sy.emsres.ack_w:b
+# sy.emsres.dout:o
+# sy.chit:b
+#
+
+use 5.005; # require Perl 5.005 or higher
+use strict; # require strict checking
+use FileHandle;
+
+use Getopt::Long;
+
+my %opts = ();
+
+GetOptions(\%opts, "help", "dump", "cdump",
+ "t_id", "t_ru", "t_em", "t_ib")
+ or die "bad options";
+
+sub print_help;
+sub do_file;
+sub code2mnemo;
+sub regmod;
+
+my @var_name;
+my @var_type;
+my @var_dec;
+my @var_oct;
+my %name;
+
+my @val_curr_text;
+my @val_curr;
+my @val_last;
+
+my @reg_05 = ("------","------","------","------","------","------", # set 0
+ "------","------","------","------","------","------",); # set 1
+my @reg_sp = ("------","------","------","------"); # ksp,ssp,???,usp
+
+my $ind_dp_pc;
+my $ind_dp_psw;
+my $ind_dp_ireg;
+my $ind_dp_ireg_we;
+my $ind_dp_ireg_we_last;
+my $ind_dp_dres;
+my $ind_dp_gpr_adst;
+my $ind_dp_gpr_mode;
+my $ind_dp_gpr_bytop;
+my $ind_dp_gpr_we;
+
+my $ind_vm_ibmreq_aval;
+my $ind_vm_ibmreq_re;
+my $ind_vm_ibmreq_we;
+my $ind_vm_ibmreq_rmw;
+my $ind_vm_ibmreq_be0;
+my $ind_vm_ibmreq_be1;
+my $ind_vm_ibmreq_cacc;
+my $ind_vm_ibmreq_racc;
+my $ind_vm_ibmreq_addr;
+my $ind_vm_ibmreq_din;
+my $ind_vm_ibsres_ack;
+my $ind_vm_ibsres_busy;
+my $ind_vm_ibsres_dout;
+
+my $ind_sy_emmreq_req;
+my $ind_sy_emmreq_we;
+my $ind_sy_emmreq_be;
+my $ind_sy_emmreq_cancel;
+my $ind_sy_emmreq_addr;
+my $ind_sy_emmreq_din;
+my $ind_sy_emsres_ack_r;
+my $ind_sy_emsres_ack_w;
+my $ind_sy_emsres_dout;
+my $ind_sy_chit;
+
+my @pdp11_opcode_tbl = (
+ {code=>0000000, mask=>0000000, name=>"halt", type=>"0arg"},
+ {code=>0000001, mask=>0000000, name=>"wait", type=>"0arg"},
+ {code=>0000002, mask=>0000000, name=>"rti ", type=>"0arg"},
+ {code=>0000003, mask=>0000000, name=>"bpt ", type=>"0arg"},
+ {code=>0000004, mask=>0000000, name=>"iot ", type=>"0arg"},
+ {code=>0000005, mask=>0000000, name=>"reset",type=>"0arg"},
+ {code=>0000006, mask=>0000000, name=>"rtt ", type=>"0arg"},
+ {code=>0000007, mask=>0000000, name=>"!!mfpt", type=>"0arg"},
+ {code=>0000100, mask=>0000077, name=>"jmp ", type=>"1arg"},
+ {code=>0000200, mask=>0000007, name=>"rts ", type=>"1reg"},
+ {code=>0000230, mask=>0000007, name=>"spl ", type=>"spl"},
+ {code=>0000240, mask=>0000017, name=>"cl", type=>"ccop"},
+ {code=>0000260, mask=>0000017, name=>"se", type=>"ccop"},
+ {code=>0000300, mask=>0000077, name=>"swap", type=>"1arg"},
+ {code=>0000400, mask=>0000377, name=>"br ", type=>"br"},
+ {code=>0001000, mask=>0000377, name=>"bne ", type=>"br"},
+ {code=>0001400, mask=>0000377, name=>"beq ", type=>"br"},
+ {code=>0002000, mask=>0000377, name=>"bge ", type=>"br"},
+ {code=>0002400, mask=>0000377, name=>"blt ", type=>"br"},
+ {code=>0003000, mask=>0000377, name=>"bgt ", type=>"br"},
+ {code=>0003400, mask=>0000377, name=>"ble ", type=>"br"},
+ {code=>0004000, mask=>0000777, name=>"jsr ", type=>"jsr"},
+ {code=>0005000, mask=>0000077, name=>"clr ", type=>"1arg"},
+ {code=>0005100, mask=>0000077, name=>"com ", type=>"1arg"},
+ {code=>0005200, mask=>0000077, name=>"inc ", type=>"1arg"},
+ {code=>0005300, mask=>0000077, name=>"dec ", type=>"1arg"},
+ {code=>0005400, mask=>0000077, name=>"neg ", type=>"1arg"},
+ {code=>0005500, mask=>0000077, name=>"adc ", type=>"1arg"},
+ {code=>0005600, mask=>0000077, name=>"sbc ", type=>"1arg"},
+ {code=>0005700, mask=>0000077, name=>"tst ", type=>"1arg"},
+ {code=>0006000, mask=>0000077, name=>"ror ", type=>"1arg"},
+ {code=>0006100, mask=>0000077, name=>"rol ", type=>"1arg"},
+ {code=>0006200, mask=>0000077, name=>"asr ", type=>"1arg"},
+ {code=>0006300, mask=>0000077, name=>"asl ", type=>"1arg"},
+ {code=>0006400, mask=>0000077, name=>"mark", type=>"mark"},
+ {code=>0006500, mask=>0000077, name=>"mfpi", type=>"1arg"},
+ {code=>0006600, mask=>0000077, name=>"mtpi", type=>"1arg"},
+ {code=>0006700, mask=>0000077, name=>"sxt ", type=>"1arg"},
+ {code=>0007000, mask=>0000077, name=>"!!csm", type=>"1arg"},
+ {code=>0007200, mask=>0000077, name=>"!!tstset",type=>"1arg"},
+ {code=>0007300, mask=>0000077, name=>"!!wrtlck",type=>"1arg"},
+ {code=>0010000, mask=>0007777, name=>"mov ", type=>"2arg"},
+ {code=>0020000, mask=>0007777, name=>"cmp ", type=>"2arg"},
+ {code=>0030000, mask=>0007777, name=>"bit ", type=>"2arg"},
+ {code=>0040000, mask=>0007777, name=>"bic ", type=>"2arg"},
+ {code=>0050000, mask=>0007777, name=>"bis ", type=>"2arg"},
+ {code=>0060000, mask=>0007777, name=>"add ", type=>"2arg"},
+ {code=>0070000, mask=>0000777, name=>"mul ", type=>"rdst"},
+ {code=>0071000, mask=>0000777, name=>"div ", type=>"rdst"},
+ {code=>0072000, mask=>0000777, name=>"ash ", type=>"rdst"},
+ {code=>0073000, mask=>0000777, name=>"ashc", type=>"rdst"},
+ {code=>0074000, mask=>0000777, name=>"xor ", type=>"rdst"},
+ {code=>0077000, mask=>0000777, name=>"sob ", type=>"sob"},
+ {code=>0100000, mask=>0000377, name=>"bpl ", type=>"br"},
+ {code=>0100400, mask=>0000377, name=>"bmi ", type=>"br"},
+ {code=>0101000, mask=>0000377, name=>"bhi ", type=>"br"},
+ {code=>0101400, mask=>0000377, name=>"blos", type=>"br"},
+ {code=>0102000, mask=>0000377, name=>"bvc ", type=>"br"},
+ {code=>0102400, mask=>0000377, name=>"bvs ", type=>"br"},
+ {code=>0103000, mask=>0000377, name=>"bcc ", type=>"br"},
+ {code=>0103400, mask=>0000377, name=>"bcs ", type=>"br"},
+ {code=>0104000, mask=>0000377, name=>"emt ", type=>"trap"},
+ {code=>0104400, mask=>0000377, name=>"trap", type=>"trap"},
+ {code=>0105000, mask=>0000077, name=>"clrb", type=>"1arg"},
+ {code=>0105100, mask=>0000077, name=>"comb", type=>"1arg"},
+ {code=>0105200, mask=>0000077, name=>"incb", type=>"1arg"},
+ {code=>0105300, mask=>0000077, name=>"decb", type=>"1arg"},
+ {code=>0105400, mask=>0000077, name=>"negb", type=>"1arg"},
+ {code=>0105500, mask=>0000077, name=>"adcb", type=>"1arg"},
+ {code=>0105600, mask=>0000077, name=>"sbcb", type=>"1arg"},
+ {code=>0105700, mask=>0000077, name=>"tstb", type=>"1arg"},
+ {code=>0106000, mask=>0000077, name=>"rorb", type=>"1arg"},
+ {code=>0106100, mask=>0000077, name=>"rolb", type=>"1arg"},
+ {code=>0106200, mask=>0000077, name=>"asrb", type=>"1arg"},
+ {code=>0106300, mask=>0000077, name=>"aslb", type=>"1arg"},
+ {code=>0106400, mask=>0000077, name=>"!!mtps", type=>"1arg"},
+ {code=>0106500, mask=>0000077, name=>"mfpd", type=>"1arg"},
+ {code=>0106600, mask=>0000077, name=>"mtpd", type=>"1arg"},
+ {code=>0106700, mask=>0000077, name=>"!!mfps", type=>"1arg"},
+ {code=>0110000, mask=>0007777, name=>"movb", type=>"2arg"},
+ {code=>0120000, mask=>0007777, name=>"cmpb", type=>"2arg"},
+ {code=>0130000, mask=>0007777, name=>"bitb", type=>"2arg"},
+ {code=>0140000, mask=>0007777, name=>"bicb", type=>"2arg"},
+ {code=>0150000, mask=>0007777, name=>"bisb", type=>"2arg"},
+ {code=>0160000, mask=>0007777, name=>"sub ", type=>"2arg"},
+ {code=>0170000, mask=>0000000, name=>"!!cfcc", type=>"0arg"},
+ {code=>0170001, mask=>0000000, name=>"!!setf", type=>"0arg"},
+ {code=>0170011, mask=>0000000, name=>"!!setd", type=>"0arg"},
+ {code=>0170002, mask=>0000000, name=>"!!seti", type=>"0arg"},
+ {code=>0170012, mask=>0000000, name=>"!!setl", type=>"0arg"},
+ {code=>0170100, mask=>0000077, name=>"!!ldfps",type=>"1fpp"},
+ {code=>0170200, mask=>0000077, name=>"!!stfps",type=>"1fpp"},
+ {code=>0170300, mask=>0000077, name=>"!!stst", type=>"1fpp"},
+ {code=>0170400, mask=>0000077, name=>"!!clrf", type=>"1fpp"},
+ {code=>0170500, mask=>0000077, name=>"!!tstf", type=>"1fpp"},
+ {code=>0170600, mask=>0000077, name=>"!!absf", type=>"1fpp"},
+ {code=>0170700, mask=>0000077, name=>"!!negf", type=>"1fpp"},
+ {code=>0171000, mask=>0000377, name=>"!!mulf", type=>"rfpp"},
+ {code=>0171400, mask=>0000377, name=>"!!modf", type=>"rfpp"},
+ {code=>0172000, mask=>0000377, name=>"!!addf", type=>"rfpp"},
+ {code=>0172400, mask=>0000377, name=>"!!ldf", type=>"rfpp"},
+ {code=>0173000, mask=>0000377, name=>"!!subf", type=>"rfpp"},
+ {code=>0173400, mask=>0000377, name=>"!!cmpf", type=>"rfpp"},
+ {code=>0174000, mask=>0000377, name=>"!!stf", type=>"rfpp"},
+ {code=>0174400, mask=>0000377, name=>"!!divf", type=>"rfpp"},
+ {code=>0175000, mask=>0000377, name=>"!!stexp",type=>"rfpp"},
+ {code=>0175400, mask=>0000377, name=>"!!stcif",type=>"rfpp"},
+ {code=>0176000, mask=>0000377, name=>"!!stcfd",type=>"rfpp"},
+ {code=>0176400, mask=>0000377, name=>"!!ldexp",type=>"rfpp"},
+ {code=>0177000, mask=>0000377, name=>"!!ldcif",type=>"rfpp"},
+ {code=>0177400, mask=>0000377, name=>"!!ldcdf",type=>"rfpp"}
+ );
+
+my %pdp11_regs = ( # use simh naming convention
+ 177776=> "psw",
+ 177774=> "stklim",
+ 177772=> "pirq",
+ 177770=> "mbrk",
+ 177766=> "cpuerr",
+ 177764=> "sysid",
+ 177600=> "uipdr0",
+ 177602=> "uipdr1",
+ 177604=> "uipdr2",
+ 177606=> "uipdr3",
+ 177610=> "uipdr4",
+ 177612=> "uipdr5",
+ 177614=> "uipdr6",
+ 177616=> "uipdr7",
+ 177620=> "udpdr0",
+ 177622=> "udpdr1",
+ 177624=> "udpdr2",
+ 177626=> "udpdr3",
+ 177630=> "udpdr4",
+ 177632=> "udpdr5",
+ 177634=> "udpdr6",
+ 177636=> "udpdr7",
+ 177640=> "uipar0",
+ 177642=> "uipar1",
+ 177644=> "uipar2",
+ 177646=> "uipar3",
+ 177650=> "uipar4",
+ 177652=> "uipar5",
+ 177654=> "uipar6",
+ 177656=> "uipar7",
+ 177660=> "udpar0",
+ 177662=> "udpar1",
+ 177664=> "udpar2",
+ 177666=> "udpar3",
+ 177670=> "udpar4",
+ 177672=> "udpar5",
+ 177674=> "udpar6",
+ 177676=> "udpar7",
+ 177576=> "mmr2",
+ 177574=> "mmr1",
+ 177572=> "mmr0",
+ 177570=> "sdreg", # not a simh name !!
+ 177560=> "ti.csr",
+ 177562=> "ti.buf",
+ 177564=> "to.csr",
+ 177566=> "to.buf",
+ 177550=> "pr.csr",
+ 177552=> "pr.buf",
+ 177554=> "pp.csr",
+ 177556=> "pp.buf",
+ 177546=> "kl.csr",
+ 177514=> "lp.csr",
+ 177516=> "lp.buf",
+ 177500=> "ii.acr",
+ 177502=> "ii.adr",
+ 177400=> "rk.ds ",
+ 177402=> "rk.er ",
+ 177404=> "rk.cs ",
+ 177406=> "rk.wc ",
+ 177410=> "rk.ba ",
+ 177412=> "rk.da ",
+ 177414=> "rk.mr ",
+ 177416=> "rk.db ",
+ 177060=> "xor.cs", # XOR Tester
+ 176700=> "rpa.cs1",
+ 176702=> "rpa.wc ",
+ 176704=> "rpa.ba ",
+ 176706=> "rpa.da ",
+ 176710=> "rpa.cs2",
+ 176712=> "rpa.ds ",
+ 176714=> "rpa.er1",
+ 176716=> "rpa.as ",
+ 176720=> "rpa.la ",
+ 176722=> "rpa.db ",
+ 176724=> "rpa.mr1",
+ 176726=> "rpa.dt ",
+ 176730=> "rpa.sn ",
+ 176732=> "rpa.of ",
+ 176734=> "rpa.dc ",
+ 176736=> "rpa.m13",
+ 176740=> "rpa.m14",
+ 176742=> "rpa.m15",
+ 176744=> "rpa.ec1",
+ 176746=> "rpa.ec2",
+ 176750=> "rpa.bae",
+ 176752=> "rpa.cs3",
+ 176500=> "ti2.cs",
+ 176502=> "ti2.bu",
+ 176504=> "to2.cs",
+ 176506=> "to2.bu",
+ 174400=> "rl.cs ",
+ 174402=> "rl.ba ",
+ 174404=> "rl.da ",
+ 174406=> "rl.mp ",
+ 172540=> "kp.csr",
+ 172542=> "kp.buf",
+ 172544=> "kp.cnt",
+ 172520=> "tm.mts",
+ 172522=> "tm.mtc",
+ 172524=> "tm.brc",
+ 172526=> "tm.cma",
+ 172530=> "tm.mtd",
+ 172532=> "tm.rda",
+ 172516=> "mmr3",
+ 172200=> "sipdr0",
+ 172202=> "sipdr1",
+ 172204=> "sipdr2",
+ 172206=> "sipdr3",
+ 172210=> "sipdr4",
+ 172212=> "sipdr5",
+ 172214=> "sipdr6",
+ 172216=> "sipdr7",
+ 172220=> "sdpdr0",
+ 172222=> "sdpdr1",
+ 172224=> "sdpdr2",
+ 172226=> "sdpdr3",
+ 172230=> "sdpdr4",
+ 172232=> "sdpdr5",
+ 172234=> "sdpdr6",
+ 172236=> "sdpdr7",
+ 172240=> "sipar0",
+ 172242=> "sipar1",
+ 172244=> "sipar2",
+ 172246=> "sipar3",
+ 172250=> "sipar4",
+ 172252=> "sipar5",
+ 172254=> "sipar6",
+ 172256=> "sipar7",
+ 172260=> "sdpar0",
+ 172262=> "sdpar1",
+ 172264=> "sdpar2",
+ 172266=> "sdpar3",
+ 172270=> "sdpar4",
+ 172272=> "sdpar5",
+ 172274=> "sdpar6",
+ 172276=> "sdpar7",
+ 172300=> "kipdr0",
+ 172302=> "kipdr1",
+ 172304=> "kipdr2",
+ 172306=> "kipdr3",
+ 172310=> "kipdr4",
+ 172312=> "kipdr5",
+ 172314=> "kipdr6",
+ 172316=> "kipdr7",
+ 172320=> "kdpdr0",
+ 172322=> "kdpdr1",
+ 172324=> "kdpdr2",
+ 172326=> "kdpdr3",
+ 172330=> "kdpdr4",
+ 172332=> "kdpdr5",
+ 172334=> "kdpdr6",
+ 172336=> "kdpdr7",
+ 172340=> "kipar0",
+ 172342=> "kipar1",
+ 172344=> "kipar2",
+ 172346=> "kipar3",
+ 172350=> "kipar4",
+ 172352=> "kipar5",
+ 172354=> "kipar6",
+ 172356=> "kipar7",
+ 172360=> "kdpar0",
+ 172362=> "kdpar1",
+ 172364=> "kdpar2",
+ 172366=> "kdpar3",
+ 172370=> "kdpar4",
+ 172372=> "kdpar5",
+ 172374=> "kdpar6",
+ 172376=> "kdpar7",
+ 160100=> "dz.csr",
+ 160102=> "dz.mp2",
+ 160104=> "dz.tcr",
+ 160106=> "dz.mp6"
+);
+
+autoflush STDOUT 1 if (-p STDOUT); # autoflush if output into pipe
+
+if (exists $opts{help}) {
+ print_help;
+ exit 0;
+}
+
+foreach my $file (@ARGV) {
+ do_file($file);
+}
+
+
+#-------------------------------------------------------------------------------
+
+sub do_file {
+ my ($file) = @_;
+
+ open IFILE,"<$file" or die "failed to open $file";
+
+ my $idec_cyc = 0;
+ my $change_cyc = 0;
+ my $emreq_cyc = 0;
+ my $emreq_str = "";
+ my $ibreq_cyc = 0;
+ my $ibreq_typ = "";
+ my $ibreq_str = "";
+ my $ibreq_nam = "";
+
+ my $emcurr_we = 0; # curr em write enable (or undef)
+ my $emcurr_addr = undef; # curr em address
+ my $emlast_we = 0; # prev em write enable (or undef)
+ my $emlast_addr = undef; # prev em address
+
+ while () {
+ chomp;
+ if (/^#\s+/) {
+ @var_name = ();
+ @var_type = ();
+ my $dsc_str = $';
+ my @dsc_list = split /\s+/,$dsc_str;
+ foreach my $dsc (@dsc_list) {
+ if ($dsc =~ /^(.*):([bdo])$/) {
+ my $ind = scalar(@var_name);
+ $name{$1} = {ind=>$ind,
+ typ=>$2};
+ push @var_name, $1;
+ push @var_type, $2;
+ push @var_dec, $ind if $2 eq "d";
+ push @var_oct, $ind if $2 eq "o";
+ } else {
+ print "tmuconv-E: bad descriptor $dsc\n";
+ }
+ }
+
+ $ind_dp_pc = $name{'dp.pc'}->{ind};
+ $ind_dp_psw = $name{'dp.psw'}->{ind};
+ $ind_dp_ireg = $name{'dp.ireg'}->{ind};
+ $ind_dp_ireg_we = $name{'dp.ireg_we'}->{ind};
+ $ind_dp_ireg_we_last = $name{'dp.ireg_we_last'}->{ind};
+ $ind_dp_dres = $name{'dp.dres'}->{ind};
+ $ind_dp_gpr_adst = $name{'dp.gpr_adst'}->{ind};
+ $ind_dp_gpr_mode = $name{'dp.gpr_mode'}->{ind};
+ $ind_dp_gpr_bytop = $name{'dp.gpr_bytop'}->{ind};
+ $ind_dp_gpr_we = $name{'dp.gpr_we'}->{ind};
+
+ $ind_vm_ibmreq_aval = $name{'vm.ibmreq.aval'}->{ind};
+ $ind_vm_ibmreq_re = $name{'vm.ibmreq.re'}->{ind};
+ $ind_vm_ibmreq_we = $name{'vm.ibmreq.we'}->{ind};
+ $ind_vm_ibmreq_rmw = $name{'vm.ibmreq.rmw'}->{ind};
+ $ind_vm_ibmreq_be0 = $name{'vm.ibmreq.be0'}->{ind};
+ $ind_vm_ibmreq_be1 = $name{'vm.ibmreq.be1'}->{ind};
+ $ind_vm_ibmreq_cacc = $name{'vm.ibmreq.cacc'}->{ind};
+ $ind_vm_ibmreq_racc = $name{'vm.ibmreq.racc'}->{ind};
+ $ind_vm_ibmreq_addr = $name{'vm.ibmreq.addr'}->{ind};
+ $ind_vm_ibmreq_din = $name{'vm.ibmreq.din'}->{ind};
+ $ind_vm_ibsres_ack = $name{'vm.ibsres.ack'}->{ind};
+ $ind_vm_ibsres_busy = $name{'vm.ibsres.busy'}->{ind};
+ $ind_vm_ibsres_dout = $name{'vm.ibsres.dout'}->{ind};
+
+ $ind_sy_emmreq_req = $name{'sy.emmreq.req'}->{ind};
+ $ind_sy_emmreq_we = $name{'sy.emmreq.we'}->{ind};
+ $ind_sy_emmreq_be = $name{'sy.emmreq.be'}->{ind};
+ $ind_sy_emmreq_cancel = $name{'sy.emmreq.cancel'}->{ind};
+ $ind_sy_emmreq_addr = $name{'sy.emmreq.addr'}->{ind};
+ $ind_sy_emmreq_din = $name{'sy.emmreq.din'}->{ind};
+ $ind_sy_emsres_ack_r = $name{'sy.emsres.ack_r'}->{ind};
+ $ind_sy_emsres_ack_w = $name{'sy.emsres.ack_w'}->{ind};
+ $ind_sy_emsres_dout = $name{'sy.emsres.dout'}->{ind};
+ $ind_sy_chit = $name{'sy.chit'}->{ind};
+
+ } else {
+ @val_last = @val_curr;
+ my $notfirst = scalar(@val_last) > 0;
+
+ $_ =~ s/^\s*//;
+ $_ =~ s/\s*$//;
+ @val_curr = split /\s+/,$_;
+ if (scalar(@val_curr) != scalar(@var_name)) {
+ printf "tmuconv-E: value list length mismatch, seen %d, expected %d\n",
+ scalar(@val_curr), scalar(@var_name);
+ for (my $i=0; $i>11 & 01;
+ $ru_str = sprintf "%o %o%o %6.6o", $bytop, $rset, $adst, $dres;
+ $ru_str .= " ";
+ if ($adst eq "7") {
+ $ru_str .= "pc";
+ } elsif ($adst eq "6") {
+ $reg_sp[$mode] = sprintf "%6.6o",$dres;
+ $ru_str .= $reg_sp[0];
+ $ru_str .= ($mode == 0) ? "*" : " ";
+ $ru_str .= $reg_sp[1];
+ $ru_str .= ($mode == 1) ? "*" : " ";
+ $ru_str .= $reg_sp[3];
+ $ru_str .= ($mode == 3) ? "*" : " ";
+ $ru_str .= " ksp" if $mode eq "0";
+ $ru_str .= " ssp" if $mode eq "1";
+ $ru_str .= " usp" if $mode eq "3";
+ } else {
+ my $rbase = ($rset==0) ? 0 : 6;
+ $reg_05[$rbase+$adst] = sprintf "%6.6o",$dres;
+ for (my $i=0; $i<6; $i++) {
+ $ru_str .= $reg_05[$rbase+$i];
+ $ru_str .= ($adst==$i) ? "*" : " ";
+ }
+ $ru_str .= sprintf " r%o%o", $rset, $adst;
+ }
+ }
+ }
+#
+# handle t_em
+# uses cycles with sy_emmreq_req = '1'
+# sy_emsres_ack_r = '1'
+# sy_emsres_ack_w = '1'
+# sy_emsreq_cancel = '1'
+#
+ if (exists $opts{t_em}) {
+ if ($val_curr[$ind_sy_emmreq_req]) {
+ $emreq_cyc = $cyc_curr;
+ $emreq_str = sprintf "%s %s %8.8o",
+ ($val_curr[$ind_sy_emmreq_we] ? "w" : "r"),
+ $val_curr[$ind_sy_emmreq_be],
+ $val_curr[$ind_sy_emmreq_addr];
+ $emcurr_we = $val_curr[$ind_sy_emmreq_we];
+ $emcurr_addr = $val_curr[$ind_sy_emmreq_addr];
+ if ($emcurr_we) {
+ $emreq_str .= sprintf " %6.6o", $val_curr[$ind_sy_emmreq_din];
+ } else {
+ $emreq_str .= " " x 7;
+ }
+ }
+ if ($val_curr[$ind_sy_emsres_ack_r] ||
+ $val_curr[$ind_sy_emsres_ack_w] ||
+ $val_curr[$ind_sy_emmreq_cancel]) {
+ $emres_str = sprintf "%s%s%s%s",
+ $val_curr[$ind_sy_emmreq_cancel],
+ $val_curr[$ind_sy_emsres_ack_r],
+ $val_curr[$ind_sy_emsres_ack_w],
+ $val_curr[$ind_sy_chit];
+ if ($val_curr[$ind_sy_emmreq_cancel]) {
+ $emreq_str .= " cancel";
+ $emcurr_we = undef;
+ } else {
+ if ($val_curr[$ind_sy_emsres_ack_r]) {
+ $emreq_str .= sprintf " %6.6o", $val_curr[$ind_sy_emsres_dout];
+ } else {
+ $emreq_str .= " " x 7;
+ }
+ if (defined $emlast_we && $emcurr_we == $emlast_we) {
+ if ($emcurr_we && $emcurr_addr == $emlast_addr-2) {
+ $emtyp_str = "SPUSH";
+ } elsif ((not $emcurr_we) && $emcurr_addr == $emlast_addr+2 &&
+ $emcurr_addr < 0400 && ($emcurr_addr % 04) == 02) {
+ $emtyp_str = "VFETCH";
+ $emtyp_str .= " 004 ill.inst" if ($emlast_addr == 0004);
+ $emtyp_str .= " 010 res.inst" if ($emlast_addr == 0010);
+ $emtyp_str .= " 014 BPT" if ($emlast_addr == 0014);
+ $emtyp_str .= " 020 IOT" if ($emlast_addr == 0020);
+ $emtyp_str .= " 030 EMT" if ($emlast_addr == 0030);
+ $emtyp_str .= " 034 TRAP" if ($emlast_addr == 0034);
+ $emtyp_str .= " 060 DL11-TTI" if ($emlast_addr == 0060);
+ $emtyp_str .= " 064 DL11-TTO" if ($emlast_addr == 0064);
+ $emtyp_str .= " 070 PC11-PTR" if ($emlast_addr == 0070);
+ $emtyp_str .= " 074 PC11-PTP" if ($emlast_addr == 0074);
+ $emtyp_str .= " 100 KW11-L" if ($emlast_addr == 0100);
+ $emtyp_str .= " 104 KW11-P" if ($emlast_addr == 0104);
+ $emtyp_str .= " 160 RL11" if ($emlast_addr == 0160);
+ $emtyp_str .= " 200 LP11" if ($emlast_addr == 0200);
+ $emtyp_str .= " 220 RK11" if ($emlast_addr == 0220);
+ $emtyp_str .= " 224 TM11" if ($emlast_addr == 0224);
+ $emtyp_str .= " 240 PIRQ" if ($emlast_addr == 0240);
+ $emtyp_str .= " 244 FPP exp" if ($emlast_addr == 0244);
+ $emtyp_str .= " 250 MMU trap" if ($emlast_addr == 0250);
+ $emtyp_str .= " 260 IIST" if ($emlast_addr == 0260);
+ $emtyp_str .= " 300 DL11-2-TTI" if ($emlast_addr == 0300);
+ $emtyp_str .= " 304 DL11-2-TTO" if ($emlast_addr == 0304);
+ }
+ }
+ }
+ $emlast_we = $emcurr_we;
+ $emlast_addr = $emcurr_addr;
+ }
+ }
+#
+# handle t_ib
+# uses cycles with sy_ibmreq_re = '1' or sy_ibmreq_we = '1'
+# sy_ibsres_ack = '1'
+# vm_ibsres_busy '1' -> '0' transition
+#
+ if (exists $opts{t_ib}) {
+ if ($val_curr[$ind_vm_ibmreq_re] || $val_curr[$ind_vm_ibmreq_we]) {
+ my $addr_str = sprintf "%6.6o", $val_curr[$ind_vm_ibmreq_addr];
+ $ibreq_cyc = $cyc_curr;
+ $ibreq_typ = sprintf "%s%s",
+ ($val_curr[$ind_vm_ibmreq_cacc] ? "c" : "-"),
+ ($val_curr[$ind_vm_ibmreq_racc] ? "r" : "-");
+ $ibreq_str = sprintf "%s%s%s%s %s",
+ ($val_curr[$ind_vm_ibmreq_we] ? "w" : "r"),
+ ($val_curr[$ind_vm_ibmreq_rmw] ? "m" : " "),
+ $val_curr[$ind_vm_ibmreq_be1],
+ $val_curr[$ind_vm_ibmreq_be0],
+ $addr_str;
+ $ibreq_we = $val_curr[$ind_vm_ibmreq_we];
+ $ibreq_act = 1;
+ if ($ibreq_we) {
+ $ibreq_str .= sprintf " %6.6o", $val_curr[$ind_vm_ibmreq_din];
+ } else {
+ $ibreq_str .= " " x 7;
+ }
+ $ibreq_nam = $pdp11_regs{$addr_str};
+ $ibreq_nam = "" if not defined $ibreq_nam;
+ }
+
+ if ($val_curr[$ind_vm_ibsres_ack]) {
+ $ibreq_act = 0;
+ $ibres_str .= sprintf " %s", $val_curr[$ind_vm_ibsres_ack];
+ if (not $ibreq_we) {
+ $ibreq_str .= sprintf " %6.6o", $val_curr[$ind_vm_ibsres_dout];
+ } else {
+ $ibreq_str .= " " x 7;
+ }
+ }
+
+ if ($ibreq_act && $val_curr[$ind_vm_ibsres_busy]==0) {
+ $ibres_str .= "no ACK, no BUSY";
+ $ibreq_act = 0;
+ }
+ }
+
+ print "$cyc_str id $id_str\n" if $id_str;
+ print "$cyc_str ru $ru_str\n" if $ru_str;
+ if ($emres_str) {
+ printf "$cyc_str em $emreq_str $emres_str (%d) $emtyp_str\n",
+ $cyc_curr-$emreq_cyc;
+ }
+ if ($ibres_str) {
+ printf "$cyc_str ib %s $ibreq_str $ibres_str (%d) $ibreq_nam\n",
+ $ibreq_typ, $cyc_curr-$ibreq_cyc;
+ }
+ }
+ }
+
+ close IFILE;
+}
+
+#-------------------------------------------------------------------------------
+
+sub code2mnemo {
+ my ($code) = @_;
+
+ foreach my $ele (@pdp11_opcode_tbl) {
+ if (($code & (~($ele->{mask})) ) == $ele->{code}) {
+ my $name = $ele->{name};
+ my $type = $ele->{type};
+ my $str = $name;
+ if ($type eq "0arg") {
+ return $name;
+
+ } elsif ($type eq "1arg" or $type eq "1fpp") {
+ my $dst = $code & 077;
+ my $dst_str = regmod($dst);
+ return "$name $dst_str";
+
+ } elsif ($type eq "2arg") {
+ my $src = ($code>>6) & 077;
+ my $dst = $code & 077;
+ my $src_str = regmod($src);
+ my $dst_str = regmod($dst);
+ return "$name $src_str,$dst_str";
+
+ } elsif ($type eq "rdst") {
+ my $reg = ($code>>6) & 07;
+ my $src = $code & 077;
+ my $src_str = regmod($src);
+ return "$name $src_str,r$reg";
+
+ } elsif ($type eq "1reg") {
+ my $reg = $code & 07;
+ my $reg_str = "r$reg";
+ $reg_str = "sp" if $reg == 6;
+ $reg_str = "pc" if $reg == 7;
+ return "$name $reg_str";
+
+ } elsif ($type eq "br") {
+ my $off = $code & 0177;
+ my $sign = "+";
+ if ($code & 0200) {
+ $off = -(((~$off) & 0177)+1);
+ $sign = "-";
+ }
+ return sprintf "$name .%s%d.", $sign, abs(2*$off);
+
+ } elsif ($type eq "sob") {
+ my $reg = ($code>>6) & 07;
+ my $off = $code & 077;
+ return sprintf "$name r%d,.-%d.", $reg, 2*$off;
+
+ } elsif ($type eq "trap") {
+ my $off = $code & 0377;
+ return sprintf "$name %3.3o", $off;
+
+ } elsif ($type eq "spl") {
+ my $off = $code & 07;
+ return sprintf "$name %d", $off;
+
+ } elsif ($type eq "ccop") {
+ my $cc = $code & 017;
+ return "nop" if ($cc == 0);
+ return "ccc" if ($code == 0257);
+ return "scc" if ($code == 0277);
+ my $str = "";
+ my $del = "";
+ if ($code & 010) { $str .= $del . $name . "n", $del = "+" }
+ if ($code & 004) { $str .= $del . $name . "z", $del = "+" }
+ if ($code & 002) { $str .= $del . $name . "v", $del = "+" }
+ if ($code & 001) { $str .= $del . $name . "c", $del = "+" }
+ return $str;
+
+ } elsif ($type eq "jsr") {
+ my $reg = ($code>>6) & 07;
+ my $dst = $code & 077;
+ my $dst_str = regmod($dst);
+ return "$name r$reg,$dst_str";
+
+ } elsif ($type eq "mark") {
+ my $off = $code & 077;
+ return sprintf "$name %3.3o", $off;
+
+ } elsif ($type eq "rfpp") {
+ my $reg = ($code>>6) & 03;
+ my $dst = $code & 077;
+ my $dst_str = regmod($dst,"f");
+ return "$name f$reg,$dst_str";
+
+ } else {
+ return "?type?";
+ }
+ }
+ }
+ return "=inval=";
+}
+
+#-------------------------------------------------------------------------------
+sub regmod {
+ my ($regmod,$pref) = @_;
+ my $mod = ($regmod>>3) & 07;
+ my $reg = $regmod & 07;
+
+ $pref = "r" if not defined $pref or $reg>5;
+
+ my $reg_str = "r$reg";
+ $reg_str = "sp" if $reg == 6;
+ $reg_str = "pc" if $reg == 7;
+
+ if ($mod == 0) { # mode 0: Rx { Fx for float }
+ $reg_str = "f$reg" if defined $pref && $pref eq "f" && $reg<=5;
+ return $reg_str;
+ } elsif ($mod == 1) { # mode 1: (Rx)
+ return "($reg_str)";
+ } elsif ($mod == 2 || $mod == 3) { # mode 2/3: (Rx)+ @(Rx)+
+ my $ind = ($mod == 3) ? "@" : "";
+ if ($reg != 7) { # if reg != pc
+ return "$ind($reg_str)+";
+ } else { # if reg == pc
+ my $str = sprintf "$ind#nnn"; # 27 -> #nnn; 37 -> @#nnn
+ return $str;
+ }
+ } elsif ($mod == 4 || $mod == 5) { # mode 4/5: -(Rx) @-(Rx)
+ my $ind = ($mod == 5) ? "@" : "";
+ return "$ind-($reg_str)";
+ } elsif ($mod == 6 || $mod == 7) { # mode 6/7: nn(Rx) @nn(Rx)
+ my $ind = ($mod == 7) ? "@" : "";
+ return "${ind}nnn($reg_str)";
+ }
+}
+
+#-------------------------------------------------------------------------------
+
+sub print_help {
+ print "usage: tmuconf file\n";
+ print " --help this message\n";
+ print " --dump dump all information\n";
+ print " --cdump dump only changes relative to prev cycle\n";
+ print " --t_id trace instruction decodes\n";
+ print " --t_ru trace register updates\n";
+ print " --t_em trace em transactions\n";
+ print " --t_ib trace ib transactions\n";
+}
tmuconv
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: asm-11
===================================================================
--- asm-11 (nonexistent)
+++ asm-11 (revision 33)
@@ -0,0 +1,2471 @@
+#!/usr/bin/perl -w
+# $Id: asm-11 659 2015-03-22 23:15:51Z mueller $
+#
+# Copyright 2013-2014 by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Version Comment
+# 2014-07-26 575 1.0.3 add 'call' and 'return' to pst (as in macro-11)
+# 2013-04-07 503 1.0.2 list dot for .even,.dot,.blkb,.blkw
+# 2013-04-01 502 1.0.1 BUGFIX: -2(r0),@-2(r0) was broken, parser fixed
+# add -lsm (lsmem format) output; add implicit .word
+# 2013-03-29 501 1.0 Initial version
+# 2013-03-22 498 0.5 Second draft (functional, but limited...)
+# 2013-03-07 496 0.1 First draft
+#
+
+use 5.10.0; # require Perl 5.10 or higher
+use strict; # require strict checking
+use FileHandle;
+
+use Getopt::Long;
+
+use constant TMASK_STRING => 0x0001;
+use constant TMASK_STRINGEXP => 0x0002;
+
+my %opts = ();
+
+GetOptions(\%opts, "help",
+ "tpass1", "tpass2",
+ "dsym1", "dsym2",
+ "ttoken", "tparse", "temit", "tout",
+ "I=s@",
+ "lst", "olst=s",
+ "lda", "olda=s",
+ "cof", "ocof=s",
+ "lsm", "olsm=s"
+ )
+ or exit 1;
+
+unshift @{$opts{I}}, "."; # ./ is first in include path
+push @{$opts{I}}, "$ENV{RETROBASE}/tools/asm-11" if defined $ENV{RETROBASE};
+
+sub create_fname;
+sub read_file;
+sub parse_line;
+sub walign;
+sub add_err;
+sub prt_err;
+sub setdot;
+sub incdot;
+sub getdot;
+sub setsym;
+sub getsym;
+sub lst_checkmdef;
+sub eval_exp;
+sub check_llbl;
+sub check_reg;
+sub check_token;
+sub pushback_token;
+sub get_token;
+sub get_token1;
+sub to_rad50;
+sub pass2;
+sub pass2_out;
+sub pass2_lst_beg;
+sub pass2_lst_end;
+sub pass2_lst_line;
+sub out_w;
+sub out_b;
+sub out_opcode;
+sub out_opcode_n;
+sub out_opcode_o;
+sub out_opdata;
+sub emitw;
+sub emitb;
+sub write_lda;
+sub write_cof;
+sub write_lsm;
+sub dump_rl;
+sub dump_sym;
+sub prt76o;
+sub prt43o;
+sub save66o;
+sub savestr;
+sub savestr1;
+sub print_help;
+
+# Permanant symbol table
+my %pst = (
+# directives
+ '.include' => {typ=>'dir'}, #
+ '.word' => {typ=>'dir'}, #
+ '.byte' => {typ=>'dir'}, #
+ '.blkw' => {typ=>'dir'}, #
+ '.blkb' => {typ=>'dir'}, #
+ '.ascii' => {typ=>'dir'}, #
+ '.asciz' => {typ=>'dir'}, #
+ '.even' => {typ=>'dir'}, #
+ '.odd' => {typ=>'dir'}, #
+ '.asect' => {typ=>'dir'}, #
+ '.end' => {typ=>'dir'}, #
+#register defs
+ 'r0' => {typ=>'reg', val=>0},
+ 'r1' => {typ=>'reg', val=>1},
+ 'r2' => {typ=>'reg', val=>2},
+ 'r3' => {typ=>'reg', val=>3},
+ 'r4' => {typ=>'reg', val=>4},
+ 'r5' => {typ=>'reg', val=>5},
+ 'sp' => {typ=>'reg', val=>6},
+ 'pc' => {typ=>'reg', val=>7},
+#opcodes
+ 'halt' => {typ=>'op', val=>0000000, fmt=>'-' },
+ 'wait' => {typ=>'op', val=>0000001, fmt=>'-' },
+ 'rti' => {typ=>'op', val=>0000002, fmt=>'-' },
+ 'bpt' => {typ=>'op', val=>0000003, fmt=>'-' },
+ 'iot' => {typ=>'op', val=>0000004, fmt=>'-' },
+ 'reset' => {typ=>'op', val=>0000005, fmt=>'-' },
+ 'rtt' => {typ=>'op', val=>0000006, fmt=>'-' },
+ 'mfpt' => {typ=>'op', val=>0000007, fmt=>'-' },
+ 'jmp' => {typ=>'op', val=>0000100, fmt=>'g' },
+ 'rts' => {typ=>'op', val=>0000200, fmt=>'r' },
+ 'return' => {typ=>'op', val=>0000207, fmt=>'-' }, # alias for rts pc
+ 'spl' => {typ=>'op', val=>0000230, fmt=>'n3' },
+ 'nop' => {typ=>'op', val=>0000240, fmt=>'-' },
+ 'clc' => {typ=>'op', val=>0000241, fmt=>'-' },
+ 'clv' => {typ=>'op', val=>0000242, fmt=>'-' },
+ 'clz' => {typ=>'op', val=>0000244, fmt=>'-' },
+ 'cln' => {typ=>'op', val=>0000250, fmt=>'-' },
+ 'ccc' => {typ=>'op', val=>0000257, fmt=>'-' },
+ 'sec' => {typ=>'op', val=>0000261, fmt=>'-' },
+ 'sev' => {typ=>'op', val=>0000262, fmt=>'-' },
+ 'sez' => {typ=>'op', val=>0000264, fmt=>'-' },
+ 'sen' => {typ=>'op', val=>0000270, fmt=>'-' },
+ 'scc' => {typ=>'op', val=>0000277, fmt=>'-' },
+ 'swab' => {typ=>'op', val=>0000300, fmt=>'g' },
+ 'br' => {typ=>'op', val=>0000400, fmt=>'s8' },
+ 'bne' => {typ=>'op', val=>0001000, fmt=>'s8' },
+ 'beq' => {typ=>'op', val=>0001400, fmt=>'s8' },
+ 'bge' => {typ=>'op', val=>0002000, fmt=>'s8' },
+ 'blt' => {typ=>'op', val=>0002400, fmt=>'s8' },
+ 'bgt' => {typ=>'op', val=>0003000, fmt=>'s8' },
+ 'ble' => {typ=>'op', val=>0003400, fmt=>'s8' },
+ 'jsr' => {typ=>'op', val=>0004000, fmt=>'rg' },
+ 'call' => {typ=>'op', val=>0004700, fmt=>'g' }, # alias for jsr pc,
+ 'clr' => {typ=>'op', val=>0005000, fmt=>'g' },
+ 'com' => {typ=>'op', val=>0005100, fmt=>'g' },
+ 'inc' => {typ=>'op', val=>0005200, fmt=>'g' },
+ 'dec' => {typ=>'op', val=>0005300, fmt=>'g' },
+ 'neg' => {typ=>'op', val=>0005400, fmt=>'g' },
+ 'adc' => {typ=>'op', val=>0005500, fmt=>'g' },
+ 'sbc' => {typ=>'op', val=>0005600, fmt=>'g' },
+ 'tst' => {typ=>'op', val=>0005700, fmt=>'g' },
+ 'ror' => {typ=>'op', val=>0006000, fmt=>'g' },
+ 'rol' => {typ=>'op', val=>0006100, fmt=>'g' },
+ 'asr' => {typ=>'op', val=>0006200, fmt=>'g' },
+ 'asl' => {typ=>'op', val=>0006300, fmt=>'g' },
+ 'mark' => {typ=>'op', val=>0006400, fmt=>'n6' },
+ 'mfpi' => {typ=>'op', val=>0006500, fmt=>'g' },
+ 'mtpi' => {typ=>'op', val=>0006600, fmt=>'g' },
+ 'sxt' => {typ=>'op', val=>0006700, fmt=>'g' },
+ 'csm' => {typ=>'op', val=>0007000, fmt=>'g' },
+ 'tstset' => {typ=>'op', val=>0007200, fmt=>'g' },
+ 'wrtlck' => {typ=>'op', val=>0007300, fmt=>'g' },
+ 'mov' => {typ=>'op', val=>0010000, fmt=>'gg' },
+ 'cmp' => {typ=>'op', val=>0020000, fmt=>'gg' },
+ 'bit' => {typ=>'op', val=>0030000, fmt=>'gg' },
+ 'bic' => {typ=>'op', val=>0040000, fmt=>'gg' },
+ 'bis' => {typ=>'op', val=>0050000, fmt=>'gg' },
+ 'add' => {typ=>'op', val=>0060000, fmt=>'gg' },
+ 'mul' => {typ=>'op', val=>0070000, fmt=>'gr' },
+ 'div' => {typ=>'op', val=>0071000, fmt=>'gr' },
+ 'ash' => {typ=>'op', val=>0072000, fmt=>'gr' },
+ 'ashc' => {typ=>'op', val=>0073000, fmt=>'gr' },
+ 'xor' => {typ=>'op', val=>0074000, fmt=>'rg' },
+ 'sob' => {typ=>'op', val=>0077000, fmt=>'ru6'},
+ 'bpl' => {typ=>'op', val=>0100000, fmt=>'s8' },
+ 'bmi' => {typ=>'op', val=>0100400, fmt=>'s8' },
+ 'bhi' => {typ=>'op', val=>0101000, fmt=>'s8' },
+ 'blos' => {typ=>'op', val=>0101400, fmt=>'s8' },
+ 'bvc' => {typ=>'op', val=>0102000, fmt=>'s8' },
+ 'bvs' => {typ=>'op', val=>0102400, fmt=>'s8' },
+ 'bcc' => {typ=>'op', val=>0103000, fmt=>'s8' },
+ 'bhis' => {typ=>'op', val=>0103000, fmt=>'s8' }, #alias
+ 'bcs' => {typ=>'op', val=>0103400, fmt=>'s8' },
+ 'blo' => {typ=>'op', val=>0103400, fmt=>'s8' }, #alias
+ 'emt' => {typ=>'op', val=>0104000, fmt=>'n8' },
+ 'trap' => {typ=>'op', val=>0104400, fmt=>'n8' },
+ 'clrb' => {typ=>'op', val=>0105000, fmt=>'g' },
+ 'comb' => {typ=>'op', val=>0105100, fmt=>'g' },
+ 'incb' => {typ=>'op', val=>0105200, fmt=>'g' },
+ 'decb' => {typ=>'op', val=>0105300, fmt=>'g' },
+ 'negb' => {typ=>'op', val=>0105400, fmt=>'g' },
+ 'adcb' => {typ=>'op', val=>0105500, fmt=>'g' },
+ 'sbcb' => {typ=>'op', val=>0105600, fmt=>'g' },
+ 'tstb' => {typ=>'op', val=>0105700, fmt=>'g' },
+ 'rorb' => {typ=>'op', val=>0106000, fmt=>'g' },
+ 'rolb' => {typ=>'op', val=>0106100, fmt=>'g' },
+ 'asrb' => {typ=>'op', val=>0106200, fmt=>'g' },
+ 'aslb' => {typ=>'op', val=>0106300, fmt=>'g' },
+ 'mtps' => {typ=>'op', val=>0106400, fmt=>'g' },
+ 'mfpd' => {typ=>'op', val=>0106500, fmt=>'g' },
+ 'mtpd' => {typ=>'op', val=>0106600, fmt=>'g' },
+ 'mfps' => {typ=>'op', val=>0106700, fmt=>'g' },
+ 'movb' => {typ=>'op', val=>0110000, fmt=>'gg' },
+ 'cmpb' => {typ=>'op', val=>0120000, fmt=>'gg' },
+ 'bitb' => {typ=>'op', val=>0130000, fmt=>'gg' },
+ 'bicb' => {typ=>'op', val=>0140000, fmt=>'gg' },
+ 'bisb' => {typ=>'op', val=>0150000, fmt=>'gg' },
+ 'sub' => {typ=>'op', val=>0160000, fmt=>'gg' },
+ 'cfcc' => {typ=>'op', val=>0170000, fmt=>'-' ,fpp=>1 },
+ 'setf' => {typ=>'op', val=>0170001, fmt=>'-' ,fpp=>1 },
+ 'setd' => {typ=>'op', val=>0170011, fmt=>'-' ,fpp=>1 },
+ 'seti' => {typ=>'op', val=>0170002, fmt=>'-' ,fpp=>1 },
+ 'setl' => {typ=>'op', val=>0170012, fmt=>'-' ,fpp=>1 },
+ 'ldfps' => {typ=>'op', val=>0170100, fmt=>'g' ,fpp=>1 },
+ 'stfps' => {typ=>'op', val=>0170200, fmt=>'g' ,fpp=>1 },
+ 'stst' => {typ=>'op', val=>0170300, fmt=>'g' ,fpp=>1 },
+ 'clrf' => {typ=>'op', val=>0170400, fmt=>'g' ,fpp=>1 },
+ 'clrd' => {typ=>'op', val=>0170400, fmt=>'g' ,fpp=>1 }, # alias
+ 'tstf' => {typ=>'op', val=>0170500, fmt=>'g' ,fpp=>1 },
+ 'tstd' => {typ=>'op', val=>0170500, fmt=>'g' ,fpp=>1 }, # alias
+ 'absf' => {typ=>'op', val=>0170600, fmt=>'g' ,fpp=>1 },
+ 'absd' => {typ=>'op', val=>0170600, fmt=>'g' ,fpp=>1 }, # alias
+ 'negf' => {typ=>'op', val=>0170700, fmt=>'g' ,fpp=>1 },
+ 'negd' => {typ=>'op', val=>0170700, fmt=>'g' ,fpp=>1 }, # alias
+ 'mulf' => {typ=>'op', val=>0171000, fmt=>'gr' ,fpp=>1 },
+ 'muld' => {typ=>'op', val=>0171000, fmt=>'gr' ,fpp=>1 }, # alias
+ 'modf' => {typ=>'op', val=>0171400, fmt=>'gr' ,fpp=>1 },
+ 'modd' => {typ=>'op', val=>0171400, fmt=>'gr' ,fpp=>1 }, # alias
+ 'addf' => {typ=>'op', val=>0172000, fmt=>'gr' ,fpp=>1 },
+ 'addd' => {typ=>'op', val=>0172000, fmt=>'gr' ,fpp=>1 }, # alias
+ 'ldf' => {typ=>'op', val=>0172400, fmt=>'gr' ,fpp=>1 },
+ 'ldd' => {typ=>'op', val=>0172400, fmt=>'gr' ,fpp=>1 }, # alias
+ 'subf' => {typ=>'op', val=>0173000, fmt=>'gr' ,fpp=>1 },
+ 'subd' => {typ=>'op', val=>0173000, fmt=>'gr' ,fpp=>1 }, # alias
+ 'cmpf' => {typ=>'op', val=>0173400, fmt=>'gr' ,fpp=>1 },
+ 'cmpd' => {typ=>'op', val=>0173400, fmt=>'gr' ,fpp=>1 }, # alias
+ 'stf' => {typ=>'op', val=>0174000, fmt=>'rg' ,fpp=>1 },
+ 'std' => {typ=>'op', val=>0174000, fmt=>'rg' ,fpp=>1 }, # alias
+ 'divf' => {typ=>'op', val=>0174400, fmt=>'gr' ,fpp=>1 },
+ 'divd' => {typ=>'op', val=>0174400, fmt=>'gr' ,fpp=>1 }, # alias
+ 'stexp' => {typ=>'op', val=>0175000, fmt=>'rg' ,fpp=>1 },
+ 'stcfi' => {typ=>'op', val=>0175400, fmt=>'rg' ,fpp=>1 },
+ 'stcfl' => {typ=>'op', val=>0175400, fmt=>'rg' ,fpp=>1 }, # alias
+ 'stcdi' => {typ=>'op', val=>0175400, fmt=>'rg' ,fpp=>1 }, # alias
+ 'stcdl' => {typ=>'op', val=>0175400, fmt=>'rg' ,fpp=>1 }, # alias
+ 'stcfd' => {typ=>'op', val=>0176000, fmt=>'rg' ,fpp=>1 },
+ 'stcdf' => {typ=>'op', val=>0176000, fmt=>'rg' ,fpp=>1 }, # alias
+ 'ldexp' => {typ=>'op', val=>0176400, fmt=>'gr' ,fpp=>1 },
+ 'ldcif' => {typ=>'op', val=>0177000, fmt=>'gr' ,fpp=>1 },
+ 'ldcid' => {typ=>'op', val=>0177000, fmt=>'gr' ,fpp=>1 }, # alias
+ 'ldclf' => {typ=>'op', val=>0177000, fmt=>'gr' ,fpp=>1 }, # alias
+ 'ldcld' => {typ=>'op', val=>0177000, fmt=>'gr' ,fpp=>1 }, # alias
+ 'ldcdf' => {typ=>'op', val=>0177400, fmt=>'gr' ,fpp=>1 },
+ 'ldcfd' => {typ=>'op', val=>0177400, fmt=>'gr' ,fpp=>1 } # alias
+);
+
+# operand formats
+my %opfmt = (
+ '-' => [], # halt,...
+ 'n3' => [{typ=>'e', pref=>''}], # spl
+ 'n6' => [{typ=>'e', pref=>''}], # mark
+ 'n8' => [{typ=>'e', pref=>''}], # trap,emt
+ 'r' => [{typ=>'r', pref=>'o1'}], # rts
+ 'g' => [{typ=>'g', pref=>'o1'}], # inc,...
+ 'rg' => [{typ=>'r', pref=>'o1'}, {typ=>'g', pref=>'o2'}], # xor,jsr
+ 'gr' => [{typ=>'g', pref=>'o2'}, {typ=>'r', pref=>'o1'}], # ash,...
+ 'gg' => [{typ=>'g', pref=>'o1'}, {typ=>'g', pref=>'o2'}], # add,...
+ 's8' => [{typ=>'e', pref=>''}], # br,...
+ 'ru6' => [{typ=>'r', pref=>'o1'}, {typ=>'e', pref=>''}] # sob
+);
+
+# psect table
+my %psect =
+('.abs.' => {dot=>0, dotmax=>0}
+);
+my $cur_psect = '.abs.'; # current psect
+
+# local symbol table
+my %lst =
+('.' => {name=>'.', typ=>'dot', val=>0, psect=>'.abs.'}
+);
+my $llbl_scope = '0'; # current local label scope
+my $llbl_ascope = 0; # annonymous local label scope count
+
+# macro table
+my %mst;
+
+my @flist; # list of filenames
+my $fstem; # stem or last file name
+my $lst_do; # generate listing
+my $lst_fname; # listing file name
+my $lda_do; # generate lda output
+my $lda_fname; # lda file name
+my $cof_do; # generate cof output
+my $cof_fname; # cof file name
+my $lsm_do; # generate lsm output
+my $lsm_fname; # lsm file name
+
+my @src;
+my %errcnt; # error tag counter
+my $errcnt_tot=0; # total error count
+my $pass;
+
+my @t_pushback;
+
+my $out_dot; # current . for output
+my @out_data; # output data
+my $out_start = 1; # absolute start address
+
+autoflush STDOUT 1 if (-p STDOUT); # autoflush if output into pipe
+
+if (exists $opts{help}) {
+ print_help;
+ exit 0;
+}
+
+if (scalar(@ARGV) == 0) {
+ print STDERR "asm-11-F: no input files specified, quiting..\n";
+ print_help;
+ exit 1;
+}
+
+# find stem of last file name
+$fstem = $ARGV[-1];
+$fstem =~ s|^.*/||; # drop leading dirs
+$fstem =~ s|\.mac$||; # drop trailing '.mac'
+
+if ($opts{lst} || $opts{olst}) {
+ $lst_do = 1;
+ $lst_fname = create_fname($opts{olst},'.lst');
+}
+
+if ($opts{lda} || $opts{olda}) {
+ $lda_do = 1;
+ $lda_fname = create_fname($opts{olda},'.lda');
+}
+
+if ($opts{cof} || $opts{ocof}) {
+ $cof_do = 1;
+ $cof_fname = create_fname($opts{ocof},'.cof');
+}
+
+if ($opts{lsm} || $opts{olsm}) {
+ $lsm_do = 1;
+ $lsm_fname = create_fname($opts{olsm},'.lsm');
+}
+
+# do pass 1
+$pass = 1;
+foreach my $fname (@ARGV) {
+ read_file($fname);
+}
+dump_sym() if $opts{dsym1};
+
+# prepare pass 2
+
+foreach (keys %psect) {
+ $psect{$_}{dot} = 0;
+}
+
+$lst{'.'}->{val} = 0;
+$lst{'.'}->{psect} = '.abs.';
+
+$cur_psect = '.abs.';
+$llbl_scope = '0';
+
+# do pass 2
+$pass = 2;
+pass2();
+dump_sym() if $opts{dsym2};
+
+# create object output files
+write_lda($lda_fname) if $lda_do;
+write_cof($cof_fname) if $cof_do;
+write_lsm($lsm_fname) if $lsm_do;
+
+# and exit
+if ($errcnt_tot > 0) {
+ print "asm-11-E: compilation errors:";
+ foreach my $err (sort keys %errcnt) {
+ printf " %s: %d", $err, $errcnt{$err};
+ }
+ print "\n";
+ exit 1;
+}
+exit 0;
+
+#-------------------------------------------------------------------------------
+
+sub create_fname {
+ my ($fname,$suff) = @_;
+ if (defined $fname) {
+ $fname =~ s|\%|$fstem|;
+ return $fname;
+ }
+ $fname = $fstem;
+ $fname .= $suff unless $fname eq '-';
+ return $fname;
+}
+
+#-------------------------------------------------------------------------------
+
+sub read_file {
+ my ($fname) = @_;
+ my $fh;
+ if ($fname eq "-") {
+ $fh = *STDIN;
+ } else {
+ if (not -r $fname) {
+ print STDERR "asm-11-F: '$fname' not found or readable, quiting..\n";
+ exit 1;
+ }
+ $fh = new FileHandle;
+ $fh->open($fname) or die "failed to open '$fname'";
+ }
+
+ push @flist, $fname;
+
+ my $lineno = 0;
+ my $fileno = scalar(@flist);
+ while (<$fh>) {
+ chomp;
+ my $line = $_;
+ $lineno += 1;
+ my $rl = parse_line($fileno, $lineno, $line);
+ dump_rl($rl) if $opts{tpass1};
+ push @src, $rl;
+
+ # handle .include
+ if (defined $$rl{oper} && $$rl{oper} eq '.include' && defined $$rl{ifile}) {
+ my $fnam = $$rl{ifile};
+ unless ($fnam =~ m|^/|) {
+ foreach (@{$opts{I}}) {
+ if (-r "$_/$fnam") {
+ $fnam = "$_/$fnam";
+ last;
+ }
+ }
+ }
+ read_file($fnam);
+ }
+
+ }
+
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub parse_line {
+ my ($fileno,$lineno,$line) = @_;
+
+ my %l = ( fileno => $fileno, # file number
+ lineno => $lineno, # line number
+ line => $line, # line
+ cl => [split '',$line], # char list
+ tl => [], # token list
+ err => '', # error tags
+ psect => $cur_psect, # current psect
+ dot => getdot(), # current dot
+ outw => [], # output: words
+ outb => [] # output: bytes
+ );
+
+ my $state = 'start'; # parser state
+
+ my $op_code; # op code
+ my $op_fmt; # op format
+ my $op_fpp; # true if floating opcode
+ my @op_ops; # list of operands
+ my $op_rop; # ref of current operand dsc
+
+ my $s_incok;
+ my $op_ibeg;
+ my $op_creg;
+ my $op_cmod;
+ my $op_cmod_def;
+
+ my @e_pbeg;
+ my $e_ibeg;
+ my $e_iend;
+
+ my $a_sym;
+ my $a_typ;
+
+ my $d_dire;
+ my @d_elist;
+
+ my $c;
+ my $rt;
+ my $tmask = 0;
+
+ my @stack;
+
+ @t_pushback = ();
+
+ printf "-- parse: '$line'\n" if $opts{tparse} || $opts{ttoken};
+
+ # quit if invalid character found (non 7 bit ascii in asm-11)
+ foreach my $c (@{$l{cl}}) {
+ if (ord($c) > 127) {
+ add_err(\%l, 'I');
+ return \%l;
+ }
+ }
+
+ while (1) {
+ if ($opts{tparse}) {
+ printf "-- state = $state";
+ printf ", nest = %d", scalar(@e_pbeg) if $state =~ m/^e_/;
+ print "\n";
+ }
+
+ if ($state eq 'start') { # state: start -------------------
+ $rt = get_token(\%l, $tmask);
+
+ # end of line seen ?
+ if ($$rt{tag} eq 'EOL') {
+ last;
+
+ # name seen
+ } elsif ($$rt{tag} eq 'SYM') {
+ # directive name seen ?
+ if (exists $pst{$$rt{val}} && $pst{$$rt{val}}{typ} eq 'dir') {
+ $state = 'oper';
+
+ # otherwise check for label or assignment
+ } else {
+ my $isllbl = check_llbl($$rt{val});
+ $rt = get_token(\%l, $tmask);
+ # handle local labels
+ if ($isllbl) {
+ if ($$rt{tag} eq 'LBL') {
+ setsym(\%l, 'lbl' ,$l{tl}[-2]{val}, getdot());
+ $l{lscope} = $llbl_scope;
+ $l{label} = $l{tl}[-2]{val};
+ $state = 'start1';
+ } else {
+ $state = 'q';
+ }
+ # handle assignments
+ } elsif ($$rt{tag} eq 'ASS') {
+ $a_sym = $l{tl}[-2]{val};
+ $a_typ = $l{tl}[-1]{val};
+ push @stack, 'a_end';
+ $state = 'e_beg';
+ # handle normal labels
+ } elsif ($$rt{tag} eq 'LBL') {
+ setsym(\%l, 'lbl' ,$l{tl}[-2]{val}, getdot());
+ $llbl_scope = $l{tl}[-2]{val};
+ $l{lscope} = $l{tl}[-2]{val};
+ $l{label} = $l{tl}[-2]{val};
+ $state = 'start1';
+ # if neither label or assigmnent, handle as operation or directive
+ } else {
+ pushback_token(\%l);
+ $state = 'oper';
+ }
+ }
+
+ # anything else seen, treat a implicit .word
+ } else {
+ pushback_token(\%l);
+ $state = 'iword';
+ }
+
+ } elsif ($state eq 'start1') { # state: start1 ------------------
+ $rt = get_token(\%l, $tmask);
+ if ($$rt{tag} eq 'EOL') {
+ last;
+ } elsif ($$rt{tag} eq 'SYM') {
+ $state = 'oper';
+ } else { # not symbol -> implicit .word
+ pushback_token(\%l);
+ $state = 'iword';
+ }
+
+ } elsif ($state eq 'oper') { # state: oper --------------------
+ # Note: state oper is entered with token already on tl list !!
+ my $rt0 = $l{tl}[-1];
+ my $op = $$rt0{val};
+ $l{oper} = $op;
+ if (exists $pst{$op}) {
+ my $rs = $pst{$op};
+ if ($$rs{typ} eq 'dir') { # directives ------------------
+ $d_dire = $op;
+ if ($op eq '.word' || # .word
+ $op eq '.byte') { # .byte
+ $state = 'dl_beg';
+
+ } elsif ($op eq '.blkw' || # .blkw
+ $op eq '.blkb') { # .blkb
+ $state = 'dl_beg';
+
+ } elsif ($op eq '.ascii' || # .ascii
+ $op eq '.asciz') { # .asciz
+ $tmask = TMASK_STRING;
+ $state = 'al_next';
+
+ } elsif ($op eq '.even' || # .even
+ $op eq '.odd') { # .odd
+ my $dot = getdot();
+ my $inc = 0;
+ $inc = 1 if $op eq '.even' && ($dot&01)==1;
+ $inc = 1 if $op eq '.odd' && ($dot&01)==0;
+ incdot(1) if $inc;
+ $l{typ} = 'data';
+ $l{incdot} = $inc;
+ $l{lstdot} = 1;
+ $state = 'end';
+
+ } elsif ($op eq '.asect') { # .asect
+ # .asect is currently a noop because asect is start default
+ $l{lstdot} = 1;
+ $state = 'end';
+
+ } elsif ($op eq '.include') { # .include
+ $rt = get_token(\%l, TMASK_STRING);
+ if ($$rt{tag} eq 'STR') {
+ my $ifile = $$rt{val};
+ my $rt = get_token(\%l, TMASK_STRING);
+ if ($$rt{tag} eq 'EOL') {
+ $l{ifile} = substr($ifile,1,-1) unless $l{err} ne '';
+ $state = 'end';
+ } else {
+ $state = 'q';
+ }
+ } else {
+ $state = 'q';
+ }
+
+ } elsif ($op eq '.end') { # .end
+ $state = 'dl_beg';
+
+ } else {
+ die "BUGCHECK: op = '$op' in pst but no handler";
+ }
+
+ } elsif ($$rs{typ} eq 'op') { # or opcodes ------------------
+ walign(\%l);
+ $l{typ} = 'code';
+ $op_code = $$rs{val};
+ $op_fmt = $$rs{fmt};
+ $op_fpp = $$rs{fpp};
+ die "BUGCHECK: op_fmt = '$op_fmt' unknown in opfmt"
+ unless defined $opfmt{$op_fmt};
+
+ $l{opcode} = $op_code;
+ $l{opfmt} = $op_fmt;
+
+ @op_ops = @{$opfmt{$op_fmt}};
+
+ if (scalar(@op_ops) == 0) {
+ incdot(2);
+ $state = 'end';
+ } else {
+ $op_rop = shift @op_ops;
+ $state = 'op_beg';
+ }
+
+ }
+ } else { # oper noy in pst --> implicit .word
+ pushback_token(\%l);
+ $state = 'iword';
+ }
+
+ } elsif ($state eq 'op_beg') { # state: op_beg ------------------
+ $op_ibeg = scalar(@{$l{tl}});
+ $op_creg = undef;
+ $op_cmod = undef;
+ $op_cmod_def = undef;
+ $e_ibeg = undef;
+ $e_iend = undef;
+ if ($$op_rop{typ} eq 'r') { # operand: register
+ $rt = get_token(\%l, $tmask);
+ $op_creg = check_reg($rt);
+ if (defined $op_creg) {
+ if ($op_fpp && $op_creg > 3) { # fpp ac must be r0:r3
+ $op_creg &= 03;
+ add_err(\%l, 'T');
+ }
+ $op_cmod = 0;
+ $state = 'op_end';
+ } else {
+ $state = 'q';
+ }
+ } elsif ($$op_rop{typ} eq 'e') { # operand: expression
+ push @stack, 'op_end';
+ $state = 'e_beg';
+ } elsif ($$op_rop{typ} eq 'g') { # operand: general
+ push @stack, 'op_end';
+ $state = 'g_beg';
+ } else {
+ die "BUGCHECK: unexpected op typ '$$op_rop{typ}'";
+ }
+
+ } elsif ($state eq 'op_end') { # state: op_end ------------------
+ my $op_iend = scalar(@{$l{tl}})-1;
+ $l{tl}[$op_ibeg]->{om} = '<';
+ $l{tl}[$op_iend]->{om} = ($l{tl}[$op_iend]->{om}) ? '<>' : '>';
+
+ my $pref = $$op_rop{pref};
+ if ($$op_rop{typ} =~ m/^[gr]$/) {
+ $l{$pref.'reg'} = $op_creg;
+ $l{$pref.'mod'} = $op_cmod;
+ if (defined $e_ibeg) {
+ $l{$pref.'ebeg'} = $e_ibeg;
+ $l{$pref.'eend'} = $e_iend;
+ }
+ } elsif ($$op_rop{typ} eq 'e') {
+ if (defined $e_ibeg) {
+ $l{ebeg} = $e_ibeg;
+ $l{eend} = $e_iend;
+ }
+ }
+
+ if (scalar(@op_ops)) { # second operand
+ $rt = get_token(\%l, $tmask);
+ if (check_token($rt, 'DEL', ',')) {
+ $op_rop = shift @op_ops;
+ $state = 'op_beg';
+ } else {
+ $state = 'q';
+ }
+
+ } else { # all operands seen
+ my $nword = 1;
+ $nword += 1 if defined $l{o1ebeg};
+ $nword += 1 if defined $l{o2ebeg};
+ incdot(2*$nword);
+ $state = 'end';
+ }
+
+ } elsif ($state eq 'g_beg') { # state: g_beg -------------------
+ $rt = get_token(\%l, $tmask);
+ if (defined check_reg($rt)) { # R !
+ $op_creg = check_reg($rt);
+ $op_cmod = 0;
+ $state = 'g_end';
+ } elsif (check_token($rt, 'DEL', '(')) { # ( R),R)+
+ $state = 'g_inc1';
+ } elsif (check_token($rt, 'OP', '@')) { # @ R,(R)+,-(R),E(R),#E,E
+ $op_cmod_def = 1;
+ $state = 'g_def1';
+ } elsif (check_token($rt, 'OP', '-')) { # - (R)
+ $rt = get_token(\%l, $tmask);
+ if (check_token($rt, 'DEL', '(')) { # next (
+ pushback_token(\%l);
+ $state = 'g_dec1'; # go for -(R)
+ } else {
+ pushback_token(\%l);
+ pushback_token(\%l);
+ push @stack, 'g_ind1'; # otherwise -E..
+ $state = 'e_beg';
+ }
+ } elsif (check_token($rt, 'OP', '#')) { # # E
+ push @stack, 'g_imm1';
+ $state = 'e_beg';
+ } else {
+ pushback_token(\%l);
+ push @stack, 'g_ind1'; # E ! (R)
+ $state = 'e_beg';
+ }
+
+ } elsif ($state eq 'g_inc1') { # state: g_inc1 ------------------
+ $rt = get_token(\%l, $tmask);
+ $op_creg = check_reg($rt);
+ if (defined $op_creg) {
+ $rt = get_token(\%l, $tmask);
+ if (check_token($rt, 'DEL', ')')) {
+ $rt = get_token(\%l, $tmask);
+ if (check_token($rt, 'OP', '+')) {
+ $op_cmod = $op_cmod_def ? 3 : 2;
+ $state = 'g_end';
+ } else {
+ if ($op_cmod_def) {
+ $state = 'q';
+ } else {
+ pushback_token(\%l);
+ $op_cmod = 1;
+ $state = 'g_end';
+ }
+ }
+ } else {
+ $state = 'q';
+ }
+ } else {
+ $state = 'q';
+ }
+
+ } elsif ($state eq 'g_def1') { # state: g_def1 ------------------
+ $rt = get_token(\%l, $tmask);
+ if (defined check_reg($rt)) { # R
+ $op_creg = check_reg($rt);
+ $op_cmod = 1;
+ $state = 'g_end';
+ } elsif (check_token($rt, 'DEL', '(')) { # ( -> R+
+ $state = 'g_inc1';
+ } elsif (check_token($rt, 'OP', '-')) { # - -> (R)
+ $rt = get_token(\%l, $tmask);
+ if (check_token($rt, 'DEL', '(')) { # next (
+ pushback_token(\%l);
+ $state = 'g_dec1'; # go for -(R)
+ } else {
+ pushback_token(\%l);
+ pushback_token(\%l);
+ push @stack, 'g_ind1'; # otherwise -E..
+ $state = 'e_beg';
+ }
+ } elsif (check_token($rt, 'OP', '#')) { # # -> #
+ push @stack, 'g_imm1';
+ $state = 'e_beg';
+ } else { # E -> !, (R)
+ pushback_token(\%l);
+ push @stack, 'g_ind1';
+ $state = 'e_beg';
+ }
+
+ } elsif ($state eq 'g_ind1') { # state: g_ind1 ------------------
+ $rt = get_token(\%l, $tmask);
+ if (check_token($rt, 'DEL', '(')) {
+ $rt = get_token(\%l, $tmask);
+ $op_creg = check_reg($rt);
+ if (defined $op_creg) {
+ $rt = get_token(\%l, $tmask);
+ $op_cmod = $op_cmod_def ? 7 : 6;
+ $state = check_token($rt, 'DEL', ')') ? 'g_end' : 'q';
+ } else {
+ $state = 'q';
+ }
+ } else {
+ pushback_token(\%l);
+ $op_creg = 7;
+ $op_cmod = $op_cmod_def ? 7 : 6;
+ $state = 'g_end';
+ }
+
+ } elsif ($state eq 'g_dec1') { # state: g_dec1 ------------------
+ $rt = get_token(\%l, $tmask);
+ if (check_token($rt, 'DEL', '(')) {
+ $rt = get_token(\%l, $tmask);
+ $op_creg = check_reg($rt);
+ if (defined $op_creg) {
+ $rt = get_token(\%l, $tmask);
+ $op_cmod = $op_cmod_def ? 5 : 4;
+ $state = check_token($rt, 'DEL', ')') ? 'g_end' : 'q';
+ } else {
+ $state = 'q';
+ }
+ } else {
+ $state = 'q';
+ }
+
+ } elsif ($state eq 'g_imm1') { # state: g_imm1 ------------------
+ $op_creg = 7;
+ $op_cmod = $op_cmod_def ? 3 : 2;
+ $state = 'g_end';
+
+ } elsif ($state eq 'g_end') { # state: g_end -------------------
+ $state = pop @stack;
+
+ } elsif ($state eq 'e_beg') { # state: e_beg -------------------
+ $e_ibeg = scalar(@{$l{tl}});
+ @e_pbeg = ();
+ $state = 'e_uop';
+
+ } elsif ($state eq 'e_uop') { # state: e_uop -------------------
+ $rt = get_token(\%l, $tmask);
+ if ($$rt{tag} eq 'OP' && $$rt{typ}=~'u') { # OP(u)
+ $$rt{typ}='u';
+ $state = 'e_uop';
+ } elsif ($$rt{tag} eq 'NUM' || $$rt{tag} eq 'SYM') {
+ $state = 'e_bop';
+ } elsif (check_token($rt, 'DEL', '<')) {
+ push @e_pbeg, scalar(@{$l{tl}})-1;
+ $state = 'e_uop';
+ } else {
+ $state = 'q';
+ }
+
+ } elsif ($state eq 'e_bop') { # state: e_bop -------------------
+ $rt = get_token(\%l, $tmask);
+ if ($$rt{tag} eq 'OP' && $$rt{typ}=~'b') { # OP(b)
+ $$rt{typ}='b';
+ $state = 'e_bop1';
+ } elsif (check_token($rt, 'DEL', '>')) {
+ if (scalar(@e_pbeg) == 0) {
+ $state = 'q';
+ } else {
+ my $pbeg = pop @e_pbeg;
+ $l{tl}[$pbeg]->{pend} = scalar(@{$l{tl}})-1;
+ if ($tmask & TMASK_STRINGEXP) {
+ $state = 'e_end';
+ } else {
+ $state = 'e_bop';
+ }
+ }
+ } else {
+ pushback_token(\%l);
+ $state = 'e_end';
+ }
+
+ } elsif ($state eq 'e_bop1') { # state: e_bop1 ------------------
+ $rt = get_token(\%l, $tmask);
+ if ($$rt{tag} eq 'NUM' || $$rt{tag} eq 'SYM') {
+ $state = 'e_bop';
+ } elsif (check_token($rt, 'DEL', '<')) {
+ push @e_pbeg, scalar(@{$l{tl}})-1;
+ $state = 'e_uop';
+ } else {
+ $state = 'q';
+ }
+
+ } elsif ($state eq 'e_end') { # state: e_end -------------------
+ $e_iend = scalar(@{$l{tl}})-1;
+ $l{tl}[$e_ibeg]->{em} = '<>';
+ if ($e_iend != $e_ibeg) {
+ $l{tl}[$e_ibeg]->{em} = '<';
+ $l{tl}[$e_iend]->{em} = '>';
+ }
+ $state = (scalar(@e_pbeg)==0) ? pop @stack : 'q';
+
+ } elsif ($state eq 'a_end') { # state: a_end -------------------
+ my $val = eval_exp(\%l, $e_ibeg, $e_iend);
+ my $typ = ($a_typ =~ m/:/) ? 'pass' : 'ass';
+ setsym(\%l, $typ, $a_sym, $val);
+ $l{typ} = 'ass';
+ $l{atyp} = $typ;
+ $l{asym} = $a_sym;
+ $l{ebeg} = $e_ibeg;
+ $l{eend} = $e_iend;
+ $state = 'end';
+
+ } elsif ($state eq 'dl_beg') { # state: dl_beg ------------------
+ $rt = get_token(\%l, $tmask);
+ if ($$rt{tag} eq 'EOL') {
+ $state = 'dl_end';
+ } elsif (check_token($rt, 'DEL', ',')) {
+ pushback_token(\%l);
+ $e_ibeg = undef;
+ $e_iend = undef;
+ $state = 'dl_next';
+ } else {
+ pushback_token(\%l);
+ $e_ibeg = undef;
+ $e_iend = undef;
+ push @stack, 'dl_next';
+ $state = 'e_beg';
+ }
+
+ } elsif ($state eq 'dl_next') { # state: dl_next -----------------
+ push @d_elist, {ibeg=>$e_ibeg, iend=>$e_iend};
+ $rt = get_token(\%l, $tmask);
+ if ($$rt{tag} eq 'EOL') {
+ $state = 'dl_end';
+ } elsif (check_token($rt, 'DEL', ',')) {
+ $rt = get_token(\%l, $tmask);
+ if ($$rt{tag} eq 'EOL' || check_token($rt, 'DEL', ',')) {
+ pushback_token(\%l);
+ $e_ibeg = undef;
+ $e_iend = undef;
+ $state = 'dl_next';
+ } else {
+ pushback_token(\%l);
+ $e_ibeg = undef;
+ $e_iend = undef;
+ push @stack, 'dl_next';
+ $state = 'e_beg';
+ }
+ } else {
+ $state = 'q';
+ }
+
+ } elsif ($state eq 'dl_end') { # state: dl_end ------------------
+ $state = 'end';
+ if ($d_dire eq '.word') {
+ walign(\%l);
+ if (scalar(@d_elist)) {
+ $l{typ} = 'data';
+ $l{delist} = \@d_elist;
+ incdot(2*scalar(@d_elist));
+ } else {
+ $state = 'q';
+ }
+ } elsif ($d_dire eq '.byte') {
+ if (scalar(@d_elist)) {
+ $l{typ} = 'data';
+ $l{delist} = \@d_elist;
+ incdot(1*scalar(@d_elist));
+ } else {
+ $state = 'q';
+ }
+ } elsif ($d_dire eq '.blkw' || $d_dire eq '.blkb') {
+ $l{lstdot} = 1;
+ walign(\%l) if $d_dire eq '.blkw';
+ my $val;
+ if (scalar(@d_elist) == 0) {
+ $val = 1;
+ } elsif (scalar(@d_elist) == 1) {
+ $val = eval_exp(\%l, $d_elist[0]{ibeg}, $d_elist[0]{iend});
+ } else {
+ $state = 'q';
+ }
+
+ if (defined $val) {
+ my $size = ($d_dire eq '.blkw') ? 2 : 1;
+ incdot($size * $val);
+ $l{typ} = 'data';
+ $l{incdot} = $size * $val;
+ } else {
+ add_err(\%l, 'A');
+ }
+
+ } elsif ($d_dire eq '.end') {
+ my $val;
+ if (scalar(@d_elist) == 0) {
+ $val = 1;
+ } elsif (scalar(@d_elist) == 1) {
+ $val = eval_exp(\%l, $d_elist[0]{ibeg}, $d_elist[0]{iend});
+ } else {
+ $state = 'q';
+ }
+ if (defined $val) {
+ $l{lstval} = $val; # set aval to get it in listing
+ $out_start = $val;
+ } else {
+ $l{lstval} = 0;
+ add_err(\%l, 'U');
+ }
+
+ } else {
+ die "BUGCHECK: unexpected d_dire = '$d_dire'";
+ }
+
+ } elsif ($state eq 'al_next') { # state: al_next -----------------
+ $rt = get_token(\%l, $tmask);
+ if ($$rt{tag} eq 'STR') {
+ push @d_elist, {str=>$$rt{val}};
+ } elsif ($$rt{tag} eq 'EOL') {
+ $state = 'al_end';
+ } elsif (check_token($rt, 'DEL', '<')) {
+ pushback_token(\%l);
+ $tmask = TMASK_STRINGEXP;
+ push @stack, 'al_exp';
+ $e_ibeg = undef;
+ $e_iend = undef;
+ $state = 'e_beg';
+ } else {
+ $state = 'q';
+ }
+
+ } elsif ($state eq 'al_exp') { # state: al_exp ------------------
+ push @d_elist, {ibeg=>$e_ibeg, iend=>$e_iend};
+ $tmask = TMASK_STRING;
+ $state = 'al_next';
+
+ } elsif ($state eq 'al_end') { # state: al_end ------------------
+ my $size = 0;
+ foreach (@d_elist) {
+ if (defined $$_{str}) {
+ $size += length($$_{str}) - 2;
+ } else {
+ $size += 1;
+ }
+ }
+ $size += 1 if $d_dire eq '.asciz';
+ incdot($size);
+ $l{typ} = 'data';
+ $l{delist} = \@d_elist;
+ $state = 'end';
+
+ } elsif ($state eq 'iword') { # state: iword -------------------
+ $l{oper} = $d_dire = '.word'; # setup implicit .word directive
+ $state = 'dl_beg';
+
+ } elsif ($state eq 'end') { # state: end ---------------------
+ # unless EOL already seen fetch next token
+ if (scalar(@{$l{tl}}) && $l{tl}[-1]{tag} eq 'EOL') {
+ $rt = $l{tl}[-1];
+ } else {
+ $rt = get_token(\%l, $tmask);
+ }
+ # if at EOL fine, otherwise mark syntax error
+ if ($$rt{tag} eq 'EOL') {
+ last;
+ } else {
+ $state = 'q';
+ }
+
+ } elsif ($state eq 'q') { # state: q -----------------------
+ add_err(\%l, 'Q'); # set Q error flag
+ last; # and quit this line
+
+ } else {
+ die "BUGCHECK: unexpected state '$state'\n";
+ }
+ }
+
+ return \%l;
+}
+
+#-------------------------------------------------------------------------------
+
+sub walign {
+ my ($rl) = @_;
+ my $dot = getdot();
+ if ($dot & 0x1) { # odd address ?
+ incdot(1);
+ add_err($rl, 'B');
+ $$rl{dot} = getdot() if ($pass == 2); # fixup . in rl context in pass 2
+ }
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub add_err {
+ my ($rl,$err) = @_;
+ return if index($$rl{err}, $err) >= 0; # prevent multiple error tags
+ $$rl{err} .= $err; # set error tag
+ $errcnt{$err} += 1; # and count them
+ $errcnt_tot += 1;
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub prt_err {
+ my ($rl) = @_;
+ return join '', sort split '', $$rl{err};
+}
+
+#-------------------------------------------------------------------------------
+
+sub setdot {
+ my ($val) = @_;
+ return unless defined $val;
+ $lst{'.'}->{val} = $val;
+ $psect{$cur_psect}{dot} = $val;
+ $psect{$cur_psect}{dotmax} = $val if $psect{$cur_psect}{dotmax} < $val;
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub incdot {
+ my ($inc) = @_;
+ return unless defined $inc;
+ setdot(getdot() + $inc);
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub getdot {
+ return $lst{'.'}{val};
+}
+
+#-------------------------------------------------------------------------------
+
+sub setsym {
+ my ($rl,$typ,$name,$val) = @_;
+ ##print "+++set: pass=$pass; $llbl_scope : $name; typ=$typ\n";
+ if ($name eq '.') {
+ if ($typ eq 'ass') {
+ setdot($val);
+ } else {
+ add_err($rl, 'A');
+ }
+ return;
+ }
+
+ my $isllbl = check_llbl($name);
+ if (check_llbl($name)) {
+ if ($typ eq 'lbl') {
+ $name = $llbl_scope . ':' . $name if $isllbl;
+ $typ = 'llbl';
+ } else {
+ die "BUGCHECK: name looks like local label, but typ=$typ";
+ }
+ }
+
+ my $namelc = lc($name);
+
+ if ($typ ne 'ass' && exists $lst{$namelc} &&
+ $lst{$namelc}{typ} ne 'udef' && $pass==1) {
+ # Note: 'M' etaging done in pass 2!
+ $lst{$namelc}{mdef} = 1;
+ return;
+ }
+
+ $lst{$namelc}{name} = $name;
+ $lst{$namelc}{val} = $val;
+ $lst{$namelc}{typ} = $typ;
+ $lst{$namelc}{psect} = $cur_psect;
+
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub getsym {
+ my ($rl, $name, $noxref) = @_;
+ ##print "+++get: pass=$pass; $llbl_scope : $name\n";
+ $name = $llbl_scope . ':' . $name if check_llbl($name);
+ my $namelc = lc($name);
+
+ # if not yet defined, add it in lst with typ='udef'
+ if (not exists $lst{$namelc}) { # not yet in lst
+ if (exists $pst{$namelc} && # but known as opcode
+ $pst{$namelc}{typ} eq 'op') {
+ return $pst{$namelc}{val}; # return that value
+ } else {
+ $lst{$namelc} = { name => $name,
+ val => undef,
+ typ => 'udef',
+ psect => ''
+ };
+ return undef;
+ }
+ }
+
+ unless ($noxref) {
+ if ($lst{$namelc}{mdef}) {
+ add_err($rl, 'D');
+ }
+ }
+
+ return $lst{$namelc}{val};
+}
+
+#-------------------------------------------------------------------------------
+
+sub lst_checkmdef {
+ my ($name) = @_;
+ $name = $llbl_scope . ':' . $name if check_llbl($name);
+ my $namelc = lc($name);
+ return $lst{$namelc}{mdef};
+}
+
+#-------------------------------------------------------------------------------
+
+sub eval_exp {
+ my ($rl,$ibeg,$iend,$nest) = @_;
+ my $rtl = $$rl{tl};
+ my @uop;
+ my $bop;
+ my @val;
+
+ return undef unless defined $ibeg && defined $iend;
+ return undef unless defined $$rtl[$ibeg] || $nest; # FIXME_code: test em !!
+
+ for (my $i=$ibeg; $i<=$iend; $i++) {
+ my $rt = $$rtl[$i];
+ my $do_uop = 0;
+ if ($$rt{tag} eq 'NUM') {
+ push @val, $$rt{nval};
+
+ } elsif ($$rt{tag} eq 'SYM') {
+ push @val, getsym($rl, $$rt{val});
+
+ } elsif ($$rt{tag} eq 'OP' && $$rt{typ} eq 'u') {
+ push @uop, $$rt{val};
+
+ } elsif ($$rt{tag} eq 'OP' && $$rt{typ} eq 'b') {
+ $bop = $$rt{val};
+
+ } elsif ($$rt{val} eq '<') {
+ my $pend = $$rt{pend};
+ die "BUGCHECK: pend not found for rtl[$i]" unless defined $pend;
+ push @val, eval_exp($rl,$i+1,$pend-1,1);
+ $i = $pend;
+
+ } else {
+ die "BUGCHECK: tag='$$rt{tag}', val='$$rt{val}'\n";
+ }
+
+ # if stack non-empty: return undef on undef, apply unary operators
+ if (scalar(@val) > 0) {
+ return undef unless defined $val[-1];
+ my $o;
+ while($o = pop @uop) {
+ my $v = pop @val;
+ if ($o eq '+') {
+ } elsif ($o eq '-') {
+ $v = -$v;
+ } elsif ($o eq '^c') {
+ $v = ~$v;
+ } else {
+ die "BUGCHECK: tag='OP(u)', val='$o'\n";
+ }
+ push @val, (0177777 & $v);
+ }
+ }
+
+ # if stack has 2 operands: apply binary operator
+ if (scalar(@val) == 2) {
+ die "BUGCHECK: bop not defined" unless defined $bop;
+ my $v2 = pop @val;
+ my $v1 = pop @val;
+ return undef unless defined $v1 && defined $v2;
+ if ($bop eq '+') {
+ push @val, int($v1) + int($v2);
+ } elsif ($bop eq '-') {
+ push @val, int($v1) - int($v2);
+ } elsif ($bop eq '*') {
+ push @val, int($v1) * int($v2);
+ } elsif ($bop eq '/') {
+ push @val, int(int($v1) / int($v2));
+ } elsif ($bop eq '&') {
+ push @val, int($v1) & int($v2);
+ } elsif ($bop eq '!') {
+ push @val, int($v1) | int($v2);
+ } else {
+ die "BUGCHECK: tag='OP(b)', val='$bop'\n";
+ }
+ $bop = undef;
+ }
+
+ }
+ return pop @val;
+}
+
+#-------------------------------------------------------------------------------
+# returns true if symbol looks like a local label (1234$)
+
+sub check_llbl {
+ my ($name) = @_;
+ return ($name =~ m/^\d+\$/) ? 1 : 0;
+}
+
+#-------------------------------------------------------------------------------
+# returns register number if register symbol, or undef
+
+sub check_reg {
+ my ($rt) = @_;
+ return undef unless $$rt{tag} eq 'SYM';
+ my $pse = $pst{$$rt{val}};
+ return undef unless defined $pse;
+ return undef unless $$pse{typ} eq 'reg';
+ return $$pse{val};
+}
+
+#-------------------------------------------------------------------------------
+# returns true if token has specific tag/val
+
+sub check_token {
+ my ($rt, $tag, $val) = @_;
+ return undef unless $$rt{tag} eq $tag;
+ return $$rt{val} eq $val;
+}
+
+#-------------------------------------------------------------------------------
+
+sub pushback_token {
+ my ($rl) = @_;
+
+ my $rt = pop @{$$rl{tl}};
+ push @t_pushback, $rt;
+
+ if ($opts{ttoken}) {
+ printf "-- token-back: tag=%-3s val='%s'\n",
+ $$rt{tag}, savestr($$rt{val});
+ }
+
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub get_token {
+ my ($rl, $tmask) = @_;
+ my $rt;
+
+ if (scalar(@t_pushback)) {
+ $rt = pop @t_pushback;
+ if ($opts{ttoken}) {
+ printf "-- token-reget: tag=%-3s val='%s'\n",
+ $$rt{tag}, savestr($$rt{val});
+ }
+
+ } else {
+ $rt = get_token1($rl, $tmask);
+ if ($opts{ttoken}) {
+ printf "-- token-get: tag=%-3s val='%s'\n",
+ $$rt{tag}, savestr($$rt{val});
+ }
+ }
+
+ push @{$$rl{tl}}, $rt;
+
+ return $rt;
+}
+
+#-------------------------------------------------------------------------------
+
+sub finish_token {
+ my $rt = shift @_;
+ while (scalar(@_)) {
+ my $tag = shift @_;
+ my $val = shift @_;
+ $$rt{$tag} = $val;
+ }
+ return $rt;
+}
+
+#-------------------------------------------------------------------------------
+
+sub get_token1 {
+ my ($rl, $tmask) = @_;
+ my $rcl = $$rl{cl};
+
+ my $val;
+ my $ws = '';
+
+ # drop any leading whitespace
+ while (scalar(@$rcl)) {
+ last if ($$rcl[0] !~ m/\s/);
+ $ws .= shift @$rcl;
+ }
+
+ my %t = (mask => $tmask,
+ ws => $ws
+ );
+
+ # end of line ?
+ unless (scalar(@$rcl)) {
+ return finish_token(\%t, tag=>'EOL', val=>$val);
+ }
+
+ # get leading char
+ my $c = $$rcl[0];
+
+ # comment ? treated similar to end of line, comment saved in val
+ if($c eq ';') {
+ $val = join('',@$rcl);
+ @$rcl = ();
+ return finish_token(\%t, tag=>'EOL', val=>$val);
+ }
+
+ # here context dependent tokens
+ if ($tmask & TMASK_STRING) {
+ my $del = shift @$rcl;
+ if ($del eq '<') {
+ return finish_token(\%t, tag=> 'DEL', val=> $del);
+ } else {
+ my $str = $del;
+ while (scalar(@$rcl)) {
+ my $c = shift @$rcl;
+ $str .= $c;
+ return finish_token(\%t, tag=> 'STR', val=> $str) if $c eq $del;
+ }
+ add_err($rl, 'A');
+ return finish_token(\%t, tag=> 'STR', val=> $str);
+ }
+ }
+
+ # looks like symbol ?
+ if ($c =~ m/[a-zA-Z\$\.]/) {
+ while (scalar(@$rcl)) {
+ last if ($$rcl[0] !~ m/[a-zA-Z0-9\$\.]/);
+ $val .= shift @$rcl;
+ }
+ return finish_token(\%t, tag=> 'SYM', val=> $val);
+ }
+
+ # looks like number or local label ?
+ if ($c =~ m/[0-9]/) {
+ while (scalar(@$rcl)) {
+ last if ($$rcl[0] !~ m/[0-9]/);
+ $val .= shift @$rcl;
+ }
+ # check for local label
+ if (scalar(@$rcl) && $$rcl[0] eq '$') {
+ # FIXME_code: reject labels with numbers >64k-1
+ $val .= shift @$rcl;
+ return finish_token(\%t, tag=> 'SYM', val=> $val);
+ }
+ # looks like numerical constant
+ my $nval = undef;
+ # if trailing '.' seen, add and handle as decimal, otherwise as octal
+ if (scalar(@$rcl) && $$rcl[0] eq '.') {
+ $nval =int($val);
+ $val .= shift @$rcl;
+ if ($nval > 65535) {
+ add_err($rl, 'T');
+ $nval &= 0177777;
+ }
+ } else {
+ $nval = 0;
+ foreach my $cc (split '',$val) {
+ $nval = ($nval<<3) + int($cc);
+ add_err($rl, 'N') unless $cc =~ m/[0-7]/;
+ add_err($rl, 'T') unless $nval <= 0177777;
+ $nval &= 0177777;
+ }
+ }
+ return finish_token(\%t, tag=> 'NUM', val=> $val, nval=>$nval);
+ }
+
+ # looks like label delimiter (':' or '::') ?
+ if ($c eq ':') {
+ $val .= shift @$rcl;
+ $val .= shift @$rcl if (scalar(@$rcl) && $$rcl[0] eq ':');
+ return finish_token(\%t, tag=> 'LBL', val=> $val);
+ }
+
+ # looks assignment delimiter ('=','=:','==','==:') ?
+ if ($c eq '=') {
+ $val .= shift @$rcl;
+ $val .= shift @$rcl if (scalar(@$rcl) && $$rcl[0] eq '=');
+ $val .= shift @$rcl if (scalar(@$rcl) && $$rcl[0] eq ':');
+ return finish_token(\%t, tag=> 'ASS', val=> $val);
+ }
+
+ # operators
+ if ($c =~ m/^(\+|\-)$/ ) { # unary/binary operators
+ return finish_token(\%t, tag=> 'OP', typ=> 'ub', val=> shift @$rcl);
+ }
+ if ($c =~ m/^(\*|\/|\&|\!)$/ ) { # binary operators
+ return finish_token(\%t, tag=> 'OP', typ=> 'b', val=> shift @$rcl);
+ }
+ if ($c =~ m/^(\#|\@)$/ ) { # unary operators
+ return finish_token(\%t, tag=> 'OP', typ=> 'u', val=> shift @$rcl);
+ }
+
+ # ' and " operator
+ if ($c eq "'") {
+ $val .= shift @$rcl;
+ $c = shift @$rcl;
+ if (not defined $c) {
+ return finish_token(\%t, tag=> 'BAD', val=> $val);
+ }
+ $val .= $c;
+ return finish_token(\%t, tag => 'NUM', val=> $val, nval=>ord($c));
+ }
+
+ if ($c eq '"') {
+ $val .= shift @$rcl;
+ my $c1 = shift @$rcl;
+ my $c2 = shift @$rcl;
+ if (! defined $c1 || ! defined $c2) {
+ return finish_token(\%t, tag=> 'BAD', val=> $val);
+ }
+ $val .= $c1;
+ $val .= $c2;
+ return finish_token(\%t, tag => 'NUM', val=> $val,
+ nval=>ord($c2)<<8|ord($c1));
+ }
+
+ # universal ^ operator
+ if ($c eq '^') {
+ $val .= shift @$rcl;
+ $c = shift @$rcl;
+ if (not defined $c) {
+ return finish_token(\%t, tag=> 'BAD', val=> $val);
+ }
+ $val .= $c;
+ $c = lc($c);
+ if ($c eq 'c') {
+ return finish_token(\%t, tag=> 'OP', typ=> 'u', val=> $val);
+
+ } elsif ($c eq 'b') {
+ my $nval = 0;
+ while (scalar(@$rcl)) {
+ last if ($$rcl[0] !~ m/[0-9]/);
+ my $cc = shift @$rcl;
+ $nval = ($nval<<1) + int($cc);
+ add_err($rl, 'N') unless $cc =~ m/[0-1]/;
+ add_err($rl, 'T') unless $nval <= 0177777;
+ $nval &= 0177777;
+ $val .= $cc;
+ }
+ return finish_token(\%t, tag=> 'NUM', val=> $val, nval=> $nval);
+
+ } elsif ($c eq 'o') {
+ my $nval = 0;
+ while (scalar(@$rcl)) {
+ last if ($$rcl[0] !~ m/[0-9]/);
+ my $cc = shift @$rcl;
+ $nval = ($nval<<3) + int($cc);
+ add_err($rl, 'N') unless $cc =~ m/[0-7]/;
+ add_err($rl, 'T') unless $nval <= 0177777;
+ $nval &= 0177777;
+ $val .= $cc;
+ }
+ return finish_token(\%t, tag=> 'NUM', val=> $val, nval=> $nval);
+
+ } elsif ($c eq 'd') {
+ my $nval = 0;
+ while (scalar(@$rcl)) {
+ last if ($$rcl[0] !~ m/[0-9]/);
+ my $cc = shift @$rcl;
+ $nval = 10*$nval + int($cc);
+ add_err($rl, 'T') unless $nval <= 0177777;
+ $nval &= 0177777;
+ $val .= $cc;
+ }
+ return finish_token(\%t, tag=> 'NUM', val=> $val, nval=> $nval);
+
+ } elsif ($c eq 'x') {
+ my $nval = 0;
+ while (scalar(@$rcl)) {
+ last if ($$rcl[0] !~ m/[0-9a-fA-F]/);
+ my $cc = shift @$rcl;
+ $nval = ($nval<<4) + hex($cc);
+ add_err($rl, 'T') unless $nval <= 0177777;
+ $nval &= 0177777;
+ $val .= $cc;
+ }
+ return finish_token(\%t, tag=> 'NUM', val=> $val, nval=> $nval);
+
+ } elsif ($c eq 'r') {
+ my $nval = 0;
+ for (my $i=0; $i<3; $i++) {
+ last unless defined $$rcl[0];
+ last unless $$rcl[0] =~ m/^[0-9a-zA-Z\.\$\ ]$/;
+ $nval = 050 * $nval + to_rad50($$rcl[0]);
+ $val .= shift @$rcl;
+ }
+ return finish_token(\%t, tag=> 'NUM', val=> $val, nval=>$nval);
+
+ } else {
+ return finish_token(\%t, tag=> 'BAD', val=> $val);
+ }
+ }
+
+ # delimiters
+ if ($c =~ m|^[\(\)\,\<\>]$|) {
+ return finish_token(\%t, tag=> 'DEL', val=> shift @$rcl);
+ }
+
+ # can't handle stuff
+ $val = join('',@$rcl);
+ @$rcl = ();
+ return finish_token(\%t, tag=> 'BAD', val=> $val);
+}
+
+#-------------------------------------------------------------------------------
+
+sub to_rad50 {
+ my ($c) = @_;
+ return undef unless defined $c;
+ $c = lc($c);
+ return 0 if $c eq ' ';
+ return 001 + ord($c)-ord('a') if $c =~ m/^[a-z]$/;
+ return 033 if $c eq '$';
+ return 034 if $c eq '.';
+ return 036 + ord($c)-ord('0') if $c =~ m/^[0-9]$/;
+ return undef;
+}
+
+#-------------------------------------------------------------------------------
+
+sub pass2 {
+
+ my $fh;
+ if ($lst_do) {
+ if ($lst_fname eq "-") {
+ $fh = *STDOUT;
+ } else {
+ $fh = new FileHandle;
+ unless (open($fh, ">", $lst_fname)) {
+ print STDERR "asm-11-F: '$lst_fname' not writable, quiting..\n";
+ exit 1;
+ }
+ }
+ }
+
+ pass2_lst_beg($fh) if $lst_do;
+
+ foreach my $rl (@src) {
+
+ $$rl{dot} = getdot();
+ $llbl_scope = $$rl{lscope} if defined $$rl{lscope};
+
+ # handle label definitions
+ if (defined $$rl{label}) {
+ if (lst_checkmdef($$rl{label})) {
+ add_err($rl, 'M');
+ } else {
+ my $val = getsym($rl, $$rl{label}, 1);
+ if (! defined $val || $val != getdot()) {
+ add_err($rl, 'P');
+ }
+ }
+ }
+
+ # generate output data
+ pass2_out($rl);
+ # listing requested
+ pass2_lst_line($rl, $fh) if $lst_do;
+ # pass 2 dump requested
+ dump_rl($rl) if $opts{tpass2};
+
+ }
+
+ pass2_lst_end($fh) if $lst_do;
+
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub pass2_out {
+ my ($rl) = @_;
+
+ # quit without code generation for 'questionable syntax' lines
+ return if $$rl{err} =~ m/[IQ]/;
+
+ # return if no pass2 action (typ not defined)
+ return unless defined $$rl{typ};
+
+ # generate code
+ if ($$rl{typ} eq 'code') {
+ walign($rl);
+ my $opcode = $$rl{opcode};
+ my $opfmt = $$rl{opfmt};
+
+ # printf "+++1 $$rl{typ},$$rl{oper},%s,%s\n",
+ # savestr($opcode), savestr($opfmt);
+
+ if ($opfmt eq '-') {
+ out_opcode($rl, $opcode);
+
+ } elsif ($opfmt eq 'g') {
+ out_opcode($rl, $opcode | $$rl{o1mod}<<3 | $$rl{o1reg});
+ out_opdata($rl, $$rl{o1mod}, $$rl{o1reg},
+ $$rl{o1ebeg}, $$rl{o1eend});
+
+ } elsif ($opfmt eq 'gg') {
+ out_opcode($rl, $opcode | $$rl{o1mod}<<9 | $$rl{o1reg}<<6 |
+ $$rl{o2mod}<<3 | $$rl{o2reg});
+ out_opdata($rl, $$rl{o1mod}, $$rl{o1reg},
+ $$rl{o1ebeg}, $$rl{o1eend});
+ out_opdata($rl, $$rl{o2mod}, $$rl{o2reg},
+ $$rl{o2ebeg}, $$rl{o2eend});
+ } elsif ($opfmt eq 'r') {
+ out_opcode($rl, $opcode | $$rl{o1reg});
+ } elsif ($opfmt eq 'rg' || $opfmt eq 'gr') {
+ out_opcode($rl, $opcode | $$rl{o1reg}<<6 |
+ $$rl{o2mod}<<3 | $$rl{o2reg});
+ out_opdata($rl, $$rl{o2mod}, $$rl{o2reg},
+ $$rl{o2ebeg}, $$rl{o2eend});
+ } elsif ($opfmt eq 'n3') {
+ out_opcode_n($rl, $opcode, 07, $$rl{ebeg}, $$rl{eend});
+ } elsif ($opfmt eq 'n6') {
+ out_opcode_n($rl, $opcode, 077, $$rl{ebeg}, $$rl{eend});
+ } elsif ($opfmt eq 'n8') {
+ out_opcode_n($rl, $opcode, 0377, $$rl{ebeg}, $$rl{eend});
+ } elsif ($opfmt eq 's8') {
+ out_opcode_o($rl, $opcode, 's8', $$rl{ebeg}, $$rl{eend});
+ } elsif ($opfmt eq 'ru6') {
+ out_opcode_o($rl, $opcode|($$rl{o1reg}<<6), 'u6',
+ $$rl{ebeg}, $$rl{eend});
+ } else {
+ die "BUGCHECK: unknown opfmt '$opfmt'";
+ }
+
+ # generate data
+ } elsif ($$rl{typ} eq 'data') {
+ if ($$rl{oper} eq '.word' || $$rl{oper} eq '.byte' ) {
+ walign($rl) if $$rl{oper} eq '.word';
+ my $size = ($$rl{oper} eq '.word') ? 2 : 1;
+ my $mask = ($size == 2) ? 0177777 : 0377;
+ foreach (@{$$rl{delist}}) {
+ my $ibeg = $$_{ibeg};
+ my $iend = $$_{iend};
+ my $val = 0;
+ if (defined $ibeg) {
+ $val = eval_exp($rl, $ibeg, $iend);
+ if (not defined $val) {
+ $val = 0;
+ add_err($rl, 'U');
+ }
+ }
+ # FIXME_code: handle T error here !!
+ $val &= $mask;
+ if ($$rl{oper} eq '.word') {
+ out_w($rl, $val);
+ } else {
+ out_b($rl, $val);
+ }
+ }
+
+ } elsif ($$rl{oper} eq '.blkw' || $$rl{oper} eq '.blkb' ) {
+ walign($rl) if $$rl{oper} eq '.blkw';
+ incdot($$rl{incdot});
+
+ } elsif ($$rl{oper} eq '.ascii' || $$rl{oper} eq '.asciz' ) {
+ foreach my $rd (@{$$rl{delist}}) {
+ if (defined $$rd{str}) {
+ my @chr = split '',$$rd{str};
+ shift @chr;
+ pop @chr;
+ foreach (@chr) {
+ push @{$$rl{outb}}, ord($_);
+ }
+ } else {
+ my $val = eval_exp($rl, $$rd{ibeg}, $$rd{iend});
+ if (not defined $val) {
+ $val = 0;
+ add_err($rl, 'U');
+ }
+ if ($val < 0 || $val > 0377) {
+ $val &= 0377;
+ add_err($rl, 'T');
+ }
+ push @{$$rl{outb}}, $val;
+ }
+ }
+ push @{$$rl{outb}}, 0 if $$rl{oper} eq '.asciz';
+ incdot(scalar(@{$$rl{outb}}));
+
+ } elsif ($$rl{oper} eq '.even' || $$rl{oper} eq '.odd' ) {
+ if ($$rl{incdot}) {
+ push @{$$rl{outb}}, 0;
+ incdot(1);
+ }
+
+ } else {
+ die "BUGCHECK: unknown data oper '$$rl{oper}'";
+ }
+
+ # handle assignments
+ } elsif ($$rl{typ} eq 'ass') {
+ my $val = eval_exp($rl, $$rl{ebeg}, $$rl{eend});
+ if (defined $val) {
+ $$rl{lstval} = $val;
+ setsym($rl, $$rl{atyp}, $$rl{asym}, $val);
+ } else {
+ $$rl{lstval} = 0;
+ add_err($rl, 'U');
+ }
+
+ } else {
+ die "BUGCHECK: unknown line typ '$$rl{typ}'";
+ }
+
+ if (scalar(@{$$rl{outw}})) {
+ emitw($$rl{dot}, $$rl{outw});
+ } elsif (scalar(@{$$rl{outb}})) {
+ emitb($$rl{dot}, $$rl{outb});
+ }
+
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub pass2_lst_beg {
+ my ($fh) = @_;
+ printf $fh "; Input file list:\n";
+ my $fileno = 1;
+ foreach my $fname (@flist) {
+ $fname =~ s/^$ENV{RETROBASE}/\$RETROBASE/;
+ printf $fh "; %2d: %s\n", $fileno, $fname;
+ $fileno += 1;
+ }
+ print $fh ";\n";
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub pass2_lst_end {
+ my ($fh) = @_;
+ if ($errcnt_tot) {
+ print $fh ";\n";
+ print $fh "; Error summary:\n";
+ foreach my $err (sort keys %errcnt) {
+ printf $fh "; %s: %3d\n", $err, $errcnt{$err};
+ }
+ }
+ return;
+}
+
+#-------------------------------------------------------------------------------
+# line format is
+# er fn lnum dot source
+# .. dd dddd oooooo oooooo oooooo oooooo
+# .. ooo ooo ooo ooo ooo
+
+sub pass2_lst_line {
+ my ($rl,$fh) = @_;
+
+ my @ow = @{$$rl{outw}};
+ my @ob = @{$$rl{outb}};
+ my $str = '';
+ $str .= sprintf("%-2s", prt_err($rl));
+ $str .= sprintf(" %2d", $$rl{fileno});
+ $str .= sprintf(" %4d", $$rl{lineno});
+
+ # print dot if data is generated for this line, or label
+ my $prtdot = defined $$rl{lstdot} ||
+ scalar(@{$$rl{outw}}) ||
+ scalar(@{$$rl{outb}}) ||
+ $$rl{label};
+ if ($prtdot) {
+ $str .= prt76o($$rl{dot});
+ } else {
+ $str .= ' ';
+ }
+
+ if (defined $$rl{lstval}) {
+ $str .= prt76o($$rl{lstval});
+ $str .= ' ' x 14;
+ } elsif (scalar(@ow)) {
+ for (my $i=0; $i<3; $i++) { $str .= prt76o(shift @ow); }
+ } elsif (scalar(@ob)) {
+ for (my $i=0; $i<5; $i++) { $str .= prt43o(shift @ob); }
+ $str .= ' ';
+ } else {
+ $str .= ' ' x 21;
+ }
+
+ $str .= ' ' . $$rl{line} . "\n";
+ print $fh $str;
+ if (1) {
+ while (scalar(@ow)) {
+ $str = ' ';
+ for (my $i=0; $i<3; $i++) { $str .= prt76o(shift @ow); }
+ print $fh $str . "\n";
+ }
+ while (scalar(@ob)) {
+ $str = ' ';
+ for (my $i=0; $i<5; $i++) { $str .= prt43o(shift @ob); }
+ print $fh $str . "\n";
+ }
+ }
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub out_w {
+ my ($rl,$word) = @_;
+ push @{$$rl{outw}}, $word;
+ incdot(2);
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub out_b {
+ my ($rl,$byte) = @_;
+ push @{$$rl{outb}}, $byte;
+ incdot(1);
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub out_opcode {
+ my ($rl,$code) = @_;
+ out_w($rl, $code);
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub out_opcode_n {
+ my ($rl,$code,$mask,$ebeg,$eend) = @_;
+ # FIXME_code: shouldn't we die here ?
+ return unless defined $ebeg;
+
+ my $val = eval_exp($rl,$ebeg,$eend);
+ unless (defined $val) {
+ $val = 0;
+ add_err($rl, 'A');
+ }
+ if ($val & ~$mask) {
+ $val &= $mask;
+ add_err($rl, 'T');
+ }
+ out_w($rl, $code|$val);
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub out_opcode_o {
+ my ($rl,$code,$typ,$ebeg,$eend) = @_;
+ # FIXME_code: shouldn't we die here ?
+ return unless defined $ebeg;
+
+ my $val = eval_exp($rl,$ebeg,$eend);
+ my $off;
+ if (defined $val) {
+ $off = ($val - (getdot()+2)) / 2;
+ } else {
+ $off = -1;
+ add_err($rl, 'U');
+ }
+
+ if ($typ eq 's8') {
+ if ($off > 127 || $off < -128) {
+ add_err($rl, 'A');
+ }
+ $off &= 0377;
+ } else {
+ $off = -$off;
+ if ($off > 63 || $off < 0) {
+ add_err($rl, 'A');
+ }
+ $off &= 0077;
+ }
+ out_w($rl, $code|$off);
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub out_opdata {
+ my ($rl,$mod,$reg,$ebeg,$eend) = @_;
+ # FIXME_code: shouldn't we die here ?
+ return unless defined $ebeg;
+
+ my $val = eval_exp($rl,$ebeg,$eend);
+ unless (defined $val) {
+ out_w($rl, 0);
+ add_err($rl, 'U');
+ return;
+ }
+ if ($mod>=6 && $reg==7) {
+ $val = ($val - (getdot()+2)) & 0177777;
+ }
+ out_w($rl, $val);
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub emitw {
+ my ($baddr,$rwl) = @_;
+ if ($opts{temit}) {
+ printf "-- emit: w %6.6o:", $baddr;
+ foreach my $w (@$rwl) { printf " %6.6o", $w; }
+ print "\n";
+ }
+ return unless scalar(@$rwl);
+
+ if ((! defined $out_dot) || $out_dot!=$baddr || $out_data[-1]->{typ} ne 'w') {
+ push @out_data, {typ=> 'w', addr=>$baddr, data=>[@$rwl]};
+ } else {
+ my $rdata = $out_data[-1]->{data};
+ push @$rdata, @$rwl;
+ }
+ $out_dot = $baddr+2;
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub emitb {
+ my ($baddr,$rbl) = @_;
+ if ($opts{temit}) {
+ printf "-- emit: b %6.6o:", $baddr;
+ foreach my $b (@$rbl) { printf " %3.3o", $b; }
+ print "\n";
+ }
+ return unless scalar(@$rbl);
+
+ if ((! defined $out_dot) || $out_dot!=$baddr || $out_data[-1]->{typ} ne 'b') {
+ push @out_data, {typ=> 'b', addr=>$baddr, data=>[@$rbl]};
+ } else {
+ my $rdata = $out_data[-1]->{data};
+ push @$rdata, @$rbl;
+ }
+ $out_dot = $baddr+1;
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub write_lda_frame {
+ my ($fh,$addr,$rblist) = @_;
+ my $len = 6 + scalar(@$rblist);
+ my @f;
+ push @f, 0x01;
+ push @f, 0x00;
+ push @f, $len & 0xff;
+ push @f, ($len>>8) & 0xff;
+ push @f, $addr & 0xff;
+ push @f, ($addr>>8) & 0xff;
+ push @f, @$rblist if $len;
+ my $csum = 0;
+ foreach (@f) { $csum = ($csum + $_) & 0xff; }
+ push @f, (-$csum) & 0xff;
+
+ if ($opts{tout}) {
+ my $nval = 0;
+ printf "-- out: %6.6o:", $addr;
+ foreach (@f) {
+ if ($nval == 16) {
+ printf "\n ";
+ $nval = 0;
+ }
+ printf " %3.3o", $_;
+ $nval += 1;
+ }
+ printf "\n";
+ }
+
+ my $buf = pack("C*", @f);
+ my $rc = syswrite($fh, $buf, length($buf));
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub write_lda {
+ my ($fname) = @_;
+ my $fh;
+ if ($fname eq "-") {
+ $fh = *STDOUT;
+ } else {
+ $fh = new FileHandle;
+ unless (open($fh, ">:raw", $fname)) {
+ print STDERR "asm-11-F: '$fname' not writable, quiting..\n";
+ exit 1;
+ }
+ }
+
+ my @blist;
+ my $base;
+ my $dot;
+ foreach my $rl (@src) {
+ die "BUGCHECK: both outb and outw contain data"
+ if scalar(@{$$rl{outb}}) && scalar(@{$$rl{outw}});
+
+ my @byt = @{$$rl{outb}};
+ foreach (@{$$rl{outw}}) {
+ push @byt, $_ & 0xff;
+ push @byt, ($_>>8) & 0xff;
+ }
+
+ next unless scalar(@byt);
+
+ # flush frame if new data not adjacent to old
+ if (scalar(@blist) && $dot!=$$rl{dot}) {
+ write_lda_frame($fh, $base, \@blist);
+ @blist = ();
+ $base = undef;
+ $dot = undef;
+ }
+
+ $dot = $base = $$rl{dot} unless defined $base;
+
+ foreach (@byt) {
+ if (scalar(@blist) >= 2*168) {
+ write_lda_frame($fh, $base, \@blist);
+ @blist = ();
+ $base = $dot;
+ }
+ push @blist, $_ & 0xff;
+ $dot += 1;
+ }
+
+ }
+
+ # flush buffer
+ write_lda_frame($fh, $base, \@blist) if scalar(@blist);
+ @blist = ();
+
+ # write terminating frame
+ write_lda_frame($fh, $out_start, \@blist);
+
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub write_cof_frame {
+ my ($fh,$typ,$addr,$rlist) = @_;
+ my $fmt = ($typ eq 'w') ? '%6.6o' : '%3.3o';
+ my $max = ($typ eq 'w') ? 10 : 20 ;
+
+ printf $fh "$typ %6.6o {\n", $addr;
+ my $i = 0;
+ foreach (@$rlist) {
+ $i += 1;
+ printf $fh "$fmt ", $_;
+ print $fh "\n" if $i%$max == 0;
+ }
+ print $fh "\n" unless $i%$max == 0;
+ print $fh "}\n";
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub write_cof {
+ my ($fname) = @_;
+ my $fh;
+ if ($fname eq "-") {
+ $fh = *STDOUT;
+ } else {
+ $fh = new FileHandle;
+ unless (open($fh, ">:raw", $fname)) {
+ print STDERR "asm-11-F: '$fname' not writable, quiting..\n";
+ exit 1;
+ }
+ }
+
+ print $fh "sym {\n";
+ foreach my $key (sort keys %lst) {
+ next unless $lst{$key}{typ} =~ m/^(lbl|llbl)$/;
+ printf $fh "%s => %s\n", $lst{$key}{name}, save66o($lst{$key}{val});
+ }
+ print $fh "}\n";
+ print $fh "dat {\n";
+
+ my @list;
+ my $typ;
+ my $base;
+ my $dot;
+
+ foreach my $rl (@src) {
+
+ if (scalar(@{$$rl{outb}})) {
+ if (scalar(@list) && ($typ ne 'b' || $dot != $$rl{dot})) {
+ write_cof_frame($fh, $typ, $base, \@list);
+ @list = ();
+ }
+ unless (scalar(@list)) {
+ $typ = 'b';
+ $base = $dot = $$rl{dot};
+ }
+ push @list, @{$$rl{outb}};
+ $dot += scalar(@{$$rl{outb}});
+ }
+
+ if (scalar(@{$$rl{outw}})) {
+ if (scalar(@list) && ($typ ne 'w' || $dot != $$rl{dot})) {
+ write_cof_frame($fh, $typ, $base, \@list);
+ @list = ();
+ }
+ unless (scalar(@list)) {
+ $typ = 'w';
+ $base = $dot = $$rl{dot};
+ }
+ push @list, @{$$rl{outw}};
+ $dot += 2 * scalar(@{$$rl{outw}});
+ }
+ }
+
+ write_cof_frame($fh, $typ, $base, \@list)
+ if scalar(@list);
+
+ print $fh "}\n";
+
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub write_lsm {
+ my ($fname) = @_;
+ my $fh;
+ if ($fname eq "-") {
+ $fh = *STDOUT;
+ } else {
+ $fh = new FileHandle;
+ unless (open($fh, ">:raw", $fname)) {
+ print STDERR "asm-11-F: '$fname' not writable, quiting..\n";
+ exit 1;
+ }
+ }
+
+ my %mem;
+
+ foreach my $rl (@src) {
+
+ my $dot = $$rl{dot};
+ if (scalar(@{$$rl{outb}})) {
+ foreach my $byte (@{$$rl{outb}}) {
+ my $addr = sprintf "%6.6o", $dot & 0xfffe;
+ $mem{$addr} = 0 unless exists $mem{$addr};
+ if ($dot & 0x1) { # odd byte
+ $mem{$addr} = (($byte&0xff)<<8) | ($mem{$addr} & 0xff);
+ } else { # even byte
+ $mem{$addr} = ($mem{$addr} & 0xff00) | ($byte&0xff);
+ }
+ $dot += 1;
+ }
+ }
+
+ if (scalar(@{$$rl{outw}})) {
+ foreach my $word (@{$$rl{outw}}) {
+ my $addr = sprintf "%6.6o", $dot;
+ $mem{$addr} = $word;
+ $dot += 2;
+ }
+ }
+ }
+
+ foreach my $addr (sort keys %mem) {
+ printf $fh "%s : %6.6o\n", $addr, $mem{$addr};
+ }
+
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub dump_rl {
+ my ($rl) = @_;
+
+ printf "-- line: '%s'\n", $$rl{line};
+ printf " err=%-3s, typ=%-4s, oper=%-6s, lineno=%3d, psect=%-6s, .=%6.6o\n",
+ prt_err($rl), savestr($$rl{typ}), savestr($$rl{oper}), $$rl{lineno},
+ $$rl{psect}, $$rl{dot};
+ my $i = 0;
+ foreach my $rt (@{$$rl{tl}}) {
+ printf " tl[%2d]: tag=%-4s, om=%-2s, em=%-2s, val='%s'",
+ $i, $$rt{tag}, savestr1($$rt{om}), savestr1($$rt{em}),
+ savestr($$rt{val});
+ printf ", nval=%6.6o",$$rt{nval} if defined $$rt{nval};
+ printf ", pend=%d",$$rt{pend} if defined $$rt{pend};
+ printf "\n";
+ $i += 1;
+ }
+ if (defined $$rl{delist}) {
+ $i = 0;
+ my $rdl = $$rl{delist};
+ foreach my $rd (@$rdl) {
+ printf " dl[%2d]:", $i;
+ printf " str='%s'",$$rd{str} if defined $$rd{str};
+ printf " ibeg=%s, iend=%s", savestr($$rd{ibeg}), savestr($$rd{iend})
+ if exists $$rd{ibeg};
+ printf "\n";
+ $i += 1;
+ }
+ }
+ if (defined $$rl{opcode}) {
+ printf " code: %6.6o,fmt=%-2s", $$rl{opcode}, $$rl{opfmt};
+ if (defined $$rl{o1mod}) {
+ printf ", o1=%s%s", $$rl{o1mod},$$rl{o1reg};
+ printf ",ei=%d:%d,val=%s", $$rl{o1ebeg}, $$rl{o1eend},
+ save66o(eval_exp($rl, $$rl{o1ebeg}, $$rl{o1eend}))
+ if defined $$rl{o1ebeg};
+ }
+ if (defined $$rl{o2mod}) {
+ printf ", o2=%s%s", $$rl{o2mod},$$rl{o2reg};
+ printf ",ei=%d:%d,val=%s", $$rl{o2ebeg}, $$rl{o2eend},
+ save66o(eval_exp($rl, $$rl{o2ebeg}, $$rl{o2eend}))
+ if defined $$rl{o2ebeg};
+ }
+ printf " ex=%d:%d,val=%s", $$rl{ebeg}, $$rl{eend},
+ save66o(eval_exp($rl, $$rl{ebeg}, $$rl{eend}))
+ if defined $$rl{ebeg};
+ print "\n";
+ }
+ if (scalar(@{$$rl{outw}})) {
+ print " outw:";
+ foreach (@{$$rl{outw}}) { printf " %6.6o", $_; }
+ print "\n";
+ }
+ if (scalar(@{$$rl{outb}})) {
+ print " outb:";
+ foreach (@{$$rl{outb}}) { printf " %3.3o", $_; }
+ print "\n";
+ }
+ foreach my $key (sort keys %{$rl}) {
+ next if $key =~ m/^(line|err|typ|oper|lineno|psect|dot|opcode|opfmt|o[12](mod|reg|ebeg|eend)|ebeg|eend|tl|delist|outw|outb)$/;
+ printf " %-6s: %s\n", $key, savestr($$rl{$key});
+ }
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub dump_sym {
+ print "\n";
+ print " psect dot dotmax\n";
+ print "------ ------ ------\n";
+ foreach my $ps (sort keys %psect) {
+ printf "%-6s %6.6o %6.6o\n", $ps, $psect{$ps}{dot}, $psect{$ps}{dotmax};
+ }
+
+ print "\n";
+ print "scope symbol typ psect val\n";
+ print "------ ------ ---- ------ ------\n";
+ foreach my $key (sort keys %lst) {
+ my $sym = $lst{$key}{name};
+ my $scope = '';
+ my $name = $sym;
+ if ($sym =~ m/^(.+):(.+)$/) {
+ $scope = $1;
+ $name = $2;
+ }
+ printf "%-6s %-6s %-4s %-6s %s\n", $scope, $name, $lst{$key}{typ},
+ $lst{$key}{psect}, save66o($lst{$key}{val});
+ }
+
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub prt76o {
+ my ($val) = @_;
+ return ' ' unless defined $val;
+ return sprintf " %6.6o", $val;
+}
+
+#-------------------------------------------------------------------------------
+
+sub prt43o {
+ my ($val) = @_;
+ return ' ' unless defined $val;
+ return sprintf " %3.3o", $val;
+}
+
+#-------------------------------------------------------------------------------
+
+sub save66o {
+ my ($val) = @_;
+ return '' unless defined $val;
+ return sprintf "%6.6o", $val;
+}
+
+#-------------------------------------------------------------------------------
+
+sub savestr {
+ my ($str) = @_;
+ return '' unless defined $str;
+ return $str;
+}
+
+#-------------------------------------------------------------------------------
+
+sub savestr1 {
+ my ($str) = @_;
+ return '-' unless defined $str;
+ return $str;
+}
+
+#-------------------------------------------------------------------------------
+
+sub print_help {
+ print "usage: asm-11 [OPTIONS]... [FILE]...\n";
+ print " --I=path adds path to the .include search path\n";
+ print " --lst create listing (default file name)\n";
+ print " --olst=fnam create listing (concrete file name)\n";
+ print " --lda create absolute loader output (default file name)\n";
+ print " --olda create absolute loader output (concrete file name)\n";
+ print " --cof create compound output (default file name)\n";
+ print " --ocof=fnam create compound output (concrete file name)\n";
+ print " --tpass1 trace line context in pass 1\n";
+ print " --tpass2 trace line context in pass 2\n";
+ print " --dsym1 dump psect and ust tables after pass 1\n";
+ print " --dsym2 dump psect and ust tables after pass 2\n";
+ print " --ttoken trace tokenizer\n";
+ print " --tparse trace parser\n";
+ print " --temit trace code emit\n";
+ print " --tout trace output file write\n";
+ print " --help print this text and exit\n";
+ return;
+}
asm-11
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: ti_w11
===================================================================
--- ti_w11 (nonexistent)
+++ ti_w11 (revision 33)
@@ -0,0 +1,307 @@
+#!/usr/bin/perl -w
+# $Id: ti_w11 680 2015-05-14 13:29:46Z mueller $
+#
+# Copyright 2013-2015 by Walter F.J. Mueller
+# License disclaimer see LICENSE_gpl_v2.txt in $RETROBASE directory
+#
+# Revision History:
+# Date Rev Version Comment
+# 2015-05-14 680 1.3.1 use now -f1,-f1e,-f2,-f2e (fx now f1e)
+# 2015-04-13 667 1.3 rename -fu->-fc, add -f2,-fx; setup good defaults
+# 2015-01-02 640 1.2.2 BUGFIX: allow 'M' unit in baud rates
+# 2014-12-23 619 1.2.1 use -fifo tbw option for test bench starts
+# 2014-07-13 570 1.2 BUGFIX: split options args into ti_rri opts and cmds
+# 2013-05-05 516 1.1 renamed to ti_w11
+# 2013-04-26 510 1.0 Initial version (derived from dorri)
+#
+
+use 5.005; # require Perl 5.005 or higher
+use strict; # require strict checking
+use FileHandle;
+
+sub print_usage;
+
+autoflush STDOUT 1; # autoflush, so nothing lost on exec later
+
+my $sysbase = "$ENV{RETROBASE}/rtl/sys_gen/w11a";
+
+my $opt_dry;
+my $opt_b;
+my $opt_io = '';
+my $opt_f = '';
+my $opt_tmu;
+my $tirri;
+my $val_term;
+my $val_tb_s3 = "tbw $sysbase/s3board/tb/tb_w11a_s3 -fifo";
+my $val_tb_n2 = "tbw $sysbase/nexys2/tb/tb_w11a_n2 -fifo";
+my $val_tb_n3 = "tbw $sysbase/nexys3/tb/tb_w11a_n3 -fifo";
+my $val_tb_b3 = "tbw $sysbase/basys3/tb/tb_w11a_b3 -fifo";
+my $val_tb_n4 = "tbw $sysbase/nexys4/tb/tb_w11a_n4 -fifo";
+my $val_tb_bn4 = "tbw $sysbase/nexys4_bram/tb/tb_w11a_br_n4 -fifo";
+my $val_tb;
+my $val_e;
+
+my @arglist;
+
+#
+# process ti_w11 options
+#
+while (scalar(@ARGV)) {
+ my $curarg = $ARGV[0];
+
+ if ($curarg =~ m{^-dry$} ) { # -dry
+ $opt_dry = 1;
+ shift @ARGV;
+
+ } elsif ($curarg =~ m{^-b$} ) { # -b
+ $opt_b = 1;
+ shift @ARGV;
+
+ } elsif ($curarg =~ m{^-tmu$} ) { # -tmu
+ $opt_tmu = 1;
+ shift @ARGV;
+
+ } elsif ($curarg =~ m{^-s3$} ) { # -s3 (use -f2 by default)
+ $opt_io = 'f';
+ $opt_f = '2';
+ $val_tb = $val_tb_s3;
+ shift @ARGV;
+
+ } elsif ($curarg =~ m{^-n2$} ) { # -n2 (use -fc by default)
+ $opt_io = 'f';
+ $opt_f = 'c';
+ $val_tb = $val_tb_n2;
+ shift @ARGV;
+
+ } elsif ($curarg =~ m{^-n3$} ) { # -n3 (use -fc by default)
+ $opt_io = 'f';
+ $opt_f = 'c';
+ $val_tb = $val_tb_n3;
+ shift @ARGV;
+
+ } elsif ($curarg =~ m{^-b3$} ) { # -b3 (use -f1x by default)
+ $opt_io = 'f';
+ $opt_f = '1x';
+ $val_tb = $val_tb_b3;
+ shift @ARGV;
+
+ } elsif ($curarg =~ m{^-n4$} ) { # -n4 (prim serport fine)
+ $opt_io = 'f';
+ $opt_f = '1';
+ $val_tb = $val_tb_n4;
+ shift @ARGV;
+
+ } elsif ($curarg =~ m{^-bn4$} ) { # -bn4 (prim serport fine)
+ $opt_io = 'f';
+ $opt_f = '1';
+ $val_tb = $val_tb_bn4;
+ shift @ARGV;
+
+ } elsif ($curarg =~ m{^-f(c|1|1x|2|2x)$} ) { # -f..
+ $opt_f = $1;
+ shift @ARGV;
+
+ } elsif ($curarg =~ m{^-t([su])(\d?),?} ) { # -t[su]...
+ my $devnam = ($1 eq 's') ? '/dev/ttyS' : '/dev/ttyUSB';
+ my $devnum = $2;
+ my ($dev,$baud,$opt1,$opt2) = split /,/,$curarg;
+ $baud = '115k' unless defined $baud;
+
+ if ($baud !~ m{^\d*[kM]?$}) {
+ print STDERR "ti_w11-E: invalid format of -ts or -tu option\n";
+ exit 1;
+ }
+
+ $opt_io = 't';
+ $val_term = sprintf '%s%d,%s', $devnam, $devnum, $baud;
+ $val_term .= ",$opt1" if defined $opt1;
+ $val_term .= ",$opt2" if defined $opt2;
+ shift @ARGV;
+
+ } elsif ($curarg =~ m{^-u$} ) { # -u
+ $opt_io = 'u';
+ shift @ARGV;
+
+ } elsif ($curarg =~ m{^-e$} ) { # -e
+ print STDERR "ti_w11-W: multiple -e options, only last taken\n"
+ if defined $val_e;
+ shift @ARGV;
+ if (scalar(@ARGV) == 0 || $ARGV[0] =~ m{^-}) {
+ print STDERR "ti_w11-E: no file name after -e option\n";
+ exit 1;
+ } else {
+ $val_e = shift @ARGV;
+ if (not -r $val_e) {
+ print STDERR "ti_w11-E: file '$val_e' not found\n";
+ exit 1;
+ }
+ }
+ } else {
+ last;
+ }
+}
+
+#
+# process remaining arguments, separate ti_rri options and commands
+#
+
+# handle options (all starting with -)
+my @tiopts;
+while (scalar(@ARGV)) {
+ last unless $ARGV[0] =~ m{^--};
+ push @tiopts, shift @ARGV;
+}
+
+# handle comands
+my @ticmds;
+while (scalar(@ARGV)) {
+ my $curarg = shift @ARGV;
+ if ($curarg =~ m{^@(.*)$} && ! -r $1) {
+ print STDERR "ti_w11-E: file '$1' not found\n";
+ exit 1;
+ }
+ push @ticmds,$curarg;
+}
+
+#
+# check that either -(s3|n2|n3|n4|bn4) or -t or -u given
+# setup options for either case
+#
+
+if ($opt_io eq 'f') {
+ my $fifoopts = ",noinit"; # fifo always with deferred init
+ $fifoopts .= ",xon" if $opt_f eq 'x';
+ push @arglist, "--fifo=$fifoopts";
+ push @arglist, "--run=$val_tb";
+} elsif ($opt_io eq 't') {
+ push @arglist, "--term=$val_term";
+} elsif ($opt_io eq 'u') {
+ push @arglist, '--cuff';
+} else {
+ print STDERR "ti_w11-E: neither -(s3|n2|n3|b3|n4|bn4) nor -t,-u specified\n";
+ print_usage();
+ exit 1;
+}
+
+#
+# setup all other ti_rri options
+#
+
+push @arglist, '--logl=2';
+push @arglist, '--int' unless $opt_b;
+push @arglist, '--pack=rw11';
+push @arglist, @tiopts; # add options from ARGV
+push @arglist, '--';
+
+#
+# actions prior to first exec
+# setup tmu ect
+# setup access path --> handle -f options
+#
+if ($opt_io eq 'f') {
+ if ($opt_tmu) {
+ push @arglist, 'rlc oob -sbcntl 13 1';
+ }
+ if ($opt_f eq 'c') {
+ push @arglist, 'rlc oob -sbdata 8 0x4'; # portsel = 0100 -> fx2
+ push @arglist, 'rlc oob -sbdata 16 0x4'; # swi = 0100 -> fx2
+ } elsif ($opt_f eq '1x') {
+ push @arglist, 'rlc oob -sbdata 8 0x2'; # portsel = 0010 -> 1st ser XON
+ push @arglist, 'rlc oob -sbdata 16 0x2'; # swi = 0010 -> 1st ser XON
+ } elsif ($opt_f eq '2') {
+ push @arglist, 'rlc oob -sbdata 8 0x1'; # portsel = 0001 -> 2nd ser
+ push @arglist, 'rlc oob -sbdata 16 0x1'; # swi = 0001 -> 2nd ser
+ } elsif ($opt_f eq '2x') {
+ push @arglist, 'rlc oob -sbdata 8 0x3'; # portsel = 0011 -> 2nd ser XON
+ push @arglist, 'rlc oob -sbdata 16 0x3'; # swi = 0011 -> 2nd ser XON
+ }
+}
+
+#
+# --fifo always uses deferred init, so add a rlc init after the oob's
+#
+push @arglist, 'rlc init' if $opt_io eq 'f';
+
+#
+# initialize w11 cpu system
+#
+push @arglist, 'rw11::setup_sys';
+
+#
+# handle -e option
+#
+
+if (defined $val_e) {
+ if ($val_e =~ m/\.mac$/) {
+ push @arglist, "cpu0 ldasm -file $val_e -sym ldasm_sym -lst ldasm_lst";
+ } else {
+ push @arglist, "cpu0 ldabs $val_e";
+ }
+ push @arglist, 'rw11::cpumon';
+ push @arglist, 'rw11::cpucons';
+ push @arglist, 'cpu0 cp -stapc 0200';
+}
+
+push @arglist, @ticmds; # add commands from ARGV
+
+#
+# find ti_rri executable
+#
+
+$tirri=`which ti_rri`;
+chomp $tirri;
+if ($tirri eq '' || ! -e $tirri) {
+ print STDERR "ti_w11-E: failed to locate ti_rri\n";
+ exit 1;
+}
+
+#
+# print command line
+#
+if (1) {
+ print 'ti_rri ', join (' ', map {(m{\s}) ? "\"$_\"" : $_} @arglist) , "\n";
+}
+
+#
+# if dry run, stop here
+#
+exit 0 if $opt_dry;
+#
+# and do it
+#
+exec $tirri, @arglist
+ or die "failed to exec: $!";
+
+exit 1;
+
+# ----------------------------------------------------------------------------
+sub print_usage {
+ print "usage: ti_w11 ...\n";
+ print " setup options for ghdl simulation runs:\n";
+ print " -b3 start tb_w11a_b3 simulation (default: -f1x)\n";
+ print " -n4 start tb_w11a_n4 simulation\n";
+ print " -bn4 start tb_w11a_br_n4 simulation\n";
+ print " -n3 start tb_w11a_n3 simulation (default: -fc)\n";
+ print " -n2 start tb_w11a_n2 simulation (default: -fc)\n";
+ print " -s3 start tb_w11a_s3 simulation (default: -f2)\n";
+ print " -f.. simulation communication options\n";
+ print " -fc use fx2 data path (cuff)\n";
+ print " -f1 use 1st serport\n";
+ print " -f1x use 1st serport with xon\n";
+ print " -f2 use 2nd serport (fusp)\n";
+ print " -f2x use 2nd serport with xon\n";
+ print " -tmu activate trace and monitoring unit\n";
+ print " setup options for FPGA connects:\n";
+ print " -u use --cuff connect\n";
+ print " -t.. use --term connect\n";
+ print " -ts*[,opts] use /dev/ttyS* (* is device number)\n";
+ print " -tu*[,opts] use /dev/ttyUSB* (* is device number)\n";
+ print " opts can be ',break', ',xon'\n";
+ print " common options:\n";
+ print " -e load and execute file\n";
+ print " file type '.mac': on the fly compile with asm-11\n";
+ print " any other file type: assume lda format\n";
+ print "\n";
+ print " either one of -s3,-n2,-n3,-b3,-n4,-bn4 must be given -> sim run\n";
+ print " or one of -t or -u must be given -> fpga run\n";
+}
ti_w11
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xise_msg_filter
===================================================================
--- xise_msg_filter (nonexistent)
+++ xise_msg_filter (revision 33)
@@ -0,0 +1,214 @@
+#!/usr/bin/perl -w
+# $Id: xise_msg_filter 646 2015-02-15 12:04:55Z mueller $
+#
+# Copyright 2011-2015 by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Version Comment
+# 2015-01-30 640 1.1.2 renamed from isemsg_filter
+# 2014-02-01 550 1.1.1 rename --pack to --pacc (accepted is meant here)
+# 2012-01-04 450 1.1 preliminary check for par 'all constraints met'
+# 2011-08-14 406 1.0 Initial version
+#
+
+use 5.005; # require Perl 5.005 or higher
+use strict; # require strict checking
+use FileHandle;
+
+use Getopt::Long;
+
+my %opts = ();
+
+GetOptions(\%opts, "help", "pacc") || exit 1;
+
+sub print_help;
+sub read_mfs;
+sub read_log;
+
+my $type = shift @ARGV;
+my $mfsnam = shift @ARGV;
+my $lognam = shift @ARGV;
+my @flist;
+my @mlist;
+my $nackcnt = 0;
+my $ackcnt = 0;
+my $misscnt = 0;
+
+
+autoflush STDOUT 1; # autoflush, so nothing lost on exec later
+
+if (exists $opts{help}) {
+ print_help;
+ exit 0;
+}
+
+if (!defined $type || !defined $mfsnam || !defined $lognam) {
+ print STDERR "xise_msg_filter-E: one of 'type mfset log' missing \n\n";
+ print_help;
+ exit 1;
+}
+
+if ($type !~ m{^(xst|tra|map|par|twr|bgn)$}) {
+ print STDERR "xise_msg_filter-E: type must be xst,tra,map,par,twr, or bgn\n";
+ exit 1;
+}
+
+if (read_mfs()) {exit 1;}
+if (read_log()) {exit 1;}
+
+foreach (@mlist) {
+ my $msgorig = $_->[0];
+ my $msgflat = $_->[1];
+ my $msgmatch = 0;
+ foreach (@flist) {
+ my $filt = $_->[0];
+ if ($msgflat =~ m{$filt}) {
+ $_->[1] += 1;
+ $msgmatch = 1;
+ last;
+ }
+ }
+ if ($msgmatch) {
+ $_->[2] += 1;
+ } else {
+ $nackcnt += 1;
+ }
+}
+
+if ($nackcnt) {
+ print "Unexpected messages of type [$type] from $lognam:\n";
+ foreach (@mlist) {
+ next if $_->[2];
+ print $_->[0] . "\n";
+ }
+ print "\n";
+}
+
+foreach (@flist) {
+ if ($_->[1]) {
+ $ackcnt += 1;
+ } else {
+ $misscnt += 1;
+ }
+}
+
+if ($ackcnt && exists $opts{pacc}) {
+ print "Accepted messages of type [$type] from $lognam:\n";
+ foreach (@flist) {
+ next if $_->[1] == 0;
+ printf "%4d: %s\n", $_->[1], $_->[0];
+ }
+ print "\n";
+}
+
+if ($misscnt) {
+ print "Missed messages of type [$type] from $lognam:\n";
+ foreach (@flist) {
+ next if $_->[1] != 0;
+ printf "%4d: %s\n", $_->[1], $_->[0];
+ }
+ print "\n";
+}
+
+#-------------------------------------------------------------------------------
+sub read_mfs {
+ if (not -r $mfsnam) {
+ print STDERR "xise_msg_filter-E: \'$mfsnam\' not existing or readable\n";
+ return 1;
+ }
+
+ open (FFILE, $mfsnam) or die "can't open for read $mfsnam: $!";
+
+ my $intyp = 0;
+
+ while () {
+ chomp;
+ next if /^\s*#/; # drop comments
+ next if /^\s*$/; # drop empty lines
+
+ if (m{^\[([a-z]{3})\]$}) {
+ if ($1 eq $type) {
+ $intyp = 1;
+ } else {
+ $intyp = 0;
+ }
+ } else {
+ if ($intyp) {
+ push @flist, [$_, 0];
+ }
+ }
+ }
+
+ close (FFILE);
+
+ return 0;
+}
+
+#-------------------------------------------------------------------------------
+sub read_log {
+ if (not -r $lognam) {
+ print STDERR "xise_msg_filter-E: \'$lognam\' not existing or readable\n";
+ return 1;
+ }
+
+ open (LFILE, $lognam) or die "can't open for read $lognam: $!";
+
+ my $msgorig = "";
+ my $msgflat = "";
+ my $inmsg = 0;
+ my $parallmet = 0;
+
+ while () {
+ chomp;
+
+ $parallmet = 1 if ($type eq "par" && m/All c/);
+
+ if (m{^(INFO|WARNING|ERROR):}) {
+ if ($inmsg) {push @mlist, [$msgorig, $msgflat, 0];}
+ $inmsg = 1;
+ $msgorig = $_;
+ $msgflat = $_;
+ } elsif ($inmsg && m{^\s\s\s\S}) {
+ $msgorig .= "\n" . $_;
+ my $txt = $_;
+ $txt =~ s{\s\s}{}; # replace 3 leading blanks by one !
+ $msgflat .= $txt;
+ } else {
+ if ($inmsg) {push @mlist, [$msgorig, $msgflat, 0];}
+ $inmsg = 0;
+ }
+ }
+
+ if ($inmsg) {push @mlist, [$msgorig, $msgflat, 0];}
+
+ close (LFILE);
+
+ if ($type eq "par" && $parallmet==0) {
+ printf "!! ----------------------------------- !!\n";
+ printf "!! par: FAILED TO REACH TIMING CLOSURE !!\n";
+ printf "!! ----------------------------------- !!\n";
+ }
+
+ return 0;
+}
+
+#-------------------------------------------------------------------------------
+
+sub print_help {
+ print "usage: xise_msg_filter [options] type mfset log\n";
+ print " type log file type: xst,tra,map,par,twr, or bgn\n";
+ print " mfset message filter set file\n";
+ print " log log file\n";
+ print " Options:\n";
+ print " --pacc print summary of accepted messages\n";
+ print " --help this message\n";
+}
xise_msg_filter
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: ti_rri
===================================================================
--- ti_rri (nonexistent)
+++ ti_rri (revision 33)
@@ -0,0 +1,338 @@
+#! /usr/bin/env tclshcpp
+# -*- tcl -*-
+# $Id: ti_rri 631 2015-01-09 21:36:51Z mueller $
+#
+# Copyright 2011-2015 by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Version Comment
+# 2015-01-09 631 1.2.1 use rlc get/set rather config
+# 2014-11-07 601 1.2 use tclshcpp (C++ based) rather tclsh
+# 2013-05-19 521 1.1.6 setup proper interactive handling; add --run reap
+# 2013-04-26 510 1.1.5 reorganize readline startup
+# 2013-04-12 504 1.1.4 add --pack; trailing '-' argv implies --int
+# 2013-02-05 482 1.1.3 stop server is rls found
+# 2013-01-27 478 1.1.2 use 'exec sh -c $cmd &' for --run implementation
+# 2013-01-02 467 1.1.1 call rlc close only when really open
+# 2012-12-27 465 1.1 add --cuff support
+# 2012-02-09 457 1.0.4 disable autoexec
+# 2011-12-19 440 1.0.3 re-organize option handling for --term and --fifo
+# 2011-12-04 435 1.0.2 add flow attribute to --term
+# 2011-04-22 379 1.0.1 check for RETROBASE; proper exit handling; help text
+# 2011-04-17 376 1.0 Initial version
+# 2011-03-19 371 0.1 First draft
+#
+#
+# --pack=pname,...
+# --fifo[=name,opts,...]
+# --term[=name,baud,opts,...]
+# --cuff[=name,...]
+# --run=command
+# --log=filename ; default "-"
+# --logl=n ; default 2
+# --dmpl=n ; default 0
+# --tiol=n ; default 0
+# --int
+# --help
+# --
+# tcl cmds
+# @...tcl
+#
+
+set tirri_interactive 0
+
+array set opts {
+ pack_ ""
+ fifo 0
+ fifo_ ""
+ term 0
+ term_ ""
+ cuff 0
+ cuff_ ""
+ run_ ""
+ log_ "-"
+ logl_ 2
+ dmpl_ 0
+ tiol_ 0
+ int 0
+ help 0
+}
+
+set clist {}
+set optsendseen 0
+set runpid {}
+
+# disable autoexec
+set auto_noexec 1
+
+#
+# cleanup handler
+# must be in a proc so that it can be called from tclreadline
+# must be defined before ::tclreadline::Loop called (all after ignored...)
+#
+proc tirri_exit {{doexit 1}} {
+ global opts
+ global runpid
+
+ # check for rlink server, stop it
+ if { [info commands rls] eq "rls" } { rls server -stop }
+
+ # now close rlink connection
+ if { $opts(fifo) || $opts(term) || $opts(cuff) } {
+ if { [rlc open] ne "" } { rlc close }
+ }
+
+ # FIXME_code: should sync here with -run process run-down
+ # but no wait available in tcl (grr...)
+ if { "$runpid" ne "" } {
+ after 100; # currently just wait 100ms
+ rutil::waitpid $runpid
+ }
+ if { $doexit } {
+ puts {}; # \n to ensure shell prompt on new line
+ exit
+ }
+ return
+}
+
+foreach arg $argv {
+ if { $optsendseen } {
+ lappend clist $arg
+ continue
+ }
+ switch -regexp -- $arg {
+ ^--?pack=.+$ { regexp -- {=(.*)} $arg dummy opts(pack_) }
+ ^--?fifo=?.*$ { set opts(fifo) 1; regexp -- {=(.*)} $arg dummy opts(fifo_) }
+ ^--?term=?.*$ { set opts(term) 1; regexp -- {=(.*)} $arg dummy opts(term_) }
+ ^--?cuff=?.*$ { set opts(cuff) 1; regexp -- {=(.*)} $arg dummy opts(cuff_) }
+ ^--?run=.+$ { regexp -- {=(.*)} $arg dummy opts(run_) }
+ ^--?log=.+$ { regexp -- {=(.*)} $arg dummy opts(log_) }
+ ^--?logl=.+$ { regexp -- {=(.*)} $arg dummy opts(logl_) }
+ ^--?dmpl=.+$ { regexp -- {=(.*)} $arg dummy opts(dmpl_) }
+ ^--?tiol=.+$ { regexp -- {=(.*)} $arg dummy opts(tiol_) }
+ ^--?int$ { set opts(int) 1 }
+ ^--?help$ { set opts(help) 1 }
+ ^--$ { set optsendseen 1 }
+ ^--.+$ { puts "-E: bad option $arg, see --help for proper usage"
+ return 1
+ }
+ default { lappend clist $arg }
+ }
+}
+
+# check whether last element in clist is plain '-'
+if { [llength clist] } {
+ if { [lindex $clist end] eq "-" } {
+ set opts(int) 1
+ set clist [lrange $clist 0 end-1]
+ }
+}
+
+if { $opts(help) } {
+ # use {} as defimiter here to avoid that escaping of all []
+ puts {usage: ti_rri [OPTION]... [COMMAND]...}
+ puts {}
+ puts {Options:}
+ puts { --pack=PLIST load, with package require, additional packages}
+ puts { PLIST is comma separated list of package names}
+ puts { --run=CMD exec's CMD as subprocess before the rlink port opened}
+ puts { useful to start test benches, usually via 'tbw'}
+ puts { --fifo[=ARGS] open fifo type rlink port. Optional arguments are:}
+ puts { --fifo=[NAME[,OPTS]]}
+ puts { --term[=ARGS] open term type rlink port. Optional arguments are:}
+ puts { --term=[NAME[,BAUD[,OPTS]]]}
+ puts { --cuff[=ARGS] open cuff type rlink port. Optional arguments are:}
+ puts { --cuff=[NAME[,OPTS]]}
+ puts { --log=FILE set log file name. Default is to write to stdout.}
+ puts { --logl=LVL set log level, default is '2' allowed values 0-3.}
+ puts { --dmpl=LVL set dump level, default is '0', values like logl}
+ puts { --tiol=LVL set i/o trace level, default is '0', allowed 0-2.}
+ puts { --int enter interactive mode even when commands given}
+ puts { --help display this help and exit}
+ puts { -- all following arguments are treated as tcl commands}
+ puts {}
+ puts {Command handling:}
+ puts { For arguments of the form '@.tcl' the respective file is}
+ puts { sourced. All other arguments are treated as Tcl commands and executed}
+ puts { with eval.}
+ puts {}
+ puts {For further details consults the ti_rri man page.}
+ return 0
+}
+
+if {![info exists env(RETROBASE)]} {
+ puts "-E: RETROBASE environment variable not defined"
+ return 1
+}
+
+# check consistency of connection open options
+set nopen 0;
+if { $opts(fifo) } { incr nopen }
+if { $opts(term) } { incr nopen }
+if { $opts(cuff) } { incr nopen }
+
+if { $nopen > 1 } {
+ puts "-E: more than one of --fifo,--term,--cuff given, only one allowed"
+ return 1
+}
+
+# setup auto path
+lappend auto_path [file join $env(RETROBASE) tools tcl]
+lappend auto_path [file join $env(RETROBASE) tools lib]
+
+# setup default packages
+package require rutiltpp
+package require rlinktpp
+package require rlink
+
+# setup signal handling
+rutil::sigaction -init
+
+# setup connect and server objects
+rlinkconnect rlc
+rlinkserver rls rlc
+
+# load additional packages (if -pack given)
+if { $opts(pack_) ne "" } {
+ foreach pack [split $opts(pack_) ","] {
+ package require $pack
+ }
+}
+
+
+# setup logging
+if { $opts(log_) ne "-" } {
+ rlc set logfile $opts(log_)
+}
+rlc set printlevel $opts(logl_)
+rlc set dumplevel $opts(dmpl_)
+rlc set tracelevel $opts(tiol_)
+
+# first start, if specified with --run, the test bench
+# exec sh -c $cmd is used to execute a shell command including [], '',""
+# in a direct exec the tcl expansion logic will interfere...
+#
+if { $opts(run_) ne "" } {
+ if { [catch {exec sh -c $opts(run_) &} runpid] } {
+ puts "-E: failed to execute \"$opts(run_)\" with error message\n $runpid"
+ puts "aborting..."
+ return 1
+ }
+}
+
+# than open the rlink connection
+# handle --fifo
+if { $opts(fifo) } {
+ set nlist [split $opts(fifo_) ","]
+ set path [lindex $nlist 0]
+ if {$path eq ""} {set path "rlink_cext_fifo"}
+ set url "fifo:$path"
+ set delim "?"
+ foreach opt [lrange $nlist 1 end] {
+ if {$opt ne ""} {append url "$delim$opt"}
+ set delim ";"
+ }
+ # puts "-I: $url"
+ rlc open $url
+}
+
+# handle --term
+if { $opts(term) } {
+ set nlist [split $opts(term_) ","]
+ set dev [lindex $nlist 0]
+ set baud [lindex $nlist 1]
+ if {$dev eq ""} {set dev "USB0"}
+ if {$baud eq ""} {set baud "115k"}
+ set url "term:$dev?baud=$baud"
+ foreach opt [lrange $nlist 2 end] {
+ if {$opt ne ""} {append url ";$opt"}
+ }
+ # puts "-I: $url"
+ rlc open $url
+}
+
+# handle --cuff
+if { $opts(cuff) } {
+ set nlist [split $opts(cuff_) ","]
+ set path [lindex $nlist 0]
+ set url "cuff:$path"
+ set delim "?"
+ foreach opt [lrange $nlist 1 end] {
+ if {$opt ne ""} {append url "$delim$opt"}
+ set delim ";"
+ }
+ # puts "-I: $url"
+ rlc open $url
+}
+
+# setup simulation mode default
+set rlink::sim_mode [rlink::isfifo]
+
+# if tclsh runs a script given on the command line or is invoked
+# like here via a shebang the tcl_interactive is always set to 0
+# so we have to check whether stdin/stdout is a terminal and set
+# tcl_interactive accordingly
+
+set tcl_interactive [rutil::isatty STDIN]
+
+# determine whether interactive mode, if yes, initialize readline
+if {$tcl_interactive && ($opts(int) || [llength $clist] == 0) } {
+ set tirri_interactive 1
+
+ package require tclreadline
+ namespace eval tclreadline {
+ proc prompt1 {} {
+ set version [info tclversion]
+ return "ti_rri > "
+ }
+ }
+ ::tclreadline::readline eofchar {::tirri_exit; puts {}; exit}
+}
+
+# now execute all commands and scripts given as start-up arguments
+foreach cmd $clist {
+ # puts "executing: $cmd"
+ # handle @filename commands
+ if { [regexp {^@(.+)} $cmd dummy filename] } {
+ # handle @file.tcl --> source tcl file
+ if { [regexp {\.tcl$} $filename] } {
+ if { [catch {source $filename} errmsg] } {
+ puts "-E: failed to source file \"$filename\" with error message:"
+ if {[info exists errorInfo]} {puts $errorInfo} else {puts $errmsg}
+ puts "aborting..."
+ break
+ }
+ # handle @file.dat ect --> not yet supported
+ } else {
+ puts "-E: only tcl supported but $filename found"
+ puts "aborting..."
+ break
+ }
+
+ # handle normal tcl commands --> eval them
+ } else {
+ if { [catch {eval $cmd} errmsg] } {
+ puts "-E: eval of \"$cmd\" failed with error message:"
+ if {[info exists errorInfo]} {puts $errorInfo} else {puts $errmsg}
+ puts "aborting..."
+ break
+ }
+ }
+}
+
+if { $tcl_interactive && $tirri_interactive } {
+ ::tclreadline::Loop
+} else {
+ tirri_exit 0
+}
+
+return 0
ti_rri
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xise_ghdl_unisim
===================================================================
--- xise_ghdl_unisim (nonexistent)
+++ xise_ghdl_unisim (revision 33)
@@ -0,0 +1,98 @@
+#!/bin/bash
+# $Id: xise_ghdl_unisim 642 2015-02-06 18:53:12Z mueller $
+#
+# Copyright 2007-2015 by Walter F.J. Mueller
+# License disclaimer see LICENSE_gpl_v2.txt in $RETROBASE directory
+#
+# Revision History:
+# Date Rev Vers Comment
+# 2015-02-03 642 1.3 remove ISE 10 legacy support; add unimacro support
+# 2015-01-29 639 1.2 rename from xilinx_*; use XTWI_PATH rather XILINX
+# 2009-11-08 248 1.1 adopt to ISE 11.1, use VITAL models from ./primitive
+# 2007-10-26 92 1.0 Initial version
+#
+
+if [ -z "$XTWI_PATH" ]
+then
+ echo "XTWI_PATH not defined"
+ exit 1
+fi
+if [ ! -d "$XTWI_PATH/ISE_DS/ISE" ]
+then
+ echo "$XTWI_PATH/ISE_DS/ISE not existing"
+ exit 1
+fi
+#
+ise_path=$XTWI_PATH/ISE_DS/ISE
+#
+cd $ise_path
+echo "============================================================"
+echo "* Build ghdl UNISIM lib for $ise_path"
+echo "============================================================"
+#
+if [ ! -d ghdl ]
+then
+ mkdir ghdl
+fi
+cd ghdl
+#
+if [ ! -d unisim ]
+then
+ mkdir unisim
+fi
+cd unisim
+#
+cp $ise_path/vhdl/src/unisims/unisim_VCOMP.vhd .
+cp $ise_path/vhdl/src/unisims/unisim_VPKG.vhd .
+#
+if [ ! -d primitive ]
+then
+ mkdir primitive
+fi
+pushd primitive
+#
+cp -p $ise_path/vhdl/src/unisims/primitive/*.vhd .
+cp -p $ise_path/vhdl/src/unisims/primitive/vhdl_analyze_order .
+#
+xilinx_vhdl_memcolltype_fix
+popd
+
+echo "# ghdl ... unisim_VCOMP.vhd"
+ghdl -a --ieee=synopsys --work=unisim unisim_VCOMP.vhd
+echo "# ghdl ... unisim_VPKG.vhd"
+ghdl -a --ieee=synopsys --work=unisim unisim_VPKG.vhd
+
+for file in `cat primitive/vhdl_analyze_order`
+do
+ echo "# ghdl ... primitive/$file"
+ ghdl -a -fexplicit --ieee=synopsys --work=unisim \
+ --no-vital-checks primitive/$file 2>&1 |\
+ tee primitive/$file.ghdl.log
+done
+#
+echo "--- scan for compilation errors:"
+find primitive -name "*.ghdl.log" | xargs grep error
+#
+echo "============================================================"
+echo "* Build ghdl UNIMACRO lib for $XTWI_PATH/ISE_DS/ISE"
+echo "============================================================"
+#
+cd $ise_path/ghdl
+if [ ! -d unimacro ]
+then
+ mkdir unimacro
+fi
+#
+cd unimacro
+cp $ise_path/vhdl/src/unimacro/*.vhd .
+#
+for file in *.vhd
+do
+ echo "# ghdl ... $file"
+ ghdl -a -P../unisim -fexplicit --ieee=synopsys --work=unimacro \
+ --no-vital-checks $file 2>&1 | tee $file.ghdl.log
+done
+#
+echo "--- scan for compilation errors:"
+find . -name "*.ghdl.log" | xargs grep error
+#
xise_ghdl_unisim
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xtwi
===================================================================
--- xtwi (nonexistent)
+++ xtwi (revision 33)
@@ -0,0 +1,65 @@
+#!/bin/bash
+# $Id: xtwi 641 2015-02-01 22:12:15Z mueller $
+#
+# Copyright 2013- by Walter F.J. Mueller
+# License disclaimer see LICENSE_gpl_v2.txt in $RETROBASE directory
+#
+# Xilinx Tool Wrapper script for ISE:
+# define XTWI_PATH
+# usage xwti
+#
+# Revision History:
+# Date Rev Version Comment
+# 2013-10-12 539 1.0 Initial version
+#
+# Note: For Xilinx ISE installations with an install path holds
+# /ISE_DS dir with settings(32|64).sh
+# /ISE_DS/ISE XILINX env var will point here
+#
+
+# store arg list on vars (will be dropped later to source scripts)
+arglist_val=$@
+arglist_num=$#
+#
+# check whether ISE already setup ($XILINX defined)
+if [ -z "$XILINX" ]
+then
+ # check whether $XTWI_PATH defined
+ if [ -z "$XTWI_PATH" ]
+ then
+ echo "XTWI_PATH not defined"
+ exit 1
+ fi
+
+ # check whether 32 or 64 bit system (uname -m gives 'i686' or 'x86_64')
+ if [ `uname -m` = "x86_64" ]
+ then
+ settings_filename=$XTWI_PATH/ISE_DS/settings64.sh
+ else
+ settings_filename=$XTWI_PATH/ISE_DS/settings32.sh
+ fi
+ if [ ! -e "$settings_filename" ]
+ then
+ echo "can't locate init script '$settings_filename'"
+ exit 1
+ fi
+
+ # drop arg list, suppress output
+ set --
+ . $settings_filename > /dev/null
+
+ # check that XILINX defined
+ if [ -z "$XILINX" ]
+ then
+ echo "Failed to setup XILINX"
+ exit 1
+ fi
+
+else
+ echo "XILINX already defined"
+fi
+
+if [ $arglist_num != 0 ]
+then
+ exec $arglist_val
+fi
xtwi
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: tbw
===================================================================
--- tbw (nonexistent)
+++ tbw (revision 33)
@@ -0,0 +1,290 @@
+#!/usr/bin/perl -w
+# $Id: tbw 642 2015-02-06 18:53:12Z mueller $
+#
+# Copyright 2007-2015 by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Version Comment
+# 2015-01-04 629 1.2.6 BUGFIX: setup proper dsc values after -fifo
+# 2014-12-23 619 1.2.5 add -fifo and -verbose options
+# 2014-07-27 575 1.2.4 use xtwi to start ISim models
+# 2011-11-06 420 1.2.3 fix tbw.dat parsing (allow / in file names)
+# 2010-05-23 294 1.2.2 handle tb_code's in non-local directories
+# 2010-04-18 279 1.2.1 add -help and more text to print_usage()
+# 2009-11-22 252 1.2 add ISim support
+# 2007-09-15 82 1.1.1 test for ambigous matches of name arguments; for
+# "suff=[l1;l2;..]" style inlines use linkname_tmp.tmp
+# as filename
+# 2007-09-09 81 1.1 add fifo setup to tbw; allow multiple action lines
+# per target; support immediate mode data
+# "[line1;line2;...]" values
+# 2007-08-03 71 1.0.1 handle redefinition of existing symlink correctly
+# 2007-06-30 62 1.0 Initial version
+#
+# 'test bench wrapper' to setup symlink refering to stimulus file(s)
+#
+# usage: tbw [file] [args]
+#
+# will look for file (default is _stim.dat) and setup a symlink
+# _stim_dat to refer to it. All args are passed along to
+#
+
+use 5.005; # require Perl 5.005 or higher
+use strict; # require strict checking
+use POSIX qw(mkfifo);
+use FileHandle;
+
+my $tb_code;
+my $is_isim;
+my $is_isim_run;
+my $is_fifo;
+my $is_verbose;
+
+my @args_pos; # list of positional args
+my @args_nam; # list of named args
+my @file_dsc; # file descriptors from tbw.dat
+
+sub print_usage;
+
+autoflush STDOUT 1; # autoflush, so nothing lost on exec later
+
+if (scalar(@ARGV) && $ARGV[0] =~ /^-*help$/) { # -help or --help given
+ print_usage;
+ exit 0;
+}
+
+if (scalar(@ARGV) == 0) {
+ print "tbw-E: name of test bench code missing\n";
+ print_usage;
+ exit 1;
+}
+
+$tb_code = shift @ARGV;
+my $tb_code_path = ".";
+my $tb_code_name = $tb_code;
+if ($tb_code =~ m|^(.*)/(.*)$|) {
+ $tb_code_path = $1;
+ $tb_code_name = $2;
+}
+
+my $tb_code_stem = $tb_code_name;
+$tb_code_stem =~ s/_[fst]sim$//; # drop _ssim,_fsim, or _tsim
+
+if ($tb_code_stem =~ /_ISim$/) { # is it an ISim executable ?
+ $is_isim = 1;
+ $tb_code_stem =~ s/_ISim$//; # drop _ISim
+ if (scalar(@ARGV) && $ARGV[0] eq "-run") {
+ $is_isim_run = 1;
+ shift @ARGV;
+ }
+}
+
+if (scalar(@ARGV) && $ARGV[0] eq "-fifo") {
+ push @file_dsc, {tag=>'rlink_cext_fifo_rx', val=>''};
+ push @file_dsc, {tag=>'rlink_cext_fifo_tx', val=>''};
+ push @file_dsc, {tag=>'rlink_cext_conf', val=>''};
+ $is_fifo = 1;
+ shift @ARGV;
+}
+if (scalar(@ARGV) && $ARGV[0] eq "-verbose") {
+ $is_verbose = 1;
+ shift @ARGV;
+}
+
+if (not -e $tb_code) {
+ print "tbw-E: $tb_code not existing or not executable\n";
+ print_usage;
+ exit 1;
+}
+
+#
+# read tbw.dat file in current directory or directory of executable
+#
+
+my $tbwdat_file = "tbw.dat";
+$tbwdat_file = "$tb_code_path/tbw.dat" unless (-r "tbw.dat");
+
+if ((!$is_fifo) && -r $tbwdat_file) {
+ my $ok = 0;
+ my $done = 0;
+
+ open (TBW, $tbwdat_file) or die "failed to open $tbwdat_file: $!";
+ while () {
+ chomp;
+ next if /^#/;
+ if ( m{^\s*\[([\.\/a-zA-Z0-9_]*)\]\s*$} ) {
+ last if $done;
+ $ok = 0;
+ $ok = 1 if ($1 eq $tb_code || $1 eq $tb_code_stem);
+ } elsif ( m{^\s*([a-zA-Z0-9_]*)\s*=\s*([a-zA-Z0-9_./<>]*)\s*$} ) {
+ if ($ok) {
+ push @file_dsc, {tag=>$1, val=>$2};
+ $done = 1;
+ }
+ } else {
+ print "tbw-E: bad line in tbw.dat:\n $_\n";
+ }
+ }
+}
+
+#
+# if no tbw.dat or no matching stanza found, setup defaults
+#
+
+if (!$is_fifo) {
+ unless (scalar (@file_dsc)) {
+ push @file_dsc, {tag=>$tb_code_stem . "_stim",
+ val=>$tb_code_stem . "_stim.dat"};
+ }
+} else {
+ push @file_dsc, {tag=>"rlink_cext_fifo_rx",
+ val=>""};
+}
+
+#
+# now process argument list
+#
+
+{
+ my $ind = 0;
+ while (scalar(@ARGV)>0 && not $ARGV[0] =~ /^-/) {
+ my $arg = shift @ARGV;
+ my $ok;
+ if ($arg =~ /([a-zA-Z0-9_]*)=(.*)/) { # named argument
+ my $tag = $1;
+ my $val = $2;
+ foreach my $dsc (@file_dsc) {
+ if ($dsc->{tag} =~ /$tag$/) {
+ $dsc->{val} = $val;
+ $ok += 1;
+ }
+ }
+ if ($ok == 0) {
+ print STDERR "tbw-F: can't match named argument: $arg\n";
+ exit 1;
+ } elsif ($ok > 1) {
+ print STDERR "tbw-F: ambiguous match for named argument: $arg\n";
+ exit 1;
+ }
+
+ } else { # positional argument
+ if ($ind < scalar(@file_dsc)) {
+ $file_dsc[$ind]->{val} = $arg;
+ } else {
+ print STDERR "tbw-F: too many positional arguments: $arg\n";
+ exit 1;
+ }
+ $ind += 1;
+ }
+ }
+}
+
+if ($is_verbose) {
+ foreach my $dsc (@file_dsc) {
+ my $tag = $dsc->{tag};
+ my $val = $dsc->{val};
+ printf " %s = %s\n", $tag, $val;
+ }
+}
+
+#
+# now handle all specified file descriptors
+#
+
+foreach my $dsc (@file_dsc) {
+ my $tag = $dsc->{tag};
+ my $val = $dsc->{val};
+ if ($val eq "") { # handle FIFO's
+ next if (-p $tag);
+ print "tbw-I: create FIFO $tag\n";
+ mkfifo($tag, 0666) || die "can't mkfifo $tag: $!";
+
+ } else { # handle link to file cases
+
+ if ($val =~ /^\[(.*)\]$/) { # immediate data case: "[line1;line2;...]"
+ my @lines = split /;/, $1;
+ my $fname = "$tag\_tmp.tmp";
+ open TFILE,">$fname" or die "can't create temporary file $fname: $!";
+ foreach (@lines) {
+ s/^\s*//;
+ s/\s*$//;
+ print TFILE "$_\n";
+ }
+ close TFILE;
+ $val = $fname;
+
+ } else {
+ unlink "$tag\_tmp.tmp" if (-e "$tag\_tmp.tmp"); # remove old .tmp file
+ $val = "/dev/null" if ($val eq ""); # null file case
+ }
+
+ if (not -r $val) {
+ print "tbw-F: file for $tag not existing or not readable: $val\n";
+ exit 1;
+ }
+ if (-l $tag) {
+ my $cur_link = readlink $tag;
+ if ($cur_link ne $val) {
+ print "tbw-I: redefine $tag -> $val\n";
+ unlink $tag
+ or die "failed to unlink: $!";
+ symlink $val, $tag
+ or die "failed to symlink 1: $!";
+ }
+ } else {
+ if (-e $tag) {
+ print "tbw-F: $tag exists but is not a symlink\n";
+ exit 1;
+ } else {
+ print "tbw-I: define $tag -> $val\n";
+ symlink $val, $tag
+ or die "failed to symlink 2: $!";
+ }
+ }
+ }
+}
+
+#
+# here all ok, finally exec test bench
+#
+
+if ($is_isim_run) { # handle for isim 'run all'
+ my $cmd = "xtwi" . " " . $tb_code . " " . join " ",@ARGV;
+ open (ISIM_RUN, "| $cmd")
+ or die "failed to open process pipe to isim: $!";
+ print ISIM_RUN "run all\n";
+ print ISIM_RUN "quit\n";
+ close (ISIM_RUN)
+ or die "failed to close process pipe to isim: $!";
+
+} else { # otherwise just exec
+ exec $tb_code,@ARGV
+ or die "failed to exec: $!";
+}
+
+# ----------------------------------------------------------------------------
+sub print_usage {
+ print "usage: tbw [opts] [filedefs] [ghdl-opts]\n";
+ print " opts\n";
+ print " -run for _ISim tb's, runs the tb with a 'run all' command\n";
+ print " -fifo use rlink_cext fifo, ignore tbw.dat\n";
+ print " -verbose show the used tag,value settings before execution\n";
+ print " filedefs define tb input, either filename in tbw.dat order or\n";
+ print " tag=name or tag=[] pairs with tag matching one in in\n";
+ print " tbw.dat. The [] form allows to give data inline, e.g.\n";
+ print " like \"_conf=[.rpmon 1]\"\n";
+ print " ghdl-opts are all other options starting with a '-', they are\n";
+ print " passed to the testbench. Some useful ghdl options are:\n";
+ print " --wave=x.ghw\n";
+ print " --stack-max-size=16384\n";
+ print " --stop-time=1ns --disp-time --trace-processes\n";
+}
tbw
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: tbrun_tbw
===================================================================
--- tbrun_tbw (nonexistent)
+++ tbrun_tbw (revision 33)
@@ -0,0 +1,100 @@
+#!/bin/bash
+# $Id: tbrun_tbw 641 2015-02-01 22:12:15Z mueller $
+#
+# Copyright 2014- by Walter F.J. Mueller
+# License disclaimer see LICENSE_gpl_v2.txt in $RETROBASE directory
+#
+# Revision History:
+# Date Rev Version Comment
+# 2014-12-27 622 1.0.1 add --stack, --ghw, --tbw, --pcom
+# 2014-12-26 621 1.0 Initial version
+#
+
+docmd ()
+{
+ echo "$1"
+ if [[ -z "$optdry" ]] ; then
+ eval "$1"
+ fi
+}
+
+optdry=""
+optlsuf=""
+optstack=""
+optghw=""
+opttbw=""
+optpcom=""
+
+# handle options
+while (( $# > 0 )) ; do
+ case $1 in
+ -dry|--dry) optdry=$1 ; shift 1 ;;
+ -lsuf|--lsuf) optlsuf=$2 ; shift 2 ;;
+ -stack|--stack) optstack=$2 ; shift 2 ;;
+ -ghw|--ghw) optghw=$2 ; shift 2 ;;
+ -tbw|--tbw) opttbw=$2 ; shift 2 ;;
+ -pcom|--pcom) optpcom=$1 ; shift 1 ;;
+ -*) echo "tbrun_tbw-E: invalid option '$1'"; exit 1 ;;
+ *) break;;
+ esac
+done
+
+tbench=$1
+stimfile=$2
+
+# complain if no tbench defined
+if (( $# == 0 )) ; then
+ echo "Usage: tbrun_tbw [opts] testbench [stimfile]"
+ echo " Options:"
+ echo " --dry dry run, print commands, don't execute"
+ echo " --lsuf suff use '_.log' as suffix for log file"
+ echo " --stack nnn use as ghdl stack size"
+ echo " --ghw fname write ghw file with name '.ghw"
+ echo " --tbw opts append to tbw command"
+ exit 1
+fi
+
+# check for ISim
+isisim=""
+if [[ $tbench =~ _ISim ]] ; then
+ isisim=true
+fi
+
+# check for ghdl with _ssim, _fsim, _tsim
+isghdlxsim=""
+if [[ "$isisim" == "" ]] && [[ $tbench =~ _[sft]sim$ ]] ; then
+ isghdlxsim=true
+ logsuff=""
+fi
+
+# issue makes
+if [[ -n "$isghdlxsim" ]] ; then docmd "make ghdl_tmp_clean"; fi
+docmd "make $tbench"
+exitstat=$?
+if [[ -n "$isghdlxsim" ]] ; then docmd "make ghdl_tmp_clean"; fi
+
+if (( $exitstat > 0 )) ; then exit $exitstat; fi
+
+# determine logfile name
+logsuff="_dsim"
+if [[ $tbench =~ _[sft]sim$ ]] ; then logsuff=""; fi
+if [[ -n "$optlsuf" ]] ; then logsuff="_$optlsuf"; fi
+
+logfile="${tbench}${logsuff}.log"
+
+# now build actual test command (a tbw|filter|tee|egrep pipe)
+cmd="time tbw $tbench"
+if [[ -n "$isisim" ]] ; then cmd+=" -run"; fi
+if [[ -n "$stimfile" ]] ; then cmd+=" $stimfile"; fi
+if [[ -n "$opttbw" ]] ; then cmd+=" $opttbw"; fi
+if [[ -n "$optstack" ]] ; then cmd+=" --stack-max-size=$optstack"; fi
+if [[ -n "$optghw" ]] ; then cmd+=" --wave=$optghw.ghw"; fi
+cmd+=" 2>&1"
+if [[ -z "$isisim" ]] ; then cmd+=" | ghdl_assert_filter"; fi
+cmd+=" | tee $logfile"
+
+pcomtag=""
+if [[ -n "$optpcom" ]] ; then pcomtag="^C|"; fi
+# FAIL, PASS, DONE come from tbs; ERROR comes from ISim
+cmd+=" | egrep \"(${pcomtag}-[EFW]:|ERROR|FAIL|PASS|DONE)\""
+docmd "$cmd"
tbrun_tbw
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: rm_dep
===================================================================
--- rm_dep (nonexistent)
+++ rm_dep (revision 33)
@@ -0,0 +1,18 @@
+#!/bin/sh
+# $Id: rm_dep 646 2015-02-15 12:04:55Z mueller $
+#
+# Copyright 2010-2015 by Walter F.J. Mueller
+# License disclaimer see LICENSE_gpl_v2.txt in $RETROBASE directory
+#
+# Revision History:
+# Date Rev Version Comment
+# 2015-02-14 646 1.2 add dep_vsyn
+# 2011-01-09 354 1.1.1 add *.dep for cpp depends
+# 2010-04-26 284 1.1 add xargs -r to prevent rm errors on empty lists
+# 2010-04-24 282 1.0 Initial version
+#
+for ftype in dep dep_ghdl dep_xst dep_isim dep_ucf_cpp dep_vsyn
+do
+ echo "---------- remove *.$ftype ----------------------------------------"
+ find -name "*.$ftype" | xargs --no-run-if-empty rm -v
+done
rm_dep
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xise_ghdl_simprim
===================================================================
--- xise_ghdl_simprim (nonexistent)
+++ xise_ghdl_simprim (revision 33)
@@ -0,0 +1,74 @@
+#!/bin/bash
+# $Id: xise_ghdl_simprim 642 2015-02-06 18:53:12Z mueller $
+#
+# Copyright 2007-2015 by Walter F.J. Mueller
+# License disclaimer see LICENSE_gpl_v2.txt in $RETROBASE directory
+#
+# Revision History:
+# Date Rev Vers Comment
+# 2015-02-03 642 1.3 remove ISE 10 legacy support
+# 2015-01-29 639 1.2 rename from xilinx_*; use XTWI_PATH rather XILINX
+# 2009-11-08 248 1.1 adopt to ISE 11.1, use VITAL models from ./primitive
+# 2007-10-26 92 1.0 Initial version
+#
+
+if [ -z "$XTWI_PATH" ]
+then
+ echo "XTWI_PATH not defined"
+ exit 1
+fi
+if [ ! -d "$XTWI_PATH/ISE_DS/ISE" ]
+then
+ echo "$XTWI_PATHISE_DS/ISE not existing"
+ exit 1
+fi
+#
+ise_path=$XTWI_PATH/ISE_DS/ISE
+#
+cd $ise_path
+echo "============================================================"
+echo "* Build ghdl SIMPRIM lib for $ise_path"
+echo "============================================================"
+#
+if [ ! -d ghdl ]
+then
+ mkdir ghdl
+fi
+#
+cd $ise_path/ghdl
+if [ ! -d simprim ]
+then
+ mkdir simprim
+fi
+cd simprim
+#
+cp $ise_path/vhdl/src/simprims/simprim_Vcomponents.vhd .
+cp $ise_path/vhdl/src/simprims/simprim_Vpackage.vhd .
+#
+if [ ! -d primitive ]
+then
+ mkdir primitive
+fi
+#
+pushd primitive
+cp -p $ise_path/vhdl/src/simprims/primitive/other/*.vhd .
+cp -p $ise_path/vhdl/src/simprims/primitive/other/vhdl_analyze_order .
+xilinx_vhdl_memcolltype_fix
+popd
+#
+echo "# ghdl ... simprim_Vcomponents.vhd"
+ghdl -a --ieee=synopsys --work=simprim --no-vital-checks simprim_Vcomponents.vhd
+echo "# ghdl ... simprim_Vpackage.vhd"
+ghdl -a --ieee=synopsys --work=simprim --no-vital-checks simprim_Vpackage.vhd
+
+for file in `cat primitive/vhdl_analyze_order`
+do
+ echo "# ghdl ... primitive/$file"
+ ghdl -a -fexplicit --ieee=synopsys --work=simprim \
+ --no-vital-checks primitive/$file 2>&1 |\
+ tee primitive/$file.ghdl.log
+done
+#
+echo "--- scan for compilation errors:"
+find primitive -name "*.ghdl.log" | xargs grep error
+#
xise_ghdl_simprim
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xtwv
===================================================================
--- xtwv (nonexistent)
+++ xtwv (revision 33)
@@ -0,0 +1,64 @@
+#!/bin/bash
+# $Id: xtwv 641 2015-02-01 22:12:15Z mueller $
+#
+# Copyright 2013- by Walter F.J. Mueller
+# License disclaimer see LICENSE_gpl_v2.txt in $RETROBASE directory
+#
+# Xilinx Tool Wrapper script for Vivado
+# define XTWV_PATH
+# usage xwtv
+#
+# Revision History:
+# Date Rev Version Comment
+# 2014-04-18 554 1.0.1 fake XILINX_VIVADO, 2014.1 doesn't define it anymore
+# 2013-10-12 539 1.0 Initial version (cloned from xtwi)
+#
+# Note: For Xilinx Vivado installations with an install path holds
+# dir with settings(32|64).sh
+#
+
+# store arg list on vars (will be dropped later to source scripts)
+arglist_val=$@
+arglist_num=$#
+#
+# check whether Vivado already setup ($XILINX_VIVADO defined)
+if [ -z "$XILINX_VIVADO" ]
+then
+ # check whether $XTWV_PATH defined
+ if [ -z "$XTWV_PATH" ]
+ then
+ echo "XTWV_PATH not defined"
+ exit 1
+ fi
+
+ # check whether 32 or 64 bit system (uname -m gives 'i686' or 'x86_64')
+ if [ `uname -m` = "x86_64" ]
+ then
+ settings_filename=$XTWV_PATH/settings64.sh
+ else
+ settings_filename=$XTWV_PATH/settings32.sh
+ fi
+ if [ ! -e "$settings_filename" ]
+ then
+ echo "can't locate init script '$settings_filename'"
+ exit 1
+ fi
+
+ # drop arg list, suppress output
+ set --
+ . $settings_filename > /dev/null
+
+ # check that XILINX_VIVADO defined
+ if [ -z "$XILINX_VIVADO" ]
+ then
+ export XILINX_VIVADO=$XTWV_PATH/.
+ fi
+
+else
+ echo "XILINX_VIVADO already defined"
+fi
+
+if [ $arglist_num != 0 ]
+then
+ exec $arglist_val
+fi
xtwv
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xviv_ghdl_unisim
===================================================================
--- xviv_ghdl_unisim (nonexistent)
+++ xviv_ghdl_unisim (revision 33)
@@ -0,0 +1,127 @@
+#!/bin/bash
+# $Id: xviv_ghdl_unisim 642 2015-02-06 18:53:12Z mueller $
+#
+# Copyright 2015- by Walter F.J. Mueller
+# License disclaimer see LICENSE_gpl_v2.txt in $RETROBASE directory
+#
+# Revision History:
+# Date Rev Vers Comment
+# 2015-02-02 642 1.0 Initial version
+#
+
+if [ -z "$XTWV_PATH" ]
+then
+ echo "XTWV_PATH not defined"
+ exit 1
+fi
+if [ ! -d "$XTWV_PATH" ]
+then
+ echo "$XTWV_PATH not existing"
+ exit 1
+fi
+#
+cd $XTWV_PATH
+echo "============================================================"
+echo "* Build ghdl UNISIM lib for $XTWV_PATH"
+echo "============================================================"
+#
+if [ ! -d ghdl ]
+then
+ mkdir ghdl
+fi
+cd ghdl
+#
+if [ ! -d unisim ]
+then
+ mkdir unisim
+fi
+cd unisim
+#
+# copy VCOMP and VPKG ----------------------------
+#
+cp $XTWV_PATH/data/vhdl/src/unisims/unisim_retarget_VCOMP.vhd .
+cp $XTWV_PATH/data/vhdl/src/unisims/unisim_VPKG.vhd .
+#
+# copy 'primitive' models ------------------------
+#
+if [ ! -d primitive ]
+then
+ mkdir primitive
+fi
+pushd primitive
+#
+cp -p $XTWV_PATH/data/vhdl/src/unisims/primitive/*.vhd .
+cp -p $XTWV_PATH/data/vhdl/src/unisims/primitive/vhdl_analyze_order .
+# in Vivado 2014.4 the vhdl_analyze_order and contains two extraneous entries
+# simply drop them to avoid errors later on
+sed -i.bak -e '\|OBUFTDSE3| d' \
+ -e '\|OBUFTE3| d' \
+ vhdl_analyze_order
+#
+xilinx_vhdl_memcolltype_fix
+popd
+#
+# copy 'retarget' models -------------------------
+#
+if [ ! -d retarget ]
+then
+ mkdir retarget
+fi
+pushd retarget
+#
+cp -p $XTWV_PATH/data/vhdl/src/unisims/retarget/*.vhd .
+ls -1 *.vhd > vhdl_analyze_order
+#
+xilinx_vhdl_memcolltype_fix
+popd
+#
+# now compile all --------------------------------
+#
+echo "# ghdl ... unisim_retarget_VCOMP.vhd"
+ghdl -a --ieee=synopsys --work=unisim unisim_retarget_VCOMP.vhd
+echo "# ghdl ... unisim_VPKG.vhd"
+ghdl -a --ieee=synopsys --work=unisim unisim_VPKG.vhd
+
+for file in `cat primitive/vhdl_analyze_order`
+do
+ echo "# ghdl ... primitive/$file"
+ ghdl -a -fexplicit --ieee=synopsys --work=unisim \
+ --no-vital-checks primitive/$file 2>&1 |\
+ tee primitive/$file.ghdl.log
+done
+#
+for file in `cat retarget/vhdl_analyze_order`
+do
+ echo "# ghdl ... retarget/$file"
+ ghdl -a -fexplicit --ieee=synopsys --work=unisim \
+ --no-vital-checks retarget/$file 2>&1 |\
+ tee retarget/$file.ghdl.log
+done
+#
+echo "--- scan for compilation errors:"
+find primitive retarget -name "*.ghdl.log" | xargs grep error
+#
+#
+echo "============================================================"
+echo "* Build ghdl UNIMACRO lib for $XTWV_PATH"
+echo "============================================================"
+#
+cd $XTWV_PATH/ghdl
+if [ ! -d unimacro ]
+then
+ mkdir unimacro
+fi
+cd unimacro
+#
+cp $XTWV_PATH/data/vhdl/src/unimacro/*.vhd .
+#
+for file in *.vhd
+do
+ echo "# ghdl ... $file"
+ ghdl -a -P../unisim -fexplicit --ieee=synopsys --work=unimacro \
+ --no-vital-checks $file 2>&1 | tee $file.ghdl.log
+done
+#
+echo "--- scan for compilation errors:"
+find . -name "*.ghdl.log" | xargs grep error
+#
xviv_ghdl_unisim
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: ghdl_assert_filter
===================================================================
--- ghdl_assert_filter (nonexistent)
+++ ghdl_assert_filter (revision 33)
@@ -0,0 +1,29 @@
+#!/usr/bin/perl -w
+# $Id: ghdl_assert_filter 620 2014-12-25 10:48:35Z mueller $
+#
+# Copyright 2014- by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Version Comment
+# 2014-12-23 620 1.0 Initial version
+
+use 5.10.0; # require Perl 5.10 or higher
+use strict; # require strict checking
+
+autoflush STDOUT 1 if (-p STDOUT); # autoflush if output into pipe
+autoflush STDOUT 1 if (-t STDOUT); # autoflush if output into term
+
+while (<>) {
+ next if /:\@0ms:\(assertion warning\): NUMERIC_STD.*metavalue detected/;
+ next if /:\@0ms:\(assertion warning\): CONV_INTEGER: There is an 'U'/;
+ print;
+}
ghdl_assert_filter
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: svn_set_ignore
===================================================================
--- svn_set_ignore (nonexistent)
+++ svn_set_ignore (revision 33)
@@ -0,0 +1,112 @@
+#!/usr/bin/perl -w
+# $Id: svn_set_ignore 601 2014-11-07 22:44:43Z mueller $
+#
+# Copyright 2007-2014 by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Vers Comment
+# 2014-11-04 601 1.1 use 'svn info' rather /.svn check for svn >= 1.7
+# 2010-04-26 284 1.0.1 add error check for GetOptions
+# 2007-06-16 56 1.0 Initial version
+#
+
+use 5.005; # require Perl 5.005 or higher
+use strict; # require strict checking
+
+use Getopt::Long;
+
+sub do_dir;
+
+my @dirlist;
+my @def_ipat;
+
+my %opts = ();
+
+GetOptions(\%opts, "dry-run")
+ or die "bad options";
+
+if (@ARGV) {
+ push @dirlist, @ARGV;
+} else {
+ @dirlist = `find -type d | grep -v "\.svn"`;
+ die "bad find|grep" if $?;
+}
+
+open (CVSIG, ".cvsignore") or die "no top level .cvsigore found";
+@def_ipat = grep /.+/, ;
+close (CVSIG);
+
+foreach (@dirlist) { chomp; do_dir($_); }
+
+#-------------------------------------------------------------------------------
+
+sub do_dir {
+ my ($dirname) = @_;
+ my @cur_ipat;
+ my @loc_ipat;
+ my @sum_ipat;
+ my @new_ipat;
+ my %ipat;
+
+ # skip ise directories (they have sometimes strange chars in dir names
+ return if $dirname =~ m|/ise/|;
+ # check for svn working directory
+ my $svn_info = `svn info $dirname 2>&1`;
+ return if $?;
+
+ print "$dirname\n";
+ open (SVN, "svn pg svn:ignore $dirname|") or die "failed to open svn pg pipe";
+ @cur_ipat = grep /.+/, ; # prop get and drop empty lines
+ close (SVN);
+
+ if ($dirname ne "." && -r "$dirname/.cvsignore") {
+ open (CVSIG, "$dirname/.cvsignore")
+ or die "failed to read local .cvsignore";
+ @loc_ipat = grep /.+/, ;
+ close (CVSIG);
+ }
+
+ push @sum_ipat, @def_ipat;
+ push @sum_ipat, @loc_ipat;
+
+ foreach (@sum_ipat) {
+ if (exists $ipat{$_}) {
+ my $pat = $_;
+ chomp $pat;
+ print "duplicate ignore: $pat in $dirname\n";
+ } else {
+ $ipat{$_} = 1;
+ push @new_ipat, $_;
+ }
+ }
+
+ if (join("",@cur_ipat) ne join("",@new_ipat)) {
+ print "update svn:ignore for $dirname\n";
+ print "old svn:ignore:\n";
+ print " ", join " ",@cur_ipat if @cur_ipat;
+ print "local .cvsignore:\n";
+ print " ", join " ",@loc_ipat if @loc_ipat;
+ print "new svn:ignore:\n";
+ print " ", join " ",@new_ipat if @new_ipat;
+
+ if (not exists $opts{"dry-run"}) {
+ open (TMP, ">/tmp/svn_set_ignore_$$") or die "failed to open tmp file";
+ print TMP join "",@new_ipat;
+ close (TMP);
+ print `svn ps svn:ignore -F /tmp/svn_set_ignore_$$ $dirname`;
+ die "bad svn ps" if $?;
+ unlink "/tmp/svn_set_ignore_$$" or die "failed to delete tmp file";
+ }
+
+ }
+
+}
svn_set_ignore
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: fx2load_wrapper
===================================================================
--- fx2load_wrapper (nonexistent)
+++ fx2load_wrapper (revision 33)
@@ -0,0 +1,262 @@
+#!/usr/bin/perl -w
+# $Id: fx2load_wrapper 604 2014-11-16 22:33:09Z mueller $
+#
+# Copyright 2011-2014 by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Version Comment
+# 2014-08-10 581 1.1 use _ic instead of _as as default firmware
+# 2012-02-11 457 1.0.1 use RETRO_FX2_VID/PID; check iProduct string
+# 2011-12-29 446 1.0 Initial version
+#
+
+use 5.005; # require Perl 5.005 or higher
+use strict; # require strict checking
+use FileHandle;
+use Time::HiRes qw(usleep);
+
+use Getopt::Long;
+
+my %opts = ();
+
+GetOptions(\%opts, "help", "dry_run", "force", "cycfx2prog",
+ "board=s", "file=s", "ihx_path=s")
+ or exit 1;
+
+#
+# setup defaults for board and file
+#
+if (not defined $opts{board}) {
+ $opts{board} = "nexys2";
+}
+if (not defined $opts{file}) {
+ $opts{file} = "nexys2_jtag_2fifo_ic.ihx" if $opts{board} eq "nexys2";
+ $opts{file} = "nexys3_jtag_2fifo_ic.ihx" if $opts{board} eq "nexys3";
+ $opts{file} = "nexys3_jtag_2fifo_ic.ihx" if $opts{board} eq "atlys";
+}
+if (not defined $opts{ihx_path}) {
+ unless (exists $ENV{RETROBASE}) {
+ print STDERR "fx2load_wrapper-F: RETROBASE not set\n";
+ exit 1;
+ }
+ $opts{ihx_path} = $ENV{RETROBASE} . "/tools/fx2/bin";
+}
+
+sub print_help;
+sub run_command;
+sub get_usb_id;
+sub get_usb_prodinfo;
+
+autoflush STDOUT 1 if (-p STDOUT); # autoflush if output into pipe
+
+if (exists $opts{help}) {
+ print_help;
+ exit 0;
+}
+
+my $board = $opts{board};
+my $ifile = $opts{file};
+
+# setup digilent default usb id's
+
+my $usbid_digi;
+
+if ($board eq "nexys2") { $usbid_digi = "1443:0005";}
+elsif ($board eq "nexys3") { $usbid_digi = "1443:0007";}
+elsif ($board eq "atlys") { $usbid_digi = "1443:0007";}
+else {
+ print STDERR
+ "fx2load_wrapper-E: only nexys2,3/atlys supported\n";
+ exit 1;
+}
+
+# handle USB VID/PID of board
+# taken from RETRO_FX2_VID and RETRO_FX2_PID environment variables
+# in the retro11 project the default is:
+# VID: 16c0 (VOTI)
+# PID: 03ef (VOTI free for internal lab use 1007)
+#
+# !! Important Note on Usage of this USB VID/PID !!
+# This VID/PID is owned by VOTI, a small dutch company. Usage is granted
+# for 'internal lab use only' by VOTI under the conditions:
+# - the gadgets in which you use those PIDs do not leave your desk
+# - you won't complain to VOTI if you get in trouble with duplicate PIDs
+# (for instance because someone else did not follow the previous rule).
+# See also http://www.voti.nl/pids/pidfaq.html
+#
+
+my $fx2_vid = $ENV{RETRO_FX2_VID};
+my $fx2_pid = $ENV{RETRO_FX2_PID};
+$fx2_vid = "16c0" unless defined $fx2_vid;
+$fx2_pid = "03ef" unless defined $fx2_pid;
+
+my $usbid_retro = "$fx2_vid:$fx2_pid";
+my $n_digi = 0;
+my $n_retro = 0;
+
+my $fx2_bus;
+my $fx2_dev;
+my $fx2_id;
+my $fx2_prodinfo;
+
+($n_digi, $n_retro, $fx2_bus, $fx2_dev, $fx2_id) = get_usb_id();
+
+if ($n_digi+$n_retro == 0) {
+ print STDERR "fx2load_wrapper-E no board detected\n";
+ exit 1;
+}
+if ($n_digi+$n_retro > 1) {
+ print STDERR "fx2load_wrapper-E more than one board detected\n";
+ exit 1;
+}
+
+if ($n_retro > 0) {
+ $fx2_prodinfo = get_usb_prodinfo($fx2_id);
+}
+
+if ($n_retro == 1 &&
+ $opts{file} eq $fx2_prodinfo . ".ihx" &&
+ (not defined $opts{force}) ) {
+ print "fx2load_wrapper-I board already configured with $fx2_prodinfo.ihx\n";
+ exit 0;
+}
+
+my $full_file = $opts{ihx_path} . "/" . $opts{file};
+unless (-r $full_file) {
+ print STDERR "fx2load_wrapper-E: ihx file \'$full_file\' not found\n";
+ exit 1;
+}
+
+my $fx2_path = "/dev/bus/usb/$fx2_bus/$fx2_dev";
+
+unless ( -r $fx2_path && -w $fx2_path) {
+ print STDERR
+ "fx2load_wrapper-E: usb device \'$fx2_path\' not user accessible\n";
+ exit 1;
+}
+
+my $cmd;
+
+if ($opts{cycfx2prog}) {
+ my $proc = `which cycfx2prog`;
+ chomp $proc;
+ unless (-x $proc) {
+ print STDERR "fx2load_wrapper-E: cycfx2prog not found or executable\n";
+ exit 1;
+ }
+ $cmd = "cycfx2prog -id=$fx2_id prg:$full_file run";
+
+} else {
+ my $proc = `which fxload`;
+ chomp $proc;
+ $proc = "/sbin/fxload" if ($proc eq "");
+ unless (-x $proc) {
+ print STDERR "fx2load_wrapper-E: fxload not found or executable\n";
+ exit 1;
+ }
+ $cmd = "$proc -t fx2 -I $full_file -D $fx2_path";
+}
+
+my $rc = 0;
+if (defined $opts{dry_run}) {
+ print "$cmd\n";
+} else {
+ print "fx2load_wrapper-I: loading $opts{file}\n";
+ $rc = run_command($cmd);
+ print "fx2load_wrapper-I: loaded $opts{file}\n";
+ usleep(1500000);
+}
+
+exit $rc;
+
+#-------------------------------------------------------------------------------
+
+sub run_command {
+
+ my ($cmd) = @_;
+
+ my $wrc = system "/bin/sh", "-c", "$cmd";
+
+ my $rc = 0;
+ if ($wrc != 0) {
+ my $rc = int($wrc/256);
+ if ($rc == 0) {
+ my $sig = $wrc % 256;
+ print STDERR "fx2load_wrapper-E \'$cmd\' aborted by signal $sig\n";
+ $rc = 1;
+ } else {
+ print STDERR "fx2load_wrapper-E \'$cmd\' failed (rc=$rc) $?\n";
+ }
+ }
+
+ return $rc;
+}
+
+#-------------------------------------------------------------------------------
+
+sub print_help {
+ print "usage: fx2load_wrapper [--board=b] [--file=f] [OPTIONS]\n";
+ print " --help this message\n";
+ print " --dry_run print command only\n";
+ print " --force reload even when proper firmware detected\n";
+ print " --cycfx2prog use cycfx2prog instead of fxload\n";
+ print " --board=b type of board (default nexys2)\n";
+ print " --file=f ihx file to load (default 2fifo_as)\n";
+ print " --ihx_path=p path to ihx files\n";
+}
+
+#-------------------------------------------------------------------------------
+
+sub get_usb_id {
+ my @lsusb = `lsusb`;
+
+ my $n_digi = 0;
+ my $n_retro = 0;
+ my $fx2_bus;
+ my $fx2_dev;
+ my $fx2_id;
+
+ foreach (@lsusb) {
+ if (/^Bus\s+(\d+)\s+Device\s+(\d+):\s+ID\s+([:0-9a-f]+)\s+(.*)$/) {
+ my ($bus,$dev,$id,$text) = ($1,$2,$3,$4);
+ my $match = 0;
+ if ($id eq $usbid_digi) {
+ $n_digi += 1;
+ $match = 1;
+ } elsif ($id eq $usbid_retro) {
+ $n_retro += 1;
+ $match = 1;
+ }
+ if ($match) {
+ $fx2_bus = $bus;
+ $fx2_dev = $dev;
+ $fx2_id = $id;
+ }
+ }
+ }
+
+ return ($n_digi, $n_retro, $fx2_bus, $fx2_dev, $fx2_id);
+
+}
+
+#-------------------------------------------------------------------------------
+
+sub get_usb_prodinfo {
+ my ($fx2_id) = @_;
+ my @lsusb = `lsusb -d $fx2_id -v`;
+ foreach (@lsusb) {
+ if (/^\s*iProduct\s*\d*\s*(.*)$/) {
+ return $1;
+ }
+ }
+ return "";
+}
fx2load_wrapper
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: console_starter
===================================================================
--- console_starter (nonexistent)
+++ console_starter (revision 33)
@@ -0,0 +1,100 @@
+#!/usr/bin/perl -w
+# $Id: console_starter 581 2014-08-10 21:48:46Z mueller $
+#
+# Copyright 2009-2014 by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Vers Comment
+# 2014-08-10 581 1.1 rename to console_starter
+# 2010-07-04 312 1.0.3 correct telnet_wrapper path
+# 2010-04-26 284 1.0.2 add error check for GetOptions
+# 2009-11-08 248 1.0.1 proper -h handling & text; add -t support;
+# 2009-11-07 247 1.0 Initial version
+#
+
+use 5.005; # require Perl 5.005 or higher
+use strict; # require strict checking
+
+use Getopt::Long;
+
+my %opts = ();
+GetOptions(\%opts, "h", "t:s", "d:s", "s", "w", "l")
+ or die "bad options";
+
+if (exists $opts{h}) {
+ print "usage: console_starter [-h] [-t type] [-d type] [-s] [-w] [-l]\n";
+ print " -h help, print this text and quit\n";
+ print " -t term set terminal type, vt100 or vt52 (def: vt100)\n";
+ print " -d dev set device type, DLx or DZx for x'the line (def: DL0)\n";
+ print " -s use simh ports, default is to use rri ports\n";
+ print " -w use wide 132 column screen (default 80 columns)\n";
+ print " -l use long 48 lines screen (default 24 lines)\n";
+ exit 0;
+}
+
+my $emu = "xterm";
+my $telnet = $ENV{"RETROBASE"} . "/tools/bin/telnet_wrapper";
+
+my @args;
+my $term = "vt100";
+my $dev = "DL";
+my $line = 0;
+my $port;
+my $title;
+
+if (exists $opts{t}) {
+ if ($opts{t} =~ m{^(vt100|vt52)$} ) {
+ $term = $opts{t};
+ } else {
+ printf "unsupported terminal type: %s\n", $opts{t};
+ exit 1;
+ }
+}
+
+if (exists $opts{d}) {
+ if ($opts{d} =~ m{^(DL|DZ)(\d*)$}i ) {
+ $dev = uc $1;
+ $line = int $2;
+ } else {
+ printf "unsupported device type: %s\n", $opts{d};
+ exit 1;
+ }
+}
+
+if (exists $opts{s}) { # simh ports
+ $port = 5670 if ($dev eq "DL");
+ $port = 5671 if ($dev eq "DZ");
+ $title = sprintf "\"%s %s\"", $dev, $term;
+} else { # rri ports
+ $port = 8000+$line if ($dev eq "DL");
+ $port = 8002+$line if ($dev eq "DZ");
+ $title = sprintf "\"%s%d %s\"", $dev, $line, $term;
+}
+
+my $geo_w = 80;
+my $geo_l = 24;
+$geo_w = 132 if exists $opts{w};
+$geo_l = 48 if exists $opts{l};
+
+push @args, "-j", "-rightbar", "-sb", "-sl", "500";
+push @args, "-bg", "gray90", "-fg", "black";
+push @args, "-ti", $term;
+push @args, "-geo", sprintf("%dx%d", $geo_w, $geo_l);
+push @args, "-T", $title;
+push @args, "-e", $telnet, "localhost", sprintf("%d",$port);
+
+print $emu, " ", join " ",@args, "\n";
+
+my $rc = system $emu, @args;
+if ($rc != 0) {
+ print STDERR "xterm failed with rc=$rc\n";
+}
console_starter
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: .cvsignore
===================================================================
--- .cvsignore (nonexistent)
+++ .cvsignore (revision 33)
@@ -0,0 +1,2 @@
+cycfx2prog
+tclshcpp
Index: telnet_wrapper
===================================================================
--- telnet_wrapper (nonexistent)
+++ telnet_wrapper (revision 33)
@@ -0,0 +1,55 @@
+#!/usr/bin/perl -w
+# $Id: telnet_wrapper 547 2013-12-29 13:10:07Z mueller $
+#
+# Copyright 2009-2013 by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Vers Comment
+# 2009-11-07 246 1.0 Initial version
+#
+
+use 5.005; # require Perl 5.005 or higher
+use strict; # require strict checking
+
+if (scalar(@ARGV) != 2) {
+ print STDERR "usage: telnet_wrapper host port\n";
+ exit 1;
+}
+
+my $host = $ARGV[0];
+my $port = $ARGV[1];
+
+print "$host $port\n";
+
+my $telnet = `which telnet`;
+chomp $telnet;
+
+while(1) {
+ my $rc = system $telnet, $host, $port;
+ if ($rc != 0) {
+ print STDERR "telnet failed with rc=$rc\n";
+ }
+ print "enter q or <^D> to quit, otherwise hit to reconnect: ";
+ my $buf;
+ my $nc = read STDIN, $buf, 1;
+ if (not defined $nc) {
+ print "\n";
+ exit 1;
+ }
+ if ($nc == 0) {
+ print "\n";
+ exit 0;
+ }
+ if ($buf eq "q") {
+ exit 0;
+ }
+}
telnet_wrapper
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: config_wrapper
===================================================================
--- config_wrapper (nonexistent)
+++ config_wrapper (revision 33)
@@ -0,0 +1,283 @@
+#!/usr/bin/perl -w
+# $Id: config_wrapper 534 2013-09-22 21:37:24Z mueller $
+#
+# Copyright 2010-2013 by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Version Comment
+# 2013-09-21 534 1.1.8 add nexys4 support
+# 2013-01-02 467 1.1.7 jconfig: prepend '0x' to support 'jtag #2007'
+# 2012-02-11 457 1.1.6 jconfig: use RETRO_FX2_VID/PID for USB VID/PID
+# 2011-12-03 435 1.1.5 add nexys3 support;
+# 2011-08-04 402 1.1.4 add atlys support;
+# 2011-07-25 399 1.1.3 add nexys2-500 support; bsdl path for sp605
+# 2011-07-18 395 1.1.2 cleanup bsdl path creation for jtag
+# 2011-07-17 394 1.1.1 add bit->svf conversion and config with jtag
+# 2011-07-11 393 1.1 renamed from impact_wrapper; add function parameter,
+# old action with 'iconfig'
+# 2011-07-01 386 1.0.3 support sp605/xc6slx45t
+# 2010-05-24 294 1.0.2 support nexys2/xc3s1200e
+# 2010-04-24 282 1.0.1 proper error exit for GetOptions()
+# 2010-04-24 281 1.0 Initial version
+#
+
+use 5.005; # require Perl 5.005 or higher
+use strict; # require strict checking
+use FileHandle;
+
+use Getopt::Long;
+
+my %opts = ();
+
+GetOptions(\%opts, "help", "dry_run", "board=s", "path=s") or exit 1;
+
+# setup defaults for board and path
+if (not defined $opts{board}) {
+ $opts{board} = "s3board";
+}
+if (not defined $opts{path}) {
+ $opts{path} = "xc3s1000" if $opts{board} eq "s3board";
+ $opts{path} = "xc3s1200e" if $opts{board} eq "nexys2";
+ $opts{path} = "xc6slx16" if $opts{board} eq "nexys3";
+ $opts{path} = "xc7a100t" if $opts{board} eq "nexys4";
+ $opts{path} = "xc6slx45" if $opts{board} eq "atlys";
+ $opts{path} = "xc6slx45t" if $opts{board} eq "sp605";
+}
+
+sub print_help;
+sub run_command;
+
+
+autoflush STDOUT 1 if (-p STDOUT); # autoflush if output into pipe
+
+if (exists $opts{help}) {
+ print_help;
+ exit 0;
+}
+
+my $board = $opts{board};
+my $ipath = $opts{path};
+
+$ipath =~ s/-.*$//; # trim all after first '-'
+
+# now setup JTAG chain config
+
+my @plist;
+my $pfpga;
+
+#
+# Note: when new targets are added update also the blist logic below
+#
+if ($board eq "s3board" && $ipath eq "xc3s200") { # S3BOARD-200
+ @plist = ($ipath, "xcf02s");
+ $pfpga = 1;
+} elsif ($board eq "s3board" && $ipath eq "xc3s1000") { # S3BOARD-1200
+ @plist = ($ipath, "xcf04s");
+ $pfpga = 1;
+
+} elsif ($board eq "nexys2" && $ipath eq "xc3s1200e") { # nexys2-1200
+ @plist = ($ipath, "xcf04s");
+ $pfpga = 1;
+} elsif ($board eq "nexys2" && $ipath eq "xc3s500e") { # nexys2-500
+ @plist = ($ipath, "xcf04s");
+ $pfpga = 1;
+
+} elsif ($board eq "nexys3" && $ipath eq "xc6slx16") { # nexys3
+ @plist = ($ipath);
+ $pfpga = 1;
+
+} elsif ($board eq "nexys4" && $ipath eq "xc7a100t") { # nexys4
+ @plist = ($ipath);
+ $pfpga = 1;
+
+} elsif ($board eq "atlys" && $ipath eq "xc6slx45") { # atlys
+ @plist = ($ipath);
+ $pfpga = 1;
+
+} elsif ($board eq "sp605" && $ipath eq "xc6slx45t") { # sp605
+ @plist = ("xccace", $ipath);
+ $pfpga = 2;
+} else {
+ print STDERR
+ "config_wrapper-E: only s3board/nexys2,3/atlys/sp605 supported\n";
+ exit 1;
+}
+
+my @blist;
+foreach my $part (@plist) {
+ if ($part =~ m/^xcf/) { push @blist, "xcf/data" } # proms
+ elsif ($part =~ m/^xc3s\d*$/) { push @blist, "spartan3/data" } # s-3
+ elsif ($part =~ m/^xc3s\d*e$/) { push @blist, "spartan3e/data" } # s-3e
+ elsif ($part =~ m/^xc6slx\d*t?$/) { push @blist, "spartan6/data" }# s-6 lx
+ elsif ($part =~ m/^xc7a\d*t?$/) { push @blist, "artix7/data" } # 7-a
+ elsif ($part =~ m/^xccace$/) { push @blist, "acempm/data" } # sys-ace
+ else {
+ print STDERR "config_wrapper-E: no bsdl path known for $part\n";
+ exit 1;
+ }
+}
+
+my $cmd = shift @ARGV;
+my $file = shift @ARGV;
+
+if (! defined $cmd) {
+ print STDERR "config_wrapper-E: no command specified\n";
+ exit 1;
+}
+
+if (! defined $file) {
+ print STDERR "config_wrapper-E: no bit or svf file specified\n";
+ exit 1;
+}
+if (! -r $file) {
+ print STDERR "config_wrapper-E: input file not found or readable\n";
+ exit 1;
+}
+
+my $xilpath = $ENV{XILINX};
+if (! defined $xilpath) {
+ print STDERR "config_wrapper-E: XILINX environment variable not defined\n";
+ exit 1;
+}
+
+# ----- iconfig action --------------------------------------------------------
+if ($cmd eq "iconfig") {
+
+ my $tmpfile = "tmp_config_wrapper.cmd";
+ open (OFILE, ">$tmpfile") or die "Couldn't open tmp cmd file: $!";
+
+ print OFILE "setMode -bs\n";
+ print OFILE "setCable -p auto\n";
+ for (my $i = 0; $i<=$#plist; $i++) {
+ printf OFILE "addDevice -p %d -part %s\n", $i+1, $plist[$i];
+ }
+ printf OFILE "assignFile -p %d -file %s\n", $pfpga, $file;
+ printf OFILE "program -p %d -verify\n", $pfpga;
+ print OFILE "quit\n";
+
+ close (OFILE) or die "Couldn't close tmp cmd file: $!";
+
+ my $rc = run_command("impact -batch", $tmpfile);
+ exit $rc;
+
+# ----- jconfig action --------------------------------------------------------
+} elsif ($cmd eq "jconfig") {
+
+ my $bpath = join ";", map "$xilpath/$_",@blist;
+
+ my $tmpfile = "tmp_config_wrapper.cmd";
+ open (OFILE, ">$tmpfile") or die "Couldn't open tmp cmd file: $!";
+
+ # the UrJtag and Xilinx impact have different chain and part number schemes
+ # impact: 1-based, 1 is first in chain;
+ # UrJtag: 0-based, 0 is last in chain;
+ # e.g. on Digilent Nexys2:
+ # impact: (1) FPGA (2) PROM
+ # UrJtag: (1) FPGA (0) PROM
+
+ my $jtag_part = $#plist + 1 - $pfpga;
+
+ # handle USB VID/PID of board
+ # taken from RETRO_FX2_VID and RETRO_FX2_PID environment variables
+ # in the retro11 project the default is:
+ # VID: 16c0 (VOTI)
+ # PID: 03ef (VOTI free for internal lab use 1007)
+ #
+ # !! Important Note on Usage of this USB VID/PID !!
+ # This VID/PID is owned by VOTI, a small dutch company. Usage is granted
+ # for 'internal lab use only' by VOTI under the conditions:
+ # - the gadgets in which you use those PIDs do not leave your desk
+ # - you won't complain to VOTI if you get in trouble with duplicate PIDs
+ # (for instance because someone else did not follow the previous rule).
+ # See also http://www.voti.nl/pids/pidfaq.html
+ #
+
+ my $fx2_vid = $ENV{RETRO_FX2_VID};
+ my $fx2_pid = $ENV{RETRO_FX2_PID};
+ $fx2_vid = "16c0" unless defined $fx2_vid;
+ $fx2_pid = "03ef" unless defined $fx2_pid;
+
+ # give vid/pid with 0x prefix. jtag #2007 requires this, #1502 tolerates
+ print OFILE "cable usbblaster vid=0x$fx2_vid pid=0x$fx2_pid\n";
+ printf OFILE "bsdl path %s\n", $bpath;
+ print OFILE "detect\n";
+ printf OFILE "part %d\n", $jtag_part;
+ printf OFILE "svf %s\n", $file;
+
+ close (OFILE) or die "Couldn't close tmp cmd file: $!";
+
+ my $rc = run_command("jtag", $tmpfile);
+ exit $rc;
+
+# ----- bit2svf action --------------------------------------------------------
+} elsif ($cmd eq "bit2svf") {
+ my $ofile = $file;
+ $ofile =~ s/\.bit/\.svf/;
+
+ my $tmpfile = "tmp_config_wrapper.cmd";
+ open (OFILE, ">$tmpfile") or die "Couldn't open tmp cmd file: $!";
+
+ print OFILE "setMode -bs\n";
+ printf OFILE "setCable -port svf -file %s\n", $ofile;
+ printf OFILE "addDevice -p 1 -file %s\n", $file;
+ print OFILE "program -p 1\n";
+ print OFILE "quit\n";
+
+ close (OFILE) or die "Couldn't close tmp cmd file: $!";
+
+ my $rc = run_command("impact -batch", $tmpfile);
+ exit $rc;
+}
+
+print STDERR "config_wrapper-E: command must be bit2svf, iconfig or jconfig\n";
+exit 1;
+
+#-------------------------------------------------------------------------------
+
+sub run_command {
+
+ my ($cmd, $tmpfile) = @_;
+
+ my $wrc;
+ if (defined $opts{dry_run}) {
+ print STDOUT "$cmd\n";
+ $wrc = system "/bin/sh", "-c", "cat $tmpfile";
+ } else {
+ $wrc = system "/bin/sh", "-c", "$cmd $tmpfile";
+ }
+
+ my $rc = 0;
+ if ($wrc != 0) {
+ my $rc = int($wrc/256);
+ if ($rc == 0) {
+ my $sig = $wrc % 256;
+ print STDERR "config_wrapper-I $cmd aborted by signal $sig\n";
+ $rc = 1;
+ } else {
+ print STDERR "config_wrapper-I $cmd failed (rc=$rc) $?\n";
+ }
+ }
+
+ unlink $tmpfile or die "Couldn't delete tmp cmd file: $!";
+ return $rc;
+}
+
+#-------------------------------------------------------------------------------
+
+sub print_help {
+ print "usage: config_wrapper [--help] [--board=b] [--path=p] cmd file\n";
+ print " cmd bit2svf or iconfig or jconfig\n";
+ print " --help this message\n";
+ print " --dry_run print impact command list\n";
+ print " --board=b type of board\n";
+ print " --path=p type of fpga\n";
+}
config_wrapper
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: asm-11_expect
===================================================================
--- asm-11_expect (nonexistent)
+++ asm-11_expect (revision 33)
@@ -0,0 +1,298 @@
+#!/usr/bin/perl -w
+# $Id: asm-11_expect 501 2013-03-30 13:53:39Z mueller $
+#
+# Copyright 2013- by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Version Comment
+# 2013-03-29 500 1.0 Initial version
+# 2013-03-24 499 0.1 First draft
+#
+
+use 5.10.0; # require Perl 5.10 or higher
+use strict; # require strict checking
+use FileHandle;
+
+use Getopt::Long;
+
+my %opts = ();
+
+GetOptions(\%opts, "help",
+ "tline", "tcheck"
+ )
+ or exit 1;
+
+sub do_help;
+sub print_help;
+
+my $errcnt; # total error count
+
+autoflush STDOUT 1 if (-p STDOUT); # autoflush if output into pipe
+
+if (exists $opts{help}) {
+ print_help;
+ exit 0;
+}
+
+if (scalar(@ARGV) == 0) {
+ print STDERR "asm-11_expect-F: no input files specified, quiting..\n";
+ print_help;
+ exit 1;
+}
+
+foreach my $fname (@ARGV) {
+ do_file($fname);
+}
+
+exit 1 if $errcnt > 0;
+exit 0;
+
+#-------------------------------------------------------------------------------
+#
+#; Input file list:
+# 1 6 ; comment
+# 1 17 000000 zero:
+# 1 23 002000 000101 w0: .word 101
+# 1 17 001011 377 .byte ^c0
+# 1 70 001206 046374 001234 001234 bic 1234(r3),@1234(r4)
+# 1 24 001036 067527 066162 020544 .word "Wo,"rl,"d!,0
+# 000000
+#EEfnolinno dot... word1. word2. word2.
+#
+# 1 2 3
+#0123456789012345678901234567890123456789
+#
+
+sub do_file {
+ my ($fname) = @_;
+ my $fh;
+ if ($fname eq "-") {
+ $fh = *STDIN;
+ } else {
+ if (not -r $fname) {
+ print STDERR "asm-11_expect-F: '$fname' not found or readable. EXIT\n";
+ exit 1;
+ }
+ $fh = new FileHandle;
+ $fh->open($fname) or die "failed to open '$fname'";
+ }
+
+ my @errmsg; # error message list
+ my $echeck = 0;
+ my $c_string;
+ my $c_pend;
+
+ while (<$fh>) {
+ chomp;
+ next if m/^;/;
+
+ print "$_\n" if $opts{tline};
+
+ my $line = $_;
+ my $rest = $_;
+ my $err;
+ if (substr($rest,2,1) =~ m/^[A-Z]$/) {
+ $rest =~ m/^([A-Z]+)$/;
+ $err = $1;
+ $rest = $';
+ } else {
+ $err = substr($rest,0,2);
+ $err =~ s/\s//g;
+ $rest = substr($rest,2);
+ }
+
+ my $fileno;
+ my $lineno;
+
+ if (substr($rest,0,8) =~ m/^\s+(\d+)\s+(\d+)$/) {
+ $fileno = int($1);
+ $lineno = int($2);
+ $rest = substr($rest,8);
+ } else {
+ next;
+ }
+
+ my $dot;
+ if (substr($rest,0,7) eq ' ') {
+ $rest = substr($rest,7);
+ } elsif (substr($rest,0,7) =~ m/^\s([0-7]{6})/) {
+ $dot = oct($1);
+ $rest = substr($rest,7);
+ } else {
+ next;
+ }
+
+ my @dat;
+ my $isbyte;
+
+ # words ?
+ if ($rest =~ m/^(\s([0-7]{6})){1,3}/) {
+ for (my $i=0; $i<3; $i++) {
+ last unless substr($rest,1,6) =~ m/[0-7]{6}/;
+ push @dat, oct(substr($rest,1,6));
+ $rest = substr($rest,7);
+ }
+ # bytes ?
+ } elsif ($rest =~ m/^(\s([0-7]{3})){1,5}/) {
+ for (my $i=0; $i<5; $i++) {
+ last unless substr($rest,1,3) =~ m/[0-7]{3}/;
+ $isbyte = 1;
+ push @dat, oct(substr($rest,1,3));
+ $rest = substr($rest,4);
+ }
+ $rest = substr($rest,1);
+ }
+
+ # look for expect condition (unless one is pending)
+ if ($c_pend) {
+ $c_pend = undef;
+ } else {
+ if ($rest =~ m/;;!!(.*)$/) {
+ $c_string = $1;
+ if ($rest =~ m/^\s*;;!!/) {
+ $c_pend = 1;
+ next;
+ }
+ }
+ }
+
+ # no expect condition defined: look for unexpected etags
+ unless (defined $c_string) {
+ if ($err ne '') {
+ push @errmsg,
+ {msg => sprintf("unexpected error '%s'", $err),
+ line => $line};
+ }
+ next;
+ }
+
+ # expect condition defined: parse it
+ my $c_err;
+ my $c_dot;
+ my @c_dat;
+
+ my $c_rest = $c_string;
+ if ($c_rest =~ m/^\s*([A-Z]+)/) {
+ $c_err = $1;
+ $c_rest = $';
+ }
+ if ($c_rest =~ m/^\s*([0-7]{6}:)/) {
+ $c_dot = oct($1);
+ $c_rest = $';
+ }
+ while (length($c_rest)) {
+ last unless $c_rest =~ m/^\s*([0-7]+)/;
+ push @c_dat, oct($1);
+ $c_rest = $';
+ }
+
+ unless ($c_rest =~ m/^\s*$/) {
+ push @errmsg,
+ {msg => sprintf("can't parse expect, rest='%s'", $c_rest),
+ line => ';;!! ' . $c_string};
+ $c_string = undef;
+ next;
+ }
+
+ if ($opts{tcheck}) {
+ print "exp: ";
+ printf " err=%s", $c_err if defined $c_err;
+ printf " dot=%6.6o", $c_dot if defined $c_dot;
+ if (scalar(@c_dat)) {
+ print " dat=";
+ foreach (@c_dat) {
+ printf "%6.6o ", $_;
+ }
+ }
+ print "\n";
+ }
+
+ if (defined $c_err) {
+ if ($c_err ne $err) {
+ push @errmsg,
+ {msg => sprintf("error mismatch: found='%s', expect='%s'",
+ $err, $c_err),
+ line => $line};
+ }
+ }
+
+ if (defined $c_dot) {
+ if (defined $dot) {
+ if ($c_dot != $dot) {
+ push @errmsg,
+ {msg => sprintf(". mismatch: found=%6.6o, expect=%6.6o",
+ $dot, $c_dot),
+ line => $line};
+ }
+ } else {
+ push @errmsg,
+ {msg => sprintf(". check miss: nothing found, expect=%6.6o",
+ $c_dot),
+ line => $line};
+ }
+ }
+
+ if (scalar(@c_dat)) {
+ my $nc = scalar(@c_dat);
+ $nc = scalar(@dat) if $nc < scalar(@dat);
+ for (my $i=0; $i<$nc; $i++) {
+ if (defined $c_dat[$i] && defined $dat[$i]) {
+ if ($c_dat[$i] != $dat[$i]) {
+ push @errmsg,
+ {msg => sprintf("data %d mismatch: found=%6.6o, expect=%6.6o",
+ $i, $dat[$i], $c_dat[$i]),
+ line => $line};
+ }
+ } elsif (defined $c_dat[$i] && ! defined $dat[$i]) {
+ push @errmsg,
+ {msg => sprintf("data %d mismatch: nothing found, expected=%6.6o",
+ $i, $c_dat[$i]),
+ line => $line};
+ } elsif (! defined $c_dat[$i] && defined $dat[$i]) {
+ push @errmsg,
+ {msg => sprintf("data %d mismatch: found=%6.6o, nothing expected",
+ $i, $dat[$i]),
+ line => $line};
+ }
+ }
+ }
+
+ # trace expects
+ if ($opts{tcheck} && $echeck != scalar(@errmsg)) {
+ $echeck = scalar(@errmsg);
+ printf "FAIL: %s\n", $errmsg[-1]{msg};
+ }
+
+ # invalidate expect condition
+ $c_string = undef;
+ }
+
+ # done with file
+ my $verdict = scalar(@errmsg) ? 'FAILED' : 'OK';
+ printf "asm-11_expect: %s %s\n", $fname, $verdict;
+ foreach (@errmsg) {
+ printf " FAIL: %s\n in: %s\n", $$_{msg}, $$_{line};
+ }
+
+ $errcnt += scalar(@errmsg);
+
+ return;
+}
+
+#-------------------------------------------------------------------------------
+
+sub print_help {
+ print "usage: asm-11_expect \n";
+ print " --tline trace input lines\n";
+ print " --tcheck trace expect checks\n";
+ return;
+}
asm-11_expect
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xilinx_vhdl_memcolltype_fix
===================================================================
--- xilinx_vhdl_memcolltype_fix (nonexistent)
+++ xilinx_vhdl_memcolltype_fix (revision 33)
@@ -0,0 +1,21 @@
+#!/bin/sh
+# $Id: xilinx_vhdl_memcolltype_fix 93 2007-10-28 21:24:44Z mueller $
+#
+# remove the lines
+#
+# variable Write_A_Write_B : memory_collision_type := Write_A_Write_B;
+# variable Read_A_Write_B : memory_collision_type := Read_A_Write_B;
+# variable Write_A_Read_B : memory_collision_type := Write_A_Read_B;
+# variable Write_B_Write_A : memory_collision_type := Write_B_Write_A;
+# variable Read_B_Write_A : memory_collision_type := Read_B_Write_A;
+# variable Write_B_Read_A : memory_collision_type := Write_B_Read_A;
+#
+# from vhd sources. These self-referencial init are wrong and cause ghdl to
+# choke. The awk script checks quite closely for this patterns.
+
+for file in `egrep -l 'variable.*(Read|Write)_(A|B)_(Read|Write)_(A|B)' *.vhd`
+do
+ echo "# strip 'variable.. memory_collision_type..' in $file"
+ mv $file $file.old
+ awk '! /variable.*(Read|Write)_(A|B)_(Read|Write)_(A|B).*memory_collision_type.*(Read|Write)_(A|B)_(Read|Write)_(A|B)/ {print $0}' $file.old > $file
+done
xilinx_vhdl_memcolltype_fix
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xilinx_tsim_xon
===================================================================
--- xilinx_tsim_xon (nonexistent)
+++ xilinx_tsim_xon (revision 33)
@@ -0,0 +1,99 @@
+#!/usr/bin/perl -w
+# $Id: xilinx_tsim_xon 314 2010-07-09 17:38:41Z mueller $
+#
+# Copyright 2010- by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Version Comment
+# 2010-05-06 289 1.0 Initial version
+#
+#
+# Add "XON => false," defs in X_FF and X_SFF instances when name of the
+# instance is matched by a regexp found in a descriptor file.
+#
+# Logic:
+# looks for lines like
+# : X_FF
+# generic map(
+# and adds
+# XON => false, -- added by xilinx_tsim_xon tool --
+# if is matched by a regexp found in file stem..tsim_xon_dat
+#
+# all old 'XON => false' lines in input file are removed first, so this
+# tool can be rerun with changing desciptor files.
+#
+
+use strict;
+
+my $stem = shift;
+
+if (not defined $stem) {
+ print "xilinx_tsim_xon-E: call with file stem\n";
+ exit 1;
+}
+
+my $file_vhd = $stem . "_tsim.vhd";
+my $file_dsc = $stem . ".tsim_xon_dat";
+
+if (! -r $file_vhd) {
+ print "xilinx_tsim_xon-E: $file_vhd not found or readable\n";
+ exit 1;
+}
+if (! -r $file_dsc) {
+ print "xilinx_tsim_xon-E: $file_dsc not found or readable\n";
+ exit 1;
+}
+
+my @dsc_list;
+open(DFILE, "<$file_dsc") || die ("Can't open descriptor file $file_dsc: $!");
+while () {
+ chomp;
+ s/^\s*//;
+ s/\s*$//;
+ next if m/^#/;
+ next if m/^$/;
+ push @dsc_list, $_;
+}
+close(DFILE);
+
+my $file_tmp = $stem . "_tsim_new.vhd";
+open(OFILE, ">$file_tmp") || die ("Can't open output file $file_tmp: $!");
+open(IFILE, "<$file_vhd") || die ("Can't open input file $file_vhd: $!");
+
+my $match_1 = 0;
+my $name_1;
+
+while () {
+ my $line = $_;
+ next if m/-- added by xilinx_tsim_xon tool --$/;
+ print OFILE $line;
+ my $match = 0;
+ my $name;
+ if ($line =~ m/\s*([a-zA-Z0-9_]+)\s*:\s*(X_FF|X_SFF)/) {
+ $name = $1;
+ foreach my $pat (@dsc_list) {
+ $match = 1 if ($name =~ m/^$pat$/);
+ }
+ }
+ if ($match_1 && $line =~ m/generic map/) {
+ ## print "xilinx_tsim_xon-I: XON=>false for $name_1\n";
+ print OFILE
+ " XON => false, -- added by xilinx_tsim_xon tool --\n";
+ }
+ $match_1 = $match;
+ $name_1 = $name;
+}
+
+close(IFILE);
+close(OFILE);
+
+rename $file_tmp, $file_vhd or die ("Can't rename $file_tmp: $!");
xilinx_tsim_xon
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xst_count_bels
===================================================================
--- xst_count_bels (nonexistent)
+++ xst_count_bels (revision 33)
@@ -0,0 +1,106 @@
+#!/usr/bin/perl -w
+# $Id: xst_count_bels 314 2010-07-09 17:38:41Z mueller $
+#
+# Copyright 2007-2010 by Walter F.J. Mueller
+#
+# This program is free software; you may redistribute and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2, or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for complete details.
+#
+# Revision History:
+# Date Rev Version Comment
+# 2010-04-26 284 1.2.1 add error check for GetOptions
+# 2007-10-28 93 1.2 added -xsts (_ssim based device summary)
+# 2007-06-30 62 1.1 fixed parser, now all bels counted
+# 2007-06-16 57 1.0 Initial version
+
+use 5.005; # require Perl 5.005 or higher
+use strict; # require strict checking
+
+use Getopt::Long;
+
+sub do_file;
+
+my %opts = ();
+
+GetOptions(\%opts, "xstl", "xsts")
+ or die "bad options";
+
+my $do_xstl = defined $opts{xstl};
+my $do_xsts = defined $opts{xsts};
+my $do_plain = not ($do_xstl or $do_xsts);
+
+foreach (@ARGV) { do_file($_); }
+
+#-------------------------------------------------------------------------------
+
+sub do_file {
+ my ($filename) = @_;
+ my %bels;
+ my $cur_bel;
+
+ open (IFILE, $filename) or die "can't open for read $filename";
+ while() {
+ chomp;
+ if (m{^\s*[a-zA-Z0-9_]+\s*:\s*([a-zA-Z0-9_]+)\s*$}) {
+ $cur_bel = $1;
+ } elsif (m{\s*(generic|port)\s+map\s*\(\s*}) {
+ $bels{$cur_bel} += 1 if $cur_bel;
+ } else {
+ $cur_bel = "";
+ }
+ }
+ close (IFILE);
+
+ if ($do_plain) {
+ foreach (sort keys %bels) {
+ printf "%16s : %5d\n", $_, $bels{$_};
+ }
+ }
+
+ if ($do_xsts) {
+ my $n_flop = 0;
+ my $n_luts = 0;
+ my $n_luts_log = 0;
+ my $n_luts_ram = 0;
+ my $n_bram = 0;
+ my $n_mult = 0;
+ my $n_iob = 0;
+
+ foreach (sort keys %bels) {
+ if (/^FD/) {
+ $n_flop += $bels{$_};
+ } elsif (/^LUT/) {
+ $n_luts += $bels{$_};
+ $n_luts_log += $bels{$_};
+ } elsif (/^RAMB/) {
+ $n_bram += $bels{$_};
+ } elsif (/^RAM\d*X.*D$/) {
+ $n_luts += 2 * $bels{$_};
+ $n_luts_ram += 2 * $bels{$_};
+ } elsif (/^RAM\d*X.*S$/) {
+ $n_luts += $bels{$_};
+ $n_luts_ram += $bels{$_};
+ } elsif (/^[IO]BUF$/) {
+ $n_iob += $bels{$_};
+ } elsif (/^MULT/) {
+ $n_mult += $bels{$_};
+ }
+ }
+
+ print "Device utilization summary (_ssim BELS scan):\n";
+ print "---------------------------------------------\n";
+ printf " Number of Flip Flops: %5d\n", $n_flop;
+ printf " Number of LUTs: %5d\n", $n_luts;
+ printf " Number used as logic: %5d\n", $n_luts_log;
+ printf " Number used as RAMs: %5d\n", $n_luts_ram;
+ printf " Number of bonded IOBs: %5d\n", $n_iob;
+ printf " Number of BRAMs: %5d\n", $n_bram;
+ printf " Number of MULT18X18s: %5d\n", $n_mult;
+ }
+}
xst_count_bels
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: .
===================================================================
--- . (nonexistent)
+++ . (revision 33)
.
Property changes :
Added: svn:ignore
## -0,0 +1,35 ##
+*.dep_ghdl
+*.dep_isim
+*.dep_xst
+work-obj93.cf
+*.vcd
+*.ghw
+*.sav
+*.tmp
+*.exe
+ise
+xflow.his
+*.ngc
+*.ncd
+*.pcf
+*.bit
+*.msk
+isim
+isim.log
+isim.wdb
+fuse.log
+*_[sft]sim.vhd
+*_tsim.sdf
+*_xst.log
+*_tra.log
+*_twr.log
+*_map.log
+*_par.log
+*_tsi.log
+*_pad.log
+*_bgn.log
+*_svn.log
+*_sum.log
+*_[dsft]sim.log
+cycfx2prog
+tclshcpp