use strict; use warnings; # 07 00 XREPEAT 0 # 13 00 XENDIR # 14 00 XENDDR # 12 00 XSTATE # 12 01 XSTATE # 02 08 FF XSIR # 02 08 01 XSIR # 08 00 00 00 20 XSDRSIZE # 01 0F FF 8F FF XTDOMASK # 04 00 00 00 00 XRUNTEST # 09 00 00 00 00 F6 E5 F0 93 XSDRTDO # 02 08 FF XSIR # 02 08 FF XSIR # 02 08 FD XSIR # 01 FF FF FF FF XTDOMASK # 09 00 00 00 00 FF FF FF FF XSDRTDO # 02 08 FF XSIR # 07 00 XREPEAT 0 # 07 00 XREPEAT 0 # 13 00 XENDIR # 14 00 XENDDR # 12 00 XSTATE # 12 01 XSTATE # 02 08 FF XSIR # 08 00 00 00 01 XSDRSIZE # 01 00 XTDOMASK # 04 00 00 00 00 XRUNTEST # 09 00 00 XSDRTDO # 00 XCOMPLETE # # http://www.xilinx.com/bvdocs/appnotes/xapp503.pdf # http://www.phys.ufl.edu/~madorsky/sp/svf/src/micro.c # 00 XCOMPLETE # 01 D XTDOMASK # 02 1d XSIR # 03 D XSDR # 04 4 XRUNTEST # 05 ? # 06 ? # 07 1 XREPEAT # 08 4 XSDRSIZE # 09 DD XSDRTDO # 0a DD XSETSDRMASKS # 0b D1X XSDRINC # 0c D XSDRB # 0d D XSDRC # 0e D XSDRE # 0f DD XSDRTDOB # 10 DD XSDRTDOC # 11 DD XSDRTDOE # 12 1 XSTATE # 13 1 XENDIR # 14 1 XENDDR # 15 2d XSIR2 # 16 z XCOMMENT # todo: length is in bits, not in bytes. my $xsvfdata=pack("H*", "070013001400120012010208FF0208010800000020010FFF8FFF04000000000900000000F6E5F0930208FF0208FF0208FD01FFFFFFFF0900000000FFFFFFFF0208FF0700070013001400120012010208FF08000000010100040000000009000000"); my $state= { xsdrlen=>32 }; my @xsvfcmds= ( sub { my $x= shift; return "XCOMPLETE "; }, sub { my $x= shift; my $tdomask= $x->getbytes($state->{xsdrlen});return sprintf("XTDOMASK %s", unpack("H*", $tdomask)); }, sub { my $x= shift; my $len= $x->getbyte(); my $tdival= $x->getbyte(); return sprintf("XSIR %02x: %02x", $len, $tdival); }, sub { my $x= shift; my $tdival= $x->getbytes($state->{xsdrlen}); return sprintf("XSDR %s", unpack("H*", $tdival)); }, sub { my $x= shift; my $time= $x->getdword(); return sprintf("XRUNTEST time %d", $time); }, sub { my $x= shift; return "cmd05 "; }, sub { my $x= shift; return "cmd06 "; }, sub { my $x= shift; my $times= $x->getbyte(); return sprintf("XREPEAT times %d", $times); }, sub { my $x= shift; my $len= $x->getdword(); $state->{xsdrlen}= int(($len+7)/8); return sprintf("XSDRSIZE %08x", $len); }, sub { my $x= shift; my $tdival= $x->getbytes($state->{xsdrlen}); my $tdoexpect= $x->getbytes($state->{xsdrlen}); return sprintf("XSDRTDO %s %s", unpack("H*", $tdival), unpack("H*", $tdoexpect)); }, sub { my $x= shift; my $addrmask= $x->getbytes($state->{xsdrlen}); my $datamask= $x->getbytes($state->{xsdrlen}); return sprintf("XSETSDRMASKS %s %s", unpack("H*", $addrmask), unpack("H*", $datamask)); }, sub { my $x= shift; my $addr= $x->getbytes($state->{xsdrlen}); return sprintf("XSDRINC %s", unpack("H*", $addr)); }, sub { my $x= shift; my $tdival= $x->getbytes($state->{xsdrlen}); return sprintf("XSDRB %s", unpack("H*", $tdival)); }, sub { my $x= shift; my $tdival= $x->getbytes($state->{xsdrlen}); return sprintf("XSDRC %s", unpack("H*", $tdival)); }, sub { my $x= shift; my $tdival= $x->getbytes($state->{xsdrlen}); return sprintf("XSDRE %s", unpack("H*", $tdival)); }, sub { my $x= shift; my $tdival= $x->getbytes($state->{xsdrlen}); my $tdoexpect= $x->getbytes($state->{xsdrlen}); return sprintf("XSDRTDOB %s %s", unpack("H*", $tdival), unpack("H*", $tdoexpect)); }, sub { my $x= shift; my $tdival= $x->getbytes($state->{xsdrlen}); my $tdoexpect= $x->getbytes($state->{xsdrlen}); return sprintf("XSDRTDOC %s %s", unpack("H*", $tdival), unpack("H*", $tdoexpect)); }, sub { my $x= shift; my $tdival= $x->getbytes($state->{xsdrlen}); my $tdoexpect= $x->getbytes($state->{xsdrlen}); return sprintf("XSDRTDOE %s %s", unpack("H*", $tdival), unpack("H*", $tdoexpect)); }, sub { my $x= shift; my $state= $x->getbyte(); return sprintf("XSTATE %02x", $state); }, sub { my $x= shift; my $state= $x->getbyte(); return sprintf("XENDIR %02x", $state); }, sub { my $x= shift; my $state= $x->getbyte(); return sprintf("XENDDR %02x", $state); }, sub { my $x= shift; my $len= $x->getword(); my $tdival= $x->getbytes($len); return sprintf("XSIR2 %04x: %s", $len, unpack("H*", $tdival)); }, sub { my $x= shift; my $cmt= $x->getzstring(); return sprintf("XCOMMENT '%s'", $cmt); }, ); package ByteStream; sub new { my ($class, $data)= @_; return bless { data=>$data, pos=>0, }, $class; } sub getbyte { my ($self)= @_; my $val= unpack("C", substr($self->{data}, $self->{pos}, 1)); $self->{pos}++; return $val; } sub getword { my ($self)= @_; my $val= unpack("n", substr($self->{data}, $self->{pos}, 2)); $self->{pos}+=2; return $val; } sub getdword { my ($self)= @_; my $val= unpack("N", substr($self->{data}, $self->{pos}, 4)); $self->{pos}+=4; return $val; } sub getbytes { my ($self, $len)= @_; my $val= substr($self->{data}, $self->{pos}, $len); $self->{pos}+=$len; return $val; } sub getzstring { my ($self, $len)= @_; my $nul= index($self->{data}, "\x00", $self->{pos}); my $val= substr($self->{data}, $self->{pos}, $nul-$self->{pos}); $self->{pos}=$nul+1; return $val; } sub eof { my ($self)= @_; return $self->{pos}>=length($self->{data}); } package main; my $x= ByteStream->new($xsvfdata); while (!$x->eof) { my $cmd= $x->getbyte(); printf("%02x %s\n", $cmd, $cmd<@xsvfcmds ? $xsvfcmds[$cmd]($x) : "?"); }