diff --git a/.DS_Store b/.DS_Store
index 72ae914635d8697f0b99c0deb7f434552ca941ea..ed95a0055d70ad3b2451ab6627c1423893718c47 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/flow/fm2conv.pl b/flow/fm2conv.pl
new file mode 100755
index 0000000000000000000000000000000000000000..523b8598f20f6d2d9df059dc8940f9cfcbc56fc1
--- /dev/null
+++ b/flow/fm2conv.pl
@@ -0,0 +1,3198 @@
+eval "exec perl -w -S $0 $@" # -*- Perl -*-
+  if ($running_under_some_sh);
+  undef ($running_under_some_sh);
+
+# ------------------------------------------------------------------------------
+# The confidential and proprietary information contained in this file may
+# only be used by a person authorised under and to the extent permitted
+# by a subsisting licensing agreement from Arm Limited or its affiliates.
+#
+#            (C) COPYRIGHT 2001-2013 Arm Limited or its affiliates.
+#                ALL RIGHTS RESERVED
+#
+# This entire notice must be reproduced on all copies of this file
+# and copies of this file may only be made by a person if such person is
+# permitted to do so under the terms of a subsisting license agreement
+# from Arm Limited or its affiliates.
+#
+# ------------------------------------------------------------------------------
+# Version and Release Control Information:
+#
+#  File Name           : fm2conv.pl,v
+#  File Revision       : $Revision: 371321 $
+#
+#  Release Information : Cortex-M System Design Kit-r1p1-00rel0
+#
+# ------------------------------------------------------------------------------
+# Purpose             : Converts an ASCII command file into a hex format,
+#                       suitable for import by the FileReader bus master.
+#                       Checks that the specified commands are compatible
+#                       with the FileReader.
+#
+#                       Options:
+#                            -help
+#                            -quiet
+#                            -adk1
+#                            -busWidth=<databus width>   32 or 64(default)
+#                            -endian=<endianness>        big or little(default)
+#                              Note: big-endian is BE-32 (a.k.a. ARM big-endian)
+#                            -stimarraysize=<size>       default = 5000 (words)
+#                            -infile=<input text file>   default = filestim.m2i
+#                            -outfile=<output hex file>  default = filestim.m2d
+# ------------------------------------------------------------------------------
+
+package main;
+
+use strict;
+use Getopt::Long;
+
+
+# Global variables
+
+# default values for command-line options
+my $help          = 0;
+my $verbose       = 1;
+my $adk1          = 0;
+my $endian        = 'little';
+my $busWidth      = 64;
+$main::infile     = 'filestim.m2i';
+$main::outfile    = '';
+my $arch          = 'ahb2';
+my $stimarraysize = 5000;
+
+
+my %command;              # hash to store stimulus fields
+my %sequence;             # hash to store start of burst info
+my $fileErrors      = 0;  # number of errors in input file
+my $fileWarnings    = 0;  # number of warnings in input file
+my $numCmds         = 0;  # number of commands in input file
+
+my $currCmd         = 0;  # current command
+my $prevCmd         = 0;  # previous command, used in case of loop commands
+my $error           = 0;  # command causing current error
+my $memorySize      = 0;  # counts memory size required by FRBM
+
+my $transCount      = 0;  # no. of transfers remaining in defined-length burst
+my $incrCount       = 0;  # number of transfers for incr burst
+my $loopCount       = 0;  # number of looped S vectors to be expanded
+my $errorsBefore    = 0;  # number of errors before looped S vector
+
+
+my $lineNum         = 0;  # line number
+my $prevLineNum     = 0;  # line number of previous command
+
+my $mismatch        = 0;  # addr/size mismatch warning is pending
+
+my $numLanesBus     = 0;  # Number of lanes determined from the specified
+                          # bus width
+
+my $maxBytesBus     = 8;  # Number of byte-lanes in the internal bus:
+                          # this is a global and is constant for a particular
+                          # version of FileReadCore
+
+my $commentString = '';   # Stores any quoted string in a line of stimulus
+
+# default values for stimulus fields
+$command{'LINE'}      = 0;
+$command{'DIFF'}      = '000000';
+$command{'CMD'}       = '00000000'; # idle
+$command{'ADDR'}      = '00000000';
+$command{'DATA'}      = '0000000000000000';
+$command{'MASK'}      = '';
+$command{'SIZE'}      = '000';
+$command{'BUR'}       = '000';
+$command{'PROT'}      = '000000';
+$command{'LOCK'}      = '0';
+$command{'DIR'}       = '0';
+$command{'RESP'}      = '00';
+$command{'WAIT'}      = '0';
+$command{'NUM'}       = 0;
+$command{'UNALIGN'}   = '0';
+$command{'BSTRB'}     = '';
+$command{'FRAMEERR'}  = 0;
+$command{'WRITEBS'}   = '0';
+
+%sequence = %command;
+
+# Get run date
+my ($sec, $min, $hour, $mday, $mon, $year) = localtime(time);
+$year += 1900;
+$mon  += 01;
+
+
+# check Perl version not older than 5.005 as switches not supported
+if ($] < 5.005) {
+  warn "******************* WARNING 128 *******************\n".
+       "No command line switches supported!\n".
+       "Default values will be used.\n".
+       "Recommend upgrading to Perl version 5.005 or higher\n\n";
+
+# Get command line options
+} else {
+  GetOptions( "help"            => \$help,
+              "quiet"           => sub {$verbose = 0},
+              "adk1"            => \$adk1,
+              "infile=s"        => \$main::infile,
+              "outfile=s"       => \$main::outfile,
+              "buswidth=s"      => \$busWidth,
+              "arch=s"          => \$arch,
+              "stimarraysize=s" => \$stimarraysize,
+              "endian=s"        => \$endian
+          );
+}
+
+
+if ($verbose == 1)   {
+  print "\n================================================================\n".
+        "= The confidential and proprietary information contained in this file may\n".
+        "= only be used by a person authorised under and to the extent permitted\n".
+        "= by a subsisting licensing agreement from Arm Limited or its affiliates.\n".
+        "=\n".
+        "=            (C) COPYRIGHT 2001-2013 Arm Limited or its affiliates.\n".
+        "=                ALL RIGHTS RESERVED\n".
+        "=\n".
+        "= This entire notice must be reproduced on all copies of this file\n".
+        "= and copies of this file may only be made by a person if such person is\n".
+        "= permitted to do so under the terms of a subsisting license agreement\n".
+        "= from Arm Limited or its affiliates.\n".
+        "=\n".
+        "= Script version : ADK2\n";
+  printf "= Run Date : %02d/%02d/%04d %02d:%02d:%02d",
+  $mday, $mon, $year, $hour, $min, $sec;
+  print "\n================================================================\n\n";
+}
+
+# Help message
+if ($help == 1) {
+  print "Purpose:\n".
+        "  Converts an ASCII command file into a hex format,\n".
+        "  suitable for import by the File Reader Bus Master.\n".
+        "  Checks that the specified commands are compatible\n".
+        "  with the File Reader Bus Master.\n".
+        "\nUsage:\n".
+        "   Reads stimulus from a text file.\n".
+        "   Writes hex data to a text file.\n".
+        "\nOptions:\n".
+        "   -help                   display this help message\n".
+        "   -quiet                  display only ERROR messages\n".
+        "   -adk1                   read an ADK1v1 input stimulus\n".
+        "   -busWidth=<32|64>       default = 64\n".
+        "   -endian=<little|big>    default = little\n".
+        "                           (big-endian is BE-32 'ARM big-endian')\n".
+        "   -stimarraysize=<size>   default = 5000\n".
+        "   -infile=<input file>    default = filestim.m2i\n".
+        "   -outfile=<output file>  default = filestim.m2d\n".
+        "\n================================================================\n";
+  exit(1);
+}
+
+
+# Check that an invalid architecture has not been entered
+$arch = lc($arch);
+if ($arch ne 'ahb2' and $arch ne 'v6') {
+  $arch = 'ahb2';
+  warn "******************* WARNING 133 *******************\n".
+       "The architecture selected is invalid\n".
+       "Architecture must be ahb2 or V6.\n".
+       "ahb2 will be used by default.\n\n";
+}
+
+# Check for options incompatible with ADK1 stimulus
+if ($adk1 == 1) {
+  # Check bus width is 32 bits
+  if ($busWidth != 32) {
+    $busWidth = 32;
+    warn "******************* WARNING 134 *******************\n".
+         "ADK1v1 stimulus format has been selected.\n".
+         "Data bus width of 32 bits will be used by default.\n\n";
+  }
+
+  # Check architecture is AHB2
+  if ($arch eq 'v6') {
+    $arch = 'ahb2';
+    warn "******************* WARNING 135 *******************\n".
+         "ADK1v1 stimulus format has been selected.\n".
+         "ahb2 architecture will be used by default.\n\n";
+  }
+}
+
+# check an invalid busWidth has not been entered
+if ($busWidth != 32 && $busWidth != 64) {
+  $busWidth = 64;
+  warn "******************* WARNING 132 *******************\n".
+       "Data bus width has been selected to be $busWidth bits.\n".
+       "Data bus width must be either 32 or 64 bits.\n".
+       "64 bits will be used by default.\n\n"
+}
+
+$numLanesBus = $busWidth >> 3;
+
+# calculate default output file name
+if ($main::outfile eq '') {
+
+  if($main::infile =~ /([\w\\\/]+)\.\w+/) {
+    $main::outfile = $1.'.m2d';
+  } else {
+    $main::outfile = $main::infile.'.f2d';
+  }
+}
+
+
+
+# Report options selected
+if ($verbose == 1) {
+  print "Input file $main::infile\n";
+  print "Output file $main::outfile\n";
+  print "ADK1v1 stimulus format selected\n"
+    if ($adk1 == 1);
+  print "ADK2 stimulus format selected\n"
+    if ($adk1 == 0);
+  print "$busWidth-bit data bus selected\n";
+  print "ARMv6 AMBA extensions are supported\n"
+    if ($arch eq 'v6');
+  print "${endian}-endian data organisation selected\n";
+  print "\n";
+}
+
+# Check that input and output filenames are not the same
+if ($main::infile eq $main::outfile) {
+  printf "ERROR 20: Input and output file names are identical\n\n";
+  $fileErrors++;
+
+} else {
+  # Open input file
+  unless (open(INPUTFILE, "$main::infile") ) {
+
+    # failed to open input file
+    printf "ERROR 17: Input file does not exist".
+           " or cannot be accessed\n";
+    $fileErrors++;
+  }
+
+  # Open output file
+  unless (open (FILEOUT, ">$main::outfile") ) {
+
+    # failed to open output file
+    printf "ERROR 21: Cannot create output file $main::outfile\n";
+    $fileErrors++;
+  }
+}
+
+# Only continue if no errors
+if ($fileErrors) {
+  die "\nExit with $fileErrors error(s) and $fileWarnings warning(s).\n\n";
+
+} elsif ($verbose == 1) {
+  printf "Reading from text file: %s\n\n", $main::infile;
+
+}
+
+# ------------------------------------------------------------------------------
+#
+#                       Stimulus file parsing
+#
+# Commands are detected by searching for the first non-whitespace character on
+# a line.
+#
+# For each command, first the required fields are retrieved and checked, then
+# any optional fields which are present. If a required field is invalid or
+# missing then an error is raised. If an optional field is invalid or not
+# recognised then a warning is raised.
+# ------------------------------------------------------------------------------
+
+# Process each line of stimulus
+# while there are lines remaining to be read from the file
+while (<INPUTFILE>) {
+
+  # Keep track of stimulus file line numbers
+  $lineNum++;
+
+  # If a character exists on this line and it is not whitespace...
+  if (/\S/) {
+    $commentString = '';
+
+    # Strip comment command text first, if any
+    s/"([\w+|\W+|s+]+)"// and
+      $commentString = $1;
+
+    # Strip comments from end of line
+    s/\s*(\#|\/\/|;|--).*//;
+
+    # Check for adk1 option switch in the stimulus file
+    if (s/^\s*-adk1\b//i) {
+
+      $adk1 = 1;
+
+      if ($verbose == 1) {
+        printf "ADK1v1 stimulus format selected ".
+               "in stimulus file\n", $lineNum;
+      }
+
+
+      # Check bus width is 32 bits
+      if ($busWidth != 32) {
+        $busWidth = 32;
+        $numLanesBus = $busWidth >> 3;
+        warn "******************* WARNING 134 *******************\n".
+             "ADK1v1 stimulus format has been selected.\n".
+             "Data bus width of 32 bits will be used by default.\n\n";
+      }
+
+      # Check architecture is AHB2
+      if ($arch eq 'v6') {
+        $arch = 'ahb2';
+        warn "******************* WARNING 135 *******************\n".
+             "ADK1v1 stimulus format has been selected.\n".
+             "ahb2 architecture will be used by default.\n\n";
+      }
+
+      # Check for anything left on the line
+      CheckInvalidFields();
+      CheckInvalidComment($commentString);
+
+    # If the AltMaster field is present, the entire command is ignored
+    }  elsif (/\baltmaster\b/i and $verbose == 1) {
+
+      printf "Line %4d: WARNING 241: AltMaster field is not supported:".
+             " entire line will be ignored\n", $lineNum;
+      $fileWarnings++;
+
+
+    # Comment commands are handled separately, because they occur in zero
+    # simulation time and cannot be looped
+    } elsif(s/^\s*(C|comm|comment)\b//i) {
+
+      $numCmds++;                         # increment command counter
+
+      $command{'LINE'} = $lineNum;        # get line number
+      $command{'DIFF'} = GetLineDiff();   # calculate line number increment
+
+      # Parse the line
+      ParseC($commentString);
+
+      # Check for anything left on the line
+      CheckInvalidFields();
+
+      # add size on memory required for command to stimulus total
+      CalcMemory('C');
+
+      # write the line to the output file
+      OutputHex();
+
+
+    # If line starts with any other valid command then decode command
+    } elsif(s/^\s*(W|R|S|B|I|P|L|Q|write|read|seq|sequential|busy|idle|poll|loop|quit)\b//i) {
+
+
+      $prevCmd = $currCmd;  # save previous command in case of Loop commands
+      $currCmd = uc(substr($1,0,1));      # get the current command
+
+      $numCmds++;                         # increment command counter
+
+
+      $command{'LINE'} = $lineNum;        # get line number
+      $command{'DIFF'} = GetLineDiff();   # calculate line number increment
+
+
+      # S or B command
+      if ($currCmd eq 'S' or $currCmd eq 'B') {
+
+        # if a burst is not in progress (defined- or undefined-length)
+        if (GetTransCount() == 0 && (GetIncrCount() == 0)) {
+
+            printf "Line %4d: ERROR 84: $currCmd command outside burst".
+                   " (check burst size)\n", $lineNum;
+            $fileErrors++;
+        }
+
+      }
+
+      # Parse the line
+      if    ($currCmd eq 'W') { ParseW() }
+      elsif ($currCmd eq 'R') { ParseR() }
+      elsif ($currCmd eq 'S') { ParseS() }
+      elsif ($currCmd eq 'B') { ParseB() }
+      elsif ($currCmd eq 'I') { ParseI() }
+      elsif ($currCmd eq 'P') { ParseP() }
+      elsif ($currCmd eq 'L') { ParseL() }
+      elsif ($currCmd eq 'Q') { ParseQ() }
+
+      # Check for anything left on the line
+      CheckInvalidFields();
+      CheckInvalidComment($commentString);
+
+      # Unfold looped S vectors
+      if ($loopCount > 0) {
+
+        while($loopCount-- > 0) {
+
+          # align data and mask and check Bstrb
+          LoopedSeq();
+
+          # add size on memory required for command to stimulus total
+          CalcMemory('S');
+
+          # write the line to the output file
+          OutputHex();
+
+          # looped S vectors are on same line of stimulus so increment is zero
+          $command{'DIFF'} = '000000';
+        }
+
+      } else {
+        # add size on memory required for command to stimulus total
+        CalcMemory($currCmd);
+
+        # write the line to the output file
+        OutputHex();
+
+      }
+
+    # Commands not supported by File Read Master are ignored:
+    #  M Memory command
+    #  D Degrant options
+    #  E XVC master event
+    }  elsif (/^\s*([MED])\b/i and $verbose == 1) {
+
+      printf "Line %4d: WARNING 240: $1 command is not supported".
+             " and will be ignored\n", $lineNum;
+      $fileWarnings++;
+
+    # Syntax error if any other non-whitespace character is on the line
+    } elsif (/^\s*(\S+.*)/)  {
+
+      $error = $1;
+      $currCmd = '$error';
+      printf "Line %4d: ERROR 32: Unknown command :".
+             " \"%s\"\n", $lineNum, $error;
+      $fileErrors++;
+    }
+
+  }
+
+  # exit loop if Q command has been detected
+  if ($currCmd eq 'Q') { last }
+
+}
+
+# At End Of File, check for an unfinished defined-length burst (unless errcanc)
+if (GetTransCount() > 0 and $sequence{'RESP'} ne '10' and ($verbose == 1)) {
+  printf "Line %4d: WARNING 144: End of file: Expected further".
+         " transfers in burst\n", $lineNum;
+  $fileWarnings++;
+}
+
+close(INPUTFILE);
+close (FILEOUT);
+
+# End of stimulus error-checking
+CheckArraySize($memorySize, $stimarraysize);
+
+PrintSummary() if ($verbose == 1);
+
+# error code is 1 if any errors
+($fileErrors == 0) ? exit(0) : exit(1);
+
+
+# ------------------------------------------------------------------------------
+#
+# Check size of stimulus does not exceed size of File Read Master array length
+#
+# ------------------------------------------------------------------------------
+
+sub CheckArraySize {
+
+  my $memorySize = shift;
+  my $stimarraysize = shift;
+
+  if (($verbose == 1) and ($memorySize > $stimarraysize)) {
+    print  "\n";
+    print  "================================================================\n";
+    print  "WARNING 136: The compiled stimulus exceeds the specified size of\n";
+    print  "             the FileReader array. Increase the FileReader\n";
+    print  "             StimArraySize generic/parameter and use script\n";
+    print  "             with the -stimarraysize switch.\n";
+    print  "\n";
+    printf "Compiled stimulus size  = %d x 32-bit\n",$memorySize;
+    printf "FileReader array size   = %d x 32-bit\n",$stimarraysize;
+    print  "================================================================\n";
+    $fileWarnings++;
+  }
+}
+
+
+# ------------------------------------------------------------------------------
+#
+# Print a summary of the file conversion process
+#
+# ------------------------------------------------------------------------------
+sub PrintSummary {
+  print  "\n";
+  print  "================================================================\n";
+  printf "Total Warnings                     = %d\n",$fileWarnings;
+  printf "Total Errors                       = %d\n",$fileErrors;
+  printf "Total commands                     = %d\n",$numCmds;
+  printf "FileReader min array size required = %d x 32-bit\n",$memorySize;
+  printf "Output file name                   = %s\n",$main::outfile;
+  print  "================================================================\n";
+}
+
+# ------------------------------------------------------------------------------
+#
+# Write a command to the output (hex) file
+#
+# ------------------------------------------------------------------------------
+
+sub OutputHex  {
+
+  # save output format and handle so that they can be restored
+  my $savedFormat = $~;
+  my $savedFileHandle = select FILEOUT;
+
+  # generate the Function word
+  $command{'FUNCTION'} = BinToHex(
+                                       $command{'CMD'}.
+                                       $command{'SIZE'}.
+                                       $command{'BUR'}.
+                                       $command{'PROT'}.
+                                       $command{'LOCK'}.
+                                       $command{'DIR'}.
+                                       $command{'RESP'}.
+                                       $command{'UNALIGN'}.
+                                       $command{'WRITEBS'}.
+                                       $command{'DIFF'}
+                                      );
+
+  # select output stimulus format for current command type
+  if    ($command{'CMD'} eq '00000000') {$~ = 'WRITECMD'}
+  elsif ($command{'CMD'} eq '00010000') {$~ = 'READCMD'}
+  elsif ($command{'CMD'} eq '00100000') {$~ = 'SEQCMD'}
+  elsif ($command{'CMD'} eq '00110000') {$~ = 'BUSYCMD'}
+  elsif ($command{'CMD'} eq '01000000') {$~ = 'IDLECMD'}
+  elsif ($command{'CMD'} eq '01010000') {$~ = 'POLLCMD'}
+  elsif ($command{'CMD'} eq '01100000') {$~ = 'LOOPCMD'}
+  elsif ($command{'CMD'} eq '01110000') {$~ = 'COMMCMD'}
+  elsif ($command{'CMD'} eq '10000000') {$~ = 'QUITCMD'}
+  else {
+    # default - should never happen
+    printf "WARNING 255: Command undefined, defaulting to IDLE";
+    $~ = 'IDLECMD';
+  }
+
+  write (FILEOUT);
+
+  # reset format and output stream
+  $~ = $savedFormat;
+  select $savedFileHandle;
+
+}
+
+
+# ------------------------------------------------------------------------------
+#
+# W command decoding
+#
+# ------------------------------------------------------------------------------
+sub ParseW {
+
+  $command{'CMD'}  = '00000000';
+
+  # Get mandatory fields
+  $command{'ADDR'} = GetAddrField();
+  $command{'DATA'} = GetDataField();
+
+
+  # get optional fields
+  $command{'MASK'}    = ''; # clear mask, otherwise could get a mismatch from old value
+  $command{'SIZE'}    = GetSizeField();
+  $command{'BUR'}     = GetBurstField();
+  $command{'PROT'}    = GetProtField();
+  $command{'LOCK'}    = GetLockField();
+  $command{'RESP'}    = GetWriteRespField();
+  $command{'UNALIGN'} = GetUnalignField();
+  $command{'BSTRB'}   = GetBstrbField();
+
+  # Check that response and prot agree for Write command
+  CheckWriteProtResp (
+                      $command{'PROT'},
+                      $command{'RESP'}
+                     );
+
+  # Check that size/mask/data agree
+  ($command{'SIZE'}, $command{'DATA'}, $command{'MASK'})
+    = CheckSizeDataMask (
+                          $numLanesBus,
+                          $command{'SIZE'},
+                          $command{'DATA'},
+                          $command{'MASK'},
+                          $command{'BSTRB'},
+                        );
+
+  # Shift data/mask into correct byte lanes
+  ($command{'DATAH'}, $command{'DATAL'}, $command{'MASKH'}, $command{'MASKL'})
+    = AlignDataMask (
+                      $command{'SIZE'},
+                      $command{'DATA'},
+                      $command{'MASK'},
+                      $command{'ADDR'}
+                    );
+
+  # New burst, so check for early burst termination and reset burst counters
+  ResetBurstCount();
+
+  # Check ARMv6 extensions to AMBA2.0
+  ($command{'UNALIGN'}, $command{'BSTRBHEX'}, $command{'WRITEBS'})
+    = CheckUnalignBstrb (
+                          $command{'UNALIGN'},
+                          $command{'BSTRB'},
+                          hex($command{'ADDR'}),
+                          $command{'SIZE'},
+                          0, # not end of unaligned burst
+                          0, # sequence address is not relevant
+                          0  # not an idle transfer
+                        );
+
+  # Check address/size alignment
+  $command{'FRAMEERR'}
+    = CheckAddrAlign(
+                      $command{'SIZE'},
+                      $command{'ADDR'},
+                      $command{'UNALIGN'}
+                     );
+
+
+  # Check any exclusive access is aligned
+  CheckProtUnalign($command{'PROT'}, $command{'UNALIGN'});
+
+  # Initialise burst counters for the remaining transfers in the burst
+  SetBurstCount($command{'BUR'}, $command{'FRAMEERR'});
+
+  # check for burst exceeding 1kB boundary
+  Check1kBdy($command{'SIZE'}, $command{'BUR'}, $command{'ADDR'}, GetTransCount());
+
+  # Save address and control information for start of burst
+  %sequence = %command;
+
+  # Reset unused fields
+  $command{'WAIT'}    = '0';
+  $command{'DIR'}     = '0';
+  $command{'NUM'}     = 0;
+}
+
+
+# ------------------------------------------------------------------------------
+#
+# R command decoding
+#
+# ------------------------------------------------------------------------------
+sub ParseR {
+
+  $command{'CMD'}  = '00010000';
+
+  # get mandatory fields
+  $command{'ADDR'} = GetAddrField();
+  $command{'DATA'} = GetDataField();
+
+  # get optional fields
+  $command{'SIZE'}   = GetSizeField();
+  $command{'MASK'}   = GetMaskField();
+  $command{'BUR'}    = GetBurstField();
+  $command{'LOCK'}   = GetLockField();
+  $command{'PROT'}   = GetProtField();
+  $command{'RESP'}   = GetRespField();
+  $command{'UNALIGN'}= GetUnalignField();
+  $command{'BSTRB'}  = GetBstrbField();
+
+
+  # Check that size/mask/data agree
+  ($command{'SIZE'}, $command{'DATA'}, $command{'MASK'})
+    = CheckSizeDataMask (
+                          $numLanesBus,
+                          $command{'SIZE'},
+                          $command{'DATA'},
+                          $command{'MASK'},
+                          $command{'BSTRB'},
+                        );
+
+  # Shift data/mask into correct byte lanes
+  ($command{'DATAH'}, $command{'DATAL'}, $command{'MASKH'}, $command{'MASKL'})
+    = AlignDataMask (
+                      $command{'SIZE'},
+                      $command{'DATA'},
+                      $command{'MASK'},
+                      $command{'ADDR'}
+                    );
+
+  # New burst, so check for early burst termination and reset burst counters
+  ResetBurstCount();
+
+  # Check ARMv6 extensions to AMBA2.0
+  ($command{'UNALIGN'}, $command{'BSTRBHEX'}, $command{'WRITEBS'})
+    = CheckUnalignBstrb (
+                          $command{'UNALIGN'},
+                          $command{'BSTRB'},
+                          hex($command{'ADDR'}),
+                          $command{'SIZE'},
+                          0, # not end of unaligned burst
+                          0, # sequence address is not relevant
+                          0  # not an idle transfer
+                        );
+
+  # Check address/size alignment
+  $command{'FRAMEERR'}
+    = CheckAddrAlign(
+                      $command{'SIZE'},
+                      $command{'ADDR'},
+                      $command{'UNALIGN'}
+                     );
+
+  # Check any exclusive access is aligned
+  CheckProtUnalign($command{'PROT'}, $command{'UNALIGN'});
+
+  # Initialise burst counters for the remaining transfers in the burst
+  SetBurstCount($command{'BUR'}, $command{'FRAMEERR'});
+
+  # check for burst exceeding 1kB boundary
+  Check1kBdy($command{'SIZE'}, $command{'BUR'}, $command{'ADDR'}, GetTransCount());
+
+  # Save address and control information for start of burst
+  %sequence = %command;
+
+  # Reset unused fields
+  $command{'WAIT'}   = '0';
+  $command{'DIR'}    = '0';
+  $command{'NUM'}    = 0;
+}
+
+
+# ------------------------------------------------------------------------------
+#
+# S command decoding
+#
+# ------------------------------------------------------------------------------
+sub ParseS {
+
+  my $endUnalignedBurst;
+
+  $command{'CMD'} = '00100000';
+
+  # get mandatory data field
+  $command{'DATA'} = GetDataField();
+
+  # retrieve control information from previous W or R command
+  $command{'SIZE'} = $sequence{'SIZE'};
+  $command{'BUR'}  = $sequence{'BUR'};
+  $command{'PROT'} = $sequence{'PROT'};
+  $command{'UNALIGN'} = $sequence{'UNALIGN'};
+
+  # Calculate and save next address in sequence
+  # for purpose of data alignment
+  $command{'ADDR'} = IncAddr( $command{'ADDR'},
+                              $command{'SIZE'},
+                              $command{'BUR'}
+                            );
+
+  # Get optional fields
+  $command{'MASK'}  = GetMaskField();
+  $command{'RESP'}  = GetRespField();
+  $command{'BSTRB'} = GetBstrbField();
+
+  # If an error cancel response, mark the burst to suppress warning of
+  # early burst termination
+  if ($command{'RESP'} eq '10' ) {
+    $sequence{'RESP'} = $command{'RESP'};
+  }
+
+  # Check that size/mask/data agree
+  ($command{'SIZE'}, $command{'DATA'}, $command{'MASK'})
+    = CheckSizeDataMask (
+                          $numLanesBus,
+                          $command{'SIZE'},
+                          $command{'DATA'},
+                          $command{'MASK'},
+                          $command{'BSTRB'}
+                        );
+
+  # Shift data/mask into correct byte lanes
+  ($command{'DATAH'}, $command{'DATAL'}, $command{'MASKH'}, $command{'MASKL'})
+    = AlignDataMask (
+                      $command{'SIZE'},
+                      $command{'DATA'},
+                      $command{'MASK'},
+                      $command{'ADDR'}
+                    );
+
+
+  # Resets warning for Addr/Size alignment
+  ResetMismatch();
+
+  # Test for the end of an unaligned burst
+  $endUnalignedBurst =
+    (GetTransCount() == 1 and $sequence{'FRAMEERR'} == 1) ? 1 : 0;
+
+  # Check ARMv6 extensions to AMBA2.0
+  ($command{'UNALIGN'}, $command{'BSTRBHEX'}, $command{'WRITEBS'})
+    = CheckUnalignBstrb (
+                          $command{'UNALIGN'},
+                          $command{'BSTRB'},
+                          hex($command{'ADDR'}),
+                          $command{'SIZE'},
+                          $endUnalignedBurst,
+                          $sequence{'ADDR'},
+                          0  # not an idle transfer
+                        );
+
+  # if undefined length (INCR) burst
+  if ($sequence{'BUR'} eq '001') {
+
+    # check for burst exceeding 1kB boundary
+    Check1kBdy($sequence{'SIZE'}, $sequence{'BUR'}, $sequence{'ADDR'}, GetIncrCount());
+
+    IncIncrCount();
+
+  } else {
+
+    DecTransCount();
+
+  }
+
+  # Reset unused fields
+  $command{'WAIT'} = '0';
+  $command{'DIR'}  = '0';
+  $command{'LOCK'} = '0';
+  $command{'NUM'}  = 0;
+
+}
+
+
+# ------------------------------------------------------------------------------
+#
+# B command decoding
+#
+# ------------------------------------------------------------------------------
+sub ParseB {
+
+  my $addrTemp;
+  my $endUnalignedBurst;
+
+  $command{'CMD'}  = '00110000';
+
+  # retrieve control information from previous W or R command
+  $command{'SIZE'} = $sequence{'SIZE'};
+  $command{'BUR'}  = $sequence{'BUR'};
+  $command{'PROT'} = $sequence{'PROT'};
+  $command{'UNALIGN'} = $sequence{'UNALIGN'};
+
+  # Get optional fields
+  $command{'WAIT'} = GetWaitField();
+  $command{'BSTRB'}= GetBstrbField();
+
+  # Calculate - but do not save - next address in sequence
+  # for purpose of data alignment
+  $addrTemp =  IncAddr( $command{'ADDR'},
+                        $command{'SIZE'},
+                        $command{'BUR'}
+                      );
+
+
+  # Test for the end of an unaligned burst
+  $endUnalignedBurst =
+    (GetTransCount() == 1 and $sequence{'FRAMEERR'} == 1) ? 1 : 0;
+
+  # Check ARMv6 extensions to AMBA2.0
+  ($command{'UNALIGN'}, $command{'BSTRBHEX'}, $command{'WRITEBS'})
+    = CheckUnalignBstrb (
+                          $command{'UNALIGN'},
+                          $command{'BSTRB'},
+                          hex($addrTemp),
+                          $command{'SIZE'},
+                          $endUnalignedBurst,
+                          $sequence{'ADDR'},
+                          0  # not an idle transfer
+                        );
+
+  # Wait and Resp fields share bits, as they are never both used
+  $command{'RESP'}    = '0'.$command{'WAIT'};
+
+  # if undefined length (INCR) burst
+  if ($sequence{'BUR'} eq '001') {
+    # check for burst exceeding 1kB boundary
+    Check1kBdy($sequence{'SIZE'}, $sequence{'BUR'}, $sequence{'ADDR'}, GetIncrCount());
+  }
+
+  # Reset unused fields
+  $command{'DIR'}     = '0';
+  $command{'LOCK'}    = '0';
+  $command{'NUM'}     = 0;
+  # Note: Address field must not be updated, in case of following S vectors
+}
+
+
+# ------------------------------------------------------------------------------
+#
+# I command decoding
+#
+# ------------------------------------------------------------------------------
+sub ParseI {
+
+  $command{'CMD'}    = '01000000';
+
+  # Get optional fields
+  $command{'ADDR'}   = GetIdleAddrField();
+  $command{'DIR'}    = GetDirField();
+  $command{'SIZE'}   = GetSizeField();
+  $command{'BUR'}    = GetBurstField();
+  $command{'LOCK'}   = GetLockField();
+  $command{'PROT'}   = GetProtField();
+  $command{'WAIT'}   = GetWaitField();
+  $command{'UNALIGN'}= GetUnalignField();
+  $command{'BSTRB'}  = GetBstrbField();
+
+  # Default Size to bus width if not specified
+  $command{'SIZE'} = BytesToHsize($numLanesBus) unless ($command{'SIZE'} ne '');
+
+  # Do not check address/size alignment for idle transfer
+  $command{'FRAMEERR'} = 0;
+
+  # Idle command implies no sequential transfers following
+  # (also checks for early burst termination)
+  ResetBurstCount();
+
+  # Check ARMv6 extensions to AMBA2.0
+  ($command{'UNALIGN'}, $command{'BSTRBHEX'}, $command{'WRITEBS'})
+    = CheckUnalignBstrb (
+                          $command{'UNALIGN'},
+                          $command{'BSTRB'},
+                          hex($command{'ADDR'}),
+                          $command{'SIZE'},
+                          0, # not end of unaligned burst
+                          0, # sequence address is not relevant
+                          1  # is an idle transfer, so no errors reported
+                        );
+
+  # Save address and control information for start of burst
+  %sequence = %command;
+
+  # Wait and Resp fields share bits, as they are never both used
+  $command{'RESP'}    = '0'.$command{'WAIT'};
+
+  # Reset unused fields
+  $command{'NUM'}    = 0;
+}
+
+# ------------------------------------------------------------------------------
+#
+# P command decoding
+#
+# ------------------------------------------------------------------------------
+sub ParseP {
+
+  $command{'CMD'} = '01010000';
+
+  # get mandatory fields
+  $command{'ADDR'} = GetAddrField();
+  $command{'DATA'} = GetDataField();
+
+  # get optional fields
+  $command{'SIZE'}   = GetSizeField();
+  $command{'MASK'}   = GetMaskField();
+  $command{'BUR'}    = GetPollBurstField();
+  $command{'PROT'}   = GetProtField();
+  $command{'TOUT'}   = GetToutField();
+  $command{'UNALIGN'}= GetUnalignField();
+  $command{'BSTRB'}  = GetBstrbField();
+
+  # Check that size/mask/data agree
+  ($command{'SIZE'}, $command{'DATA'}, $command{'MASK'})
+    = CheckSizeDataMask (
+                          $numLanesBus,
+                          $command{'SIZE'},
+                          $command{'DATA'},
+                          $command{'MASK'},
+                          $command{'BSTRB'}
+                        );
+
+  # Shift data/mask into correct byte lanes
+  ($command{'DATAH'}, $command{'DATAL'}, $command{'MASKH'}, $command{'MASKL'})
+    = AlignDataMask (
+                      $command{'SIZE'},
+                      $command{'DATA'},
+                      $command{'MASK'},
+                      $command{'ADDR'}
+                    );
+
+
+  # Burst type can only be SIGN or INCR therefore no S vectors are implied
+  # (also checks for early burst termination)
+  ResetBurstCount();
+
+  # Check ARMv6 extensions to AMBA2.0
+  ($command{'UNALIGN'}, $command{'BSTRBHEX'}, $command{'WRITEBS'})
+    = CheckUnalignBstrb (
+                          $command{'UNALIGN'},
+                          $command{'BSTRB'},
+                          hex($command{'ADDR'}),
+                          $command{'SIZE'},
+                          0, # not end of unaligned burst
+                          0, # sequence address is not relevant
+                          0  # not an idle transfer
+                        );
+
+  # Check address/size alignment
+  $command{'FRAMEERR'}
+    = CheckAddrAlign(
+                      $command{'SIZE'},
+                      $command{'ADDR'},
+                      $command{'UNALIGN'}
+                     );
+
+  # check address alignment
+  if ($command{'FRAMEERR'} == 1)  {
+    printf "Line %4d: ERROR 108: Cannot poll".
+           " an unaligned address\n", $lineNum;
+    $fileErrors++;
+  }
+
+  # Save address and control information for start of burst
+  %sequence = %command;
+
+  # Reset unused fields
+  $command{'WAIT'}   = '0';
+  $command{'LOCK'}   = '0';
+  $command{'DIR'}    = '0';
+  $command{'RESP'}   = '00';
+}
+
+
+# ------------------------------------------------------------------------------
+#
+# L command decoding
+#
+# ------------------------------------------------------------------------------
+sub ParseL {
+
+  $command{'CMD'} = '01100000';
+
+  # get mandatory field
+  $command{'NUM'} = GetNumberField();
+
+  # Looped S vectors must be expanded, because of data alignment
+  if ($prevCmd eq 'S') {
+
+    # Set command to S because loop will be unfolded
+    $command{'CMD'} = '00100000';
+
+    # Set global counter for number of looped vectors remaining
+    $loopCount = hex($command{'NUM'});
+
+    if ($sequence{'BUR'} ne '001') {
+
+      # defined burst length
+      if (GetTransCount() - $loopCount < 0) {
+        printf "Line %4d: ERROR 89: Loop number exceeds".
+               " number of remaining transfers\n", $lineNum;
+        $fileErrors++;
+      }
+
+    } else {
+
+      # undefined length burst
+      # check for burst exceeding 1kB boundary
+      Check1kBdy($sequence{'SIZE'}, $sequence{'BUR'}, $sequence{'ADDR'}, GetIncrCount() + $loopCount - 1);
+    }
+
+
+  } else {
+    # Reset unused fields
+    $command{'SIZE'}    = '000';
+    $command{'UNALIGN'} = '0';
+    $command{'BSTRB'}   = '';
+    $command{'WAIT'}    = '0';
+    $command{'BUR'}     = '000';
+    $command{'PROT'}    = '000000';
+    $command{'LOCK'}    = '0';
+    $command{'DIR'}     = '0';
+    $command{'RESP'}    = '00';
+    $command{'WRITEBS'} = '0';
+  }
+
+  # Record current number of errors to suppress multiple error reporting in loops
+  $errorsBefore = $fileErrors;
+
+}
+
+
+# ------------------------------------------------------------------------------
+#
+# One iteration of looped Sequential command unfolding
+#
+# ------------------------------------------------------------------------------
+sub LoopedSeq {
+
+  my $endUnalignedBurst;
+
+
+  $command{'ADDR'} = IncAddr( $command{'ADDR'},
+                              $command{'SIZE'},
+                              $command{'BUR'}
+                            );
+
+  # Test for the end of an unaligned burst
+  $endUnalignedBurst =
+    (GetTransCount() == 1 and $sequence{'FRAMEERR'} == 1) ? 1 : 0;
+
+
+  # Data and mask will need realigning for new address unless full bus
+  # width is specified. Shift data/mask into correct byte lanes
+  ($command{'DATAH'}, $command{'DATAL'}, $command{'MASKH'}, $command{'MASKL'})
+    = AlignDataMask (
+                      $command{'SIZE'},
+                      $command{'DATA'},
+                      $command{'MASK'},
+                      $command{'ADDR'}
+                    );
+
+  # If not already detected a Bstrb error, perform an additional check on
+  # the extra transfer at the end of an unaligned burst
+  ($command{'UNALIGN'}, $command{'BSTRBHEX'}, $command{'WRITEBS'})
+    = CheckUnalignBstrb (
+                          $command{'UNALIGN'},
+                          $command{'BSTRB'},
+                          hex($command{'ADDR'}),
+                          $command{'SIZE'},
+                          $endUnalignedBurst,
+                          $sequence{'ADDR'},
+                          $fileErrors<=>$errorsBefore # only report error once
+                        );
+
+  # if undefined length (INCR) burst
+  if ($sequence{'BUR'} eq '001') {
+    IncIncrCount();
+
+  } else {
+    DecTransCount();
+
+  }
+}
+
+
+# ------------------------------------------------------------------------------
+#
+# C command decoding
+#
+# ------------------------------------------------------------------------------
+sub ParseC {
+
+  my $commentString = shift;
+  my @commentPacked;
+  my $word;
+  my $i;
+
+  $command{'CMD'} = '01110000';
+
+  # Check comment for illegal characters
+  $commentString = CheckComment($commentString);
+
+  # Pack the comment string into words
+  @commentPacked = PackComment($commentString);
+
+  # Length of array is the number of words
+  $command{'COUNT'} = @commentPacked;
+
+  # Store value in Number field in hex format
+  $command{'NUM'} = ToHex32($command{'COUNT'});
+
+  # Store the packed comment into the appropriate elements of %command
+  $i = 1;
+  foreach $word ( @commentPacked ) {
+    $command{"WORD$i"} = ToHex32($word);
+    $i++;
+  }
+
+  # Note: Unused fields must not be reset, in case comment occurs
+  # inside burst or loop
+}
+
+
+# ------------------------------------------------------------------------------
+#
+# Q command decoding
+#
+# ------------------------------------------------------------------------------
+sub ParseQ {
+
+  $command{'CMD'}  = '10000000';
+
+  # Reset unused fields
+  $command{'UNALIGN'} = '0';
+  $command{'BSTRB'}   = '';
+  $command{'WAIT'}    = '0';
+  $command{'SIZE'}    = '000';
+  $command{'BUR'}     = '000';
+  $command{'PROT'}    = '000000';
+  $command{'LOCK'}    = '0';
+  $command{'DIR'}     = '0';
+  $command{'RESP'}    = '00';
+  $command{'NUM'}     = '0000';
+  $command{'ADDR'}    = '00000000';
+  $command{'WRITEBS'} = '0';
+}
+
+
+# ------------------------------------------------------------------------------
+# Get mandatory address field value
+#
+# I/O: searches from start of line for the address field
+#      returns the value of the address field, or reports an error
+# ------------------------------------------------------------------------------
+sub GetAddrField {
+
+  my $addr;
+
+
+  if (s/\b(?:0x)?([0-9A-F]{8})\b//i) {
+    $addr = $1;
+
+  } else {
+    # mandatory field missing
+    $addr = 0;
+    printf "Line %4d: ERROR 36: Required field is missing or".
+           " in wrong format\n", $lineNum;
+    $fileErrors++;
+
+  }
+
+  return $addr;
+}
+
+
+# ------------------------------------------------------------------------------
+# Get optional address field value
+#
+# I/O: searches along line for the address field
+#      returns the value of the address field
+# ------------------------------------------------------------------------------
+sub GetIdleAddrField {
+
+  my $addr;
+
+  if (s/\b(?:0x)?([0-9A-F]{8})\b//i ) {
+    $addr = $1;
+
+  } else {
+    # default
+    $addr = '00000000';
+
+  }
+
+  return $addr;
+}
+
+
+# ------------------------------------------------------------------------------
+# Get mandatory data field value
+#
+# I/O: searches from start of line for the data field
+#      returns the value of the data field, or reports an error
+# ------------------------------------------------------------------------------
+sub GetDataField {
+
+  my $data;             # (hex string) value of data field in stimulus
+  my $dataFieldWidth;   # width of data field, i.e. number of hex digits
+
+  # Note 'X' is allowed, but may cause an error in the FileReadCore
+  if ($adk1 == 0 and s/\b(?:0x)?([0-9A-FX]{2,32})\b//i) {
+    $data = $1;
+
+  } elsif ($adk1 == 1 and s/\b([0-9A-FX]{8})\b//i) {
+    $data = $1;
+
+  } else {
+    # mandatory field missing
+    $data = 0;
+    printf "Line %4d: ERROR 36: Required field is missing or".
+           " in wrong format\n", $lineNum;
+    $fileErrors++;
+  }
+
+
+  # if data field exists
+  if ($data) {
+
+    $dataFieldWidth = length($data);
+
+    # check if data field width is greater than busWidth
+    if (($dataFieldWidth << 2) > $busWidth) {
+      printf "\nLine %4d: ERROR 48: Data field length exceeds".
+             " data bus width\n", $lineNum;
+      $fileErrors++;
+
+    # check data field width is either 2,4,8 or 16 hex digits
+    } elsif (($dataFieldWidth != 2) && ($dataFieldWidth != 4) &&
+        ($dataFieldWidth != 8) && ($dataFieldWidth != 16)) {
+      printf "\nLine %4d: ERROR 49: Data field is an".
+             " invalid length\n", $lineNum;
+      $fileErrors++;
+
+    }
+
+  }
+
+  return $data;
+}
+
+
+# ------------------------------------------------------------------------------
+# Get mask field value
+#
+# I/O: searches along the current line for a valid mask field value
+#      returns the value of the mask field
+# ------------------------------------------------------------------------------
+sub GetMaskField {
+
+ my $mask;
+ my $maskFieldWidth  = 0;        # width of mask field read from stimulus
+
+  if ($adk1 == 0 and s/\b(?:0x)?([0-9A-F]{2,32})\b//i ) {
+    $mask = $1;
+
+  } elsif ($adk1 == 1 and s/\b([0-9A-F]{8})\b//i) {
+    $mask = $1;
+
+  } else {
+    $mask = '';
+  }
+
+  $maskFieldWidth = length($mask);
+
+  # if mask field exists
+  unless ($mask eq '') {
+
+    # check if mask field width is greater than busWidth
+    if (($maskFieldWidth << 2) > $busWidth) {
+
+      printf "\nLine %4d: ERROR 52: Mask field length exceeds".
+             " data bus width\n", $lineNum;
+      $fileErrors++;
+      $mask = '';
+
+
+    # check mask field width is either 2,4,8 or 16 hex digits
+    } elsif (($maskFieldWidth != 2) && ($maskFieldWidth != 4) &&
+        ($maskFieldWidth != 8) && ($maskFieldWidth != 16)) {
+
+      printf "\nLine %4d: ERROR 53: Mask field is an".
+             " invalid length\n", $lineNum;
+      $fileErrors++;
+      $mask = '';
+
+    }
+  }
+
+  return $mask;
+}
+
+
+# ------------------------------------------------------------------------------
+# Get size field value
+#
+# I/O: searches along the current line for a valid size field value
+#      returns the value of the size field
+# ------------------------------------------------------------------------------
+sub GetSizeField {
+
+  my $size;
+
+  if (s/\bb\b|\bbyte\b|\bsize8\b//i) {
+    $size = '000';
+
+  } elsif (s/\bh\b|\bhword\b|\bsize16\b//i) {
+    $size = '001';
+
+  } elsif (s/\bw\b|\bword\b|\bsize32\b//i) {
+    $size = '010';
+
+  } elsif (s/\bd\b|\bdword\b|\bsize64\b//i) {
+    # 64-bit transfer size not supported in ADK1
+    if($adk1 == 1) {
+    printf "Line %4d: ERROR 40: size64 not supported".
+           " in FileReader ADK1 stimulus\n", $lineNum;
+    $fileErrors++;
+    $size = '010';
+
+    # 64-bit transfer not supported when busWidth set to 32-bit
+    } elsif (($busWidth == 32)) {
+      printf "Line %4d: ERROR 40: size64 not valid".
+             " when outputting to 32-bit busWidth\n", $lineNum;
+      $fileErrors++;
+      $size = ''; # size will be determined later
+
+    } else {
+      $size = '011';
+
+    }
+
+  } elsif (s/\bq\b|\bqword\b|\bsize128\b//i) {
+    printf "Line %4d: ERROR 40: size128 not supported".
+           " by AHB File Reader Master\n", $lineNum;
+    $fileErrors++;
+    $size = ''; # size will be determined later
+
+  } else {
+    $size = ''; # size will be determined later
+
+  }
+
+  return $size;
+}
+
+
+# ------------------------------------------------------------------------------
+# Get burst type
+#
+# I/O: searches along the current line for a valid burst field value
+#      returns the value of the burst field
+# ------------------------------------------------------------------------------
+sub GetBurstField {
+
+  my $burst;
+
+  if (s/\bsing\b|\bsingle\b//i) {
+    $burst = '000';
+
+  } elsif (s/\bincr\b//i) {
+    $burst = '001';
+
+  } elsif (s/\bwrap4\b//i) {
+    $burst = '010';
+
+  } elsif (s/\bincr4\b//i) {
+    $burst = '011';
+
+  } elsif (s/\bwrap8\b//i) {
+    $burst = '100';
+
+  } elsif (s/\bincr8\b//i) {
+    $burst = '101';
+
+  } elsif (s/\bwrap16\b//i) {
+    $burst = '110';
+
+  } elsif (s/\bincr16\b//i) {
+    $burst = '111';
+
+  } else {
+    # default to INCR
+    $burst = '001';
+  }
+
+  return $burst;
+}
+
+
+# ------------------------------------------------------------------------------
+# Get burst type for Poll commands
+#
+# I/O: searches along the current line for a valid burst field value
+#      returns the value of the burst field
+# Only Incr and Single are allowed
+# ------------------------------------------------------------------------------
+sub GetPollBurstField {
+
+  my $burst;
+
+  if (s/\bsing\b|\bsingle\b//i) {
+    $burst = '000';
+
+  } elsif (s/\bincr\b//i) {
+    $burst = '001';
+
+  } elsif (s/\b((wrap|incr)(4|8|16))\b//i) {
+    # invalid burst type for Poll command
+    printf "Line %4d: ERROR 80: Burst type \"$1\" is".
+           " incompatible with P command\n", $lineNum;
+    $fileErrors++;
+
+    # default to INCR
+    $burst = '001';
+
+  } else {
+    # default to INCR
+    $burst = '001';
+  }
+
+  return $burst;
+}
+
+
+# ------------------------------------------------------------------------------
+# Get protection field value
+#
+# I/O: searches along the current line for a valid protection field value
+#      returns the value of the protection field
+# ------------------------------------------------------------------------------
+sub GetProtField {
+
+  my $prot;
+
+  if ($adk1 == 0 ) {
+    # reading adk2 stimulus
+    if (s/\bp([0-1]{6})\b//i) {
+      $prot = $1;
+
+      if ($arch eq 'v6') {
+
+        # Prot[4] should only be asserted if Prot[3] is asserted
+        if  ( substr($prot, 1, 2) eq '10') {
+          printf "Line %4d: ERROR 105: HPROT[4] can only be asserted".
+                 " if HPROT[3] is asserted \n", $lineNum;
+          $fileErrors++;
+          # The value of $prot is not changed, to allow the testing
+          # of invalid values
+        }
+      } else {
+
+        printf "Line %4d: ERROR 96: ARMv6 AMBA extensions are not allowed".
+               " unless V6 architecture is selected: Prot field\n", $lineNum;
+        $fileErrors++;
+        # The value of $prot is not changed, to allow the testing
+        # of invalid values
+
+      }
+
+    } elsif ($arch ne 'v6' and s/\bp([0-1]{4})\b//i) {
+      # add extra leading zeros to ahb2 prot value
+      $prot = '00'.$1;
+
+    } else {
+      # default value
+      $prot = '000000';
+
+    }
+
+  # reading adk1 stimulus
+  } elsif (s/\b([0-1]{4})\b//i) {
+    # add extra leading zeros to ahb2 prot value
+    $prot = '00'.$1;
+
+  } else {
+      # default value
+    $prot = '000000';
+
+  }
+
+  return $prot;
+}
+
+
+# ------------------------------------------------------------------------------
+# Get lock field value
+#
+# I/O: searches along the current line for a valid lock field value
+#      returns the value of the lock field
+# ------------------------------------------------------------------------------
+sub GetLockField {
+
+  my $lock;
+
+  if (s/\block\b//i){
+    $lock = '1';
+
+  } elsif (s/\bnolock\b//i) {
+    $lock = '0';
+
+  } else {
+    $lock = '0';
+
+  }
+
+  return $lock;
+}
+
+
+# ------------------------------------------------------------------------------
+# Get Direction field value
+#
+# I/O: searches along the current line for a valid direction field value
+#      returns the value of the direction field
+# ------------------------------------------------------------------------------
+sub GetDirField {
+
+  my $dir;
+
+  if (s/\bread\b//i) {
+    $dir = '0';
+
+  } elsif (s/\bwrite\b//i) {
+    $dir = '1';
+
+  } else {
+    $dir = '0';
+
+  }
+
+  return $dir;
+}
+
+
+# ------------------------------------------------------------------------------
+# Get Resp field value
+#
+# I/O: searches along the current line for a valid error field value
+#      returns the value of the error field
+# ------------------------------------------------------------------------------
+sub GetRespField {
+
+  my $resp;
+
+
+  if (s/\bok\b|\bokay\b//i) {
+    $resp = '00';
+
+  } elsif (s/\berrcont|errorcont\b//i) {
+    $resp = '01';
+
+  }  elsif (s/\berrcanc|errorcanc\b//i) {
+    $resp = '10';
+
+  } elsif (s/\bxfail\b//i and $adk1 == 0) {
+    # Reading ADK2 stimulus
+
+    $resp = '00';
+
+    if ($arch eq 'v6') {
+      printf "Line %4d: ERROR 104: XFAIL response can only be specified".
+             " for a W command with Prot[5] asserted\n", $lineNum;
+      $fileErrors++;
+
+    } else {
+      printf "Line %4d: ERROR 96: ARMv6 AMBA extensions are not allowed".
+             " unless V6 architecture is selected: Resp field\n", $lineNum;
+      $fileErrors++;
+
+    }
+
+  } else {
+    $resp = '00';
+
+  }
+
+  return $resp;
+}
+
+
+# ------------------------------------------------------------------------------
+# Get Resp field value for Write command
+#
+# I/O: searches along the current line for a valid error field value
+#      returns the value of the error field
+# ------------------------------------------------------------------------------
+sub GetWriteRespField {
+
+  my $resp;
+
+
+  if (s/\bok\b|\bokay\b//i) {
+    $resp = '00';
+
+  } elsif (s/\berrcont|errorcont\b//i) {
+    $resp = '01';
+
+  }  elsif (s/\berrcanc|errorcanc\b//i) {
+    $resp = '10';
+
+  } elsif (s/\bxfail\b//i and $adk1 == 0) {
+    # Reading ADK2 stimulus
+
+    if ($arch eq 'v6') {
+      $resp = '11';
+
+    } else {
+      $resp = '00';
+      printf "Line %4d: ERROR 96: ARMv6 AMBA extensions are not allowed".
+             " unless V6 architecture is selected: Resp field\n", $lineNum;
+      $fileErrors++;
+
+    }
+
+  } else {
+    $resp = '00';
+
+  }
+
+  return $resp;
+}
+
+
+# ------------------------------------------------------------------------------
+# Get Wait field value
+#
+# I/O: searches along the current line for a valid Wait field value
+#      returns the value of the wait field
+# ------------------------------------------------------------------------------
+sub GetWaitField {
+
+  my($wait) = '0';
+
+  if ($adk1 == 0) {
+    # reading adk2 stimulus
+
+    if (s/\bwait\b//i) {
+      $wait = '1';
+
+    } elsif (s/\bnowait\b//i) {
+      $wait = '0';
+
+    }
+
+  } else {
+    # reading adk1 stimulus
+    $wait = '0';
+
+  }
+
+  return $wait;
+}
+
+
+# ------------------------------------------------------------------------------
+# Get Loop mandatory number field value
+#
+# I/O: searches along the current line for a valid number field value
+#      returns a string of the hex value of the number field,
+#      or reports an error an defaults to zero
+# ------------------------------------------------------------------------------
+sub GetNumberField {
+
+  my $num;
+  my $hexNum = '00000000';
+
+  if (s/\b([0-9]{1,10})\b//i) {
+
+    $num = $1;
+
+    if ($num > 2**32-1 or $num < 1) {
+      # number is out of range
+      printf "Line %4d: ERROR 43: Loop number out".
+             " of range [1 to 2^32-1]\n", $lineNum;
+      $fileErrors++;
+      $hexNum = '00000000';
+
+    } else {
+      # convert to hex string
+      $hexNum = ToHex32($num);
+
+    }
+
+  } else {
+    printf "Line %4d: ERROR 37: Loop command must".
+           " have number specified\n", $lineNum;;
+    $fileErrors++;
+    $hexNum = '00000000';
+
+  }
+
+  return $hexNum;
+}
+
+
+# ------------------------------------------------------------------------------
+# Get TimeOut field value
+#
+# I/O: searches along the current line for a valid repeat field value
+#      returns the value of the repeat field
+# ------------------------------------------------------------------------------
+sub GetToutField {
+
+  my $num;
+  my $hexNum = '00000000';
+
+  # TimeOut field is not allowed for ADK1 stimulus
+  if ($adk1 == 0 and s/\b[t|T]([0-9]{1,10})\b//i) {
+
+    $num = $1;
+
+    if ($num > 2**32-1) {
+      # number is out of range
+      printf "Line %4d: ERROR 44: Time out value out".
+             " of range [0 to 2^32-1]\n", $lineNum;
+      $fileErrors++;
+      $hexNum = '00000000';
+
+    } else {
+      # convert to hex string
+      $hexNum = ToHex32($num);
+
+    }
+
+  } else {
+    $hexNum = '00000000';
+
+  }
+
+  return $hexNum;
+}
+
+
+# ------------------------------------------------------------------------------
+# Get Unalign field value
+#
+# I/O: searches along the current line for a valid Unalign field value
+#      returns the value of the Unalign field
+# ------------------------------------------------------------------------------
+sub GetUnalignField {
+
+  my $unalign;
+
+  if (s/\balign\b//i) {
+    $unalign = '0';
+
+  } elsif (s/\bunalign\b//i) {
+    $unalign = '1';
+
+  } else {
+    $unalign = '';
+
+  }
+
+  if  ( $arch ne 'v6' and $unalign ne '' ) {
+    printf "Line %4d: ERROR 96: ARMv6 AMBA extensions are not allowed".
+           " unless V6 architecture is selected: Unalign field\n", $lineNum;
+    $fileErrors++;
+  }
+
+  return $unalign;
+}
+
+
+# ------------------------------------------------------------------------------
+# Get Bstrb field value
+#
+# I/O: Searches along the current line for a valid Bstrb field value
+#      Returns the value of the Bstrb field as a numeric value
+#      or empty string if not present or in error
+# ------------------------------------------------------------------------------
+sub GetBstrbField {
+
+  my $bstrb;
+  my $bstrbFieldWidth = 0;
+
+  # If Bstrb field found
+  if (s/\b[s|S]([0|1]{1,16})\b//i) {
+
+    $bstrb = $1;
+    $bstrbFieldWidth = length($bstrb);
+
+    if  ( $arch ne 'v6' ) {
+      printf "Line %4d: ERROR 96: ARMv6 AMBA extensions are not allowed".
+             " unless V6 architecture is selected: Bstrb field\n", $lineNum;
+      $fileErrors++;
+      $bstrb = '';
+
+      # check that Bstrb is a valid length for the selected databus width
+    } elsif ($bstrbFieldWidth > $numLanesBus) {
+
+      printf "Line %4d: ERROR 100: Byte Lane Strobe is not".
+             " valid for selected busWidth.\n", $lineNum;
+      $fileErrors++;
+      $bstrb = '';
+
+    # check Bstrb field width is either 1,2,4 or 8 binary digits
+    } elsif (($bstrbFieldWidth != 1) && ($bstrbFieldWidth != 2) &&
+          ($bstrbFieldWidth != 4) && ($bstrbFieldWidth != 8)) {
+
+      printf "Line %4d: ERROR 100: Byte Lane Strobe is an".
+             " invalid length\n", $lineNum;
+      $fileErrors++;
+      $bstrb = '';
+
+    }
+
+  } else {
+    $bstrb = '';
+
+  }
+
+  return $bstrb;
+}
+
+
+# ------------------------------------------------------------------------------
+# Calculate line difference
+#
+# I/O: reads current line number and finds the difference from the last command
+#      returns the difference
+# ------------------------------------------------------------------------------
+sub GetLineDiff {
+
+  my $lineDiffBin;
+  my $lineDiff;
+
+  $lineDiff = ($lineNum - $prevLineNum);
+  $prevLineNum = $lineNum;
+
+  # if there are more than 63 blank or comment lines between two commands
+  #  issue a warning to decrease gap, or add a blank C command i.e. C ""
+  if ($lineDiff > 63) {
+    $lineDiff = 63;
+    if ($verbose == 1) {
+      printf "Line %4d: WARNING 169: Number of blank or comment lines".
+             " before command exceeds 63\n", $lineNum;
+      $fileWarnings++;
+    }
+  }
+
+  # convert $lineDiff into 6-digits binary
+  $lineDiffBin = substr ToBin8($lineDiff), 2, 6;
+
+  return $lineDiffBin;
+}
+
+
+# ------------------------------------------------------------------------------
+# Check invalid fields
+#
+# Reports any non-whitespace words as errors
+# ------------------------------------------------------------------------------
+sub CheckInvalidFields {
+
+  my $item;
+
+  # First check for unsupported fields that may be ignored
+  if (s/\bdegrant\b//i and $verbose == 1) {
+
+    printf "Line %4d: WARNING 242: DeGrant field is not supported".
+           " and will be ignored\n", $lineNum;
+    $fileWarnings++;
+  }
+
+
+   # If there is anything but whitespace left on the line, it is invalid.
+   # Only report warnings if verbose is requested
+   if (($verbose == 1) and /\S/) {
+
+    foreach $item ( split ) {
+       printf "Line %4d: WARNING 164: \"$item\" is an".
+              " invalid or duplicate field\n", $lineNum;
+       $fileWarnings++;
+    }
+  }
+}
+
+
+# ------------------------------------------------------------------------------
+# Check invalid comment
+#
+# Reports error if comment string is found where not expected
+# ------------------------------------------------------------------------------
+sub CheckInvalidComment {
+
+  my $item = shift;
+
+  if ($item ne '') {
+     printf "Line %4d: WARNING 164: \"$item\" is an".
+            " invalid or duplicate field\n", $lineNum;
+     $fileWarnings++;
+  }
+}
+
+
+# ------------------------------------------------------------------------------
+# Pack comment
+#
+# Converts a character string to a list of up to 20 32-bit words
+# Pads with whitespace
+# Reports error for zero-length string
+# ------------------------------------------------------------------------------
+sub PackComment {
+
+  my $commentString = shift;
+  my @words;
+
+  my $length;
+
+  $length = length($commentString);
+
+  if ($length == 0) {
+
+    # Error if zero-length string
+    printf "Line %4d: ERROR 38: Comment command requires".
+           " a string within double quotes\n", $lineNum;
+    $fileErrors++;
+    $commentString = "\x00"; # Use a NULL character instead of the empty string
+
+  } elsif ($length > 80 and $verbose == 1) {
+
+      # warn if string longer than 80 chars
+      printf "Line %4d: WARNING 168: Comment exceeds limit".
+             " of 80 characters. Message will be truncated\n", $lineNum;
+      $fileWarnings++;
+
+  }
+
+
+  # Convert string to up to 20 32-bit words
+  # String is first padded with 3 null characters
+  @words = unpack ( 'L20', $commentString."\x00\x00\x00" );
+
+  return @words
+}
+
+# ------------------------------------------------------------------------------
+# Check comment
+#
+# Replaces invalid comment characters with a dash (-) and warns.
+# ------------------------------------------------------------------------------
+sub CheckComment {
+
+  my $commentString = shift;
+  my $item;
+
+  # Report invalid characters in comment string.
+  # Note: every match character has been escaped (using \) because most of
+  # these characters have a special meaning inside a regular expression
+  if ($verbose == 1) {
+    for $item ($commentString =~
+      /[^\w\!\$\%\^\&\*\(\)\-\+\=\{\}\[\]\:\;\@\'\~\#\<\>\,\.\?\/\|\ ]/cg) {
+
+      printf "Line %4d: WARNING 165: $item is an".
+             " invalid character\n", $lineNum;
+      $fileWarnings++;
+    }
+  }
+
+  # Replace invalid characters with a dash (-).
+  # Note: every match character has been escaped (using \) because most of
+  # these characters have a special meaning inside a regular expression
+  $commentString =~
+    s/[^\w\!\$\%\^\&\*\(\)\-\+\=\{\}\[\]\:\;\@\'\~\#\<\>\,\.\?\/\|\ ]/-/g;
+
+  return $commentString;
+}
+
+
+# ------------------------------------------------------------------------------
+# Check Prot and Resp fields for write command
+#
+# Can only expect XFAIL for a Write command with Prot[5] set
+# ------------------------------------------------------------------------------
+sub CheckWriteProtResp {
+
+my $prot = shift;
+my $resp = shift;
+
+  if ($resp eq '11' and $prot !~ '1[0-1]{5}') {
+    printf "Line %4d: ERROR 104: XFAIL response can only be specified".
+           " for a W command with Prot[5] asserted\n", $lineNum;
+    $fileErrors++;
+  }
+}
+
+
+# ------------------------------------------------------------------------------
+# Increment address
+#
+# Calculate next address in sequence
+#
+# ------------------------------------------------------------------------------
+sub IncAddr {
+
+  my $incrAddr = hex(shift);
+  my $sizeBytes = HsizeToBytes(shift);
+  my $burst = shift;
+
+  my $burstLength = 0;
+  my $wrapBytes = 0; # number of bytes in burst
+
+  # calculate beats in wrapping bursts
+  if ($command{'BUR'} eq '010') {
+
+    $burstLength = 4;
+
+  } elsif ($command{'BUR'} eq '100')  {
+
+    $burstLength = 8;
+
+  } elsif ($command{'BUR'} eq '110')  {
+
+    $burstLength = 16;
+  }
+
+  # Address is always incremented from an aligned version
+  $incrAddr &= (0xFFFFFFFF - $sizeBytes + 1);
+
+  # Increment address by size of transfer
+  $incrAddr += $sizeBytes;
+
+  # Trap boundaries for wrapping bursts
+  if ($burstLength > 0) {
+
+    # number of bytes in burst (size * beats)
+    $wrapBytes = $sizeBytes * $burstLength;
+
+    if ($incrAddr % $wrapBytes == 0) {
+      $incrAddr -= $wrapBytes;
+    }
+  }
+
+  $incrAddr = ToHex32($incrAddr);
+
+  return $incrAddr;
+}
+
+
+# ------------------------------------------------------------------------------
+# Determine the transfer size
+#
+# Check transfer size integrity
+#   Checks there are no discrepancies in transfer size by comparing values of
+#    the Size, Data and Mask field.
+# Assumes Data and Mask size not > bus width
+# ------------------------------------------------------------------------------
+
+sub CheckSizeDataMask {
+
+  my $bytesBus  = shift;
+  my $size      = shift;
+  my $data      = shift;
+  my $mask      = shift;
+  my $bstrb     = shift;
+
+  # Lengths of fields (in bytes)
+  my $bytesSize = $size eq '' ? 0 : HsizeToBytes($size);
+  my $bytesData = length($data) >> 1; # Number of bytes is number of hex digits /2
+  my $bytesMask = length($mask) >> 1; # Number of bytes is number of hex digits /2
+  my $bytesBstrb = length($bstrb);    # Number of bytes is number of binary digits
+  my $bytesResult   = 0;
+
+  my $mismatchError = 0;
+
+
+  # Size field sets size whenever specified
+  if ( ($bytesSize > 0) ) {
+    $bytesResult = $bytesSize;
+  }
+
+  # Data only sets size if data field is specified and
+  # size implied by data < busWidth
+  if ( ($bytesData > 0)  and ($bytesData < $bytesBus) ) {
+    if ($bytesResult == 0) { # resultant size not already set
+    # size of data sets transfer size
+    $bytesResult = $bytesData;
+    } elsif ($bytesResult != $bytesData) {
+      $mismatchError = 1; # set mismatch error flag
+    }
+  }
+
+
+  # Mask only sets size if size implied by mask < busWidth
+  if ( ($bytesMask > 0) and  ($bytesMask < $bytesBus) ) {
+    if ($bytesResult == 0) { # resultant size not already set
+    # size of mask sets transfer size
+    $bytesResult = $bytesMask;
+    } elsif ($bytesResult != $bytesMask)  {
+      $mismatchError = 1; # set mismatch error flag
+    }
+  }
+
+  # Bstrb only sets size if size implied by Bstrb < busWidth
+  if ( ($bytesBstrb > 0) and  ($bytesBstrb < $bytesBus) ) {
+    if ($bytesResult == 0) { # resultant size not already set
+    # size of Bstrb sets transfer size
+    $bytesResult = $bytesBstrb;
+    } elsif ($bytesResult != $bytesBstrb)  {
+      printf "Line %4d: ERROR 57: Transfer size mismatch:".
+             " Check Bstrb\n", $lineNum;
+      $fileErrors++;
+    }
+  }
+
+  # Default resultant size is the bus width
+  $bytesResult = $bytesBus unless $bytesResult > 0;
+
+  # Default size is the resultant size
+  $bytesSize = $bytesResult unless $bytesSize > 0;
+
+  # If a transfer size mismatch occurred, display Error else
+  #  check if Data/Mask needs aligning within busWidth
+  if ($mismatchError == 1)  {
+    printf "Line %4d: ERROR 56: Transfer size mismatch:".
+           " Check Size/Data/Mask\n", $lineNum;
+    $fileErrors++;
+  }
+
+  # Convert resultant size back to binary string
+  $size = BytesToHsize($bytesSize);
+
+  # Default data if data not specified
+  if ($data eq '' ) {
+    $bytesData = $bytesBus;  # default data is zero across entire bus
+    $data = '0' x ($bytesData << 1); # Number of hex digits is number of bytes *2
+  }
+
+  # Default mask if mask not specified
+  if ($mask eq '') {
+    if ($adk1 == 0) {
+      $bytesMask = $bytesResult;  # inactive byte lanes are masked out for ADK2
+    } else {
+      $bytesMask = $bytesBus;     # entire bus is compared with data for ADK1
+    }
+    $mask = 'F' x ($bytesMask << 1); # Number of hex digits is number of bytes *2
+  }
+
+  return ($size, $data, $mask);
+
+}
+
+# ------------------------------------------------------------------------------
+# Shifts the data and mask to the correct byte lanes
+# ------------------------------------------------------------------------------
+sub AlignDataMask {
+
+  my $size      = shift;
+  my $data      = shift;
+  my $mask      = shift;
+  my $address   = shift;
+
+  # Lengths of fields (in bytes)
+  my $bytesSize = HsizeToBytes($size);
+  my $bytesData = length($data) >> 1; # Number of bytes is number of hex digits /2
+  my $bytesMask = length($mask) >> 1; # Number of bytes is number of hex digits /2
+
+  # intermediate variables for data alignment
+  my $dataH;
+  my $dataL;
+
+  # intermediate variables for mask alignment
+  my $maskH;
+  my $maskL;
+
+  # low order address bits
+  my $offset;
+
+  # Calculate position within the hex string that the data/mask will start
+  $offset = hex($address)
+            & (($maxBytesBus-1) << FromBin8($size)) & ($maxBytesBus-1);
+
+  # Modify the offset according to the endianness of the transfer
+  $offset = MakeOffsetBigEndian( $offset ) if ($endian eq 'big');
+
+  # Shift the data to the correct byte lanes
+  ($dataH, $dataL) = ShiftData( $data, $bytesData, $offset );
+
+  # Shift the mask to the correct byte lanes
+  ($maskH, $maskL) = ShiftData( $mask, $bytesMask, $offset );
+
+  return ($dataH, $dataL, $maskH, $maskL);
+}
+
+
+# ------------------------------------------------------------------------------
+# Shift data or mask into correct byte lanes
+# and split into High and Low words
+#
+#  Assumes 64 bit data representation
+# ------------------------------------------------------------------------------
+sub ShiftData {
+
+  my $value     = shift;
+  my $numLanes  = shift;
+  my $offset    = shift;
+
+  my $wordH;
+  my $wordL;
+
+  # mask and data are zero outside the specified transfer
+  my $fullWidth = '0000000000000000';
+
+  # align the address offset with the length of the data
+  $offset &= (0x100 - $numLanes); # Note 0x100 will cope up to HSIZE =1024 bits
+
+  # Shift the mask or data to the correct byte lanes
+  substr $fullWidth, ($maxBytesBus-$offset-$numLanes) << 1, $numLanes << 1, $value;
+
+  # Split the data into high and low words
+  $wordH = substr $fullWidth, 0, $maxBytesBus;
+  $wordL = substr $fullWidth, $maxBytesBus, $maxBytesBus;
+
+  return ($wordH, $wordL);
+}
+
+
+# ------------------------------------------------------------------------------
+# Check for burst exceeding 1kB boundary
+#
+# Arguments: HSIZE, HBURST, HADDR, number of transfer to check
+# ------------------------------------------------------------------------------
+sub Check1kBdy {
+
+  my $transSize = TransSize(shift);
+  my $currBurst = shift;
+  my $startAddr = hex(shift);
+  my $numTransfers = shift;
+
+
+  # test only non-wrapping bursts
+  if  (
+        (
+          $currBurst eq '000' ||
+          $currBurst eq '001' ||
+          $currBurst eq '011' ||
+          $currBurst eq '101' ||
+          $currBurst eq '111'
+        )
+    # Check that last transfer in burst is within the same 1k partition
+    and (
+          ( ($numTransfers * $transSize + $startAddr) & hex('FFFFFC00') )
+           != ($startAddr & hex('FFFFFC00'))
+        )
+      ) {
+        printf "Line %4d: ERROR 88: Burst would exceed".
+               " 1kB boundary : R\n", $lineNum;
+        $fileErrors++;
+  }
+}
+
+
+# ------------------------------------------------------------------------------
+# Convert size field to Number of transfers
+#
+# ------------------------------------------------------------------------------
+sub TransSize {
+
+  my $sizeField = shift;
+  my $transSize = 1;
+
+  # assign TransSize
+  if    ($sizeField eq '000') {$transSize = 1;}
+  elsif ($sizeField eq '001') {$transSize = 2;}
+  elsif ($sizeField eq '010') {$transSize = 4;}
+  elsif ($sizeField eq '011') {$transSize = 8;}
+
+  return $transSize;
+}
+
+
+# ------------------------------------------------------------------------------
+# Check Bstrb and Unalign field integrity
+#   Checks there are no discrepancies in values specified by Bstrb and Unalign
+#   fields. Also generates correct value of Bstrb where necessary.
+#   Returns updated Unalign and Bstrb fields.
+#   The parameter $seqAddress only need be passed if $endOfUnaligned == 1
+#
+# Note! this function must be called before $transCount is updated
+# ------------------------------------------------------------------------------
+sub CheckUnalignBstrb {
+
+  my $unalign         = shift;
+  my $bstrb           = shift;
+  my $address         = shift;
+  my $size            = shift;
+  my $endOfUnaligned  = shift;
+  my $seqAddress      = shift;
+  my $idleTransfer    = shift;  # if true, suppresses error checks
+
+
+  my $offset;
+  my $offsetAligned;
+  my $seqOffset;
+
+  my $numLanesTrans;
+  my $numLanesUnalign;
+
+  my $bstrbAligned;
+  my $bstrbDefault;
+  my $bstrbCore;
+
+  my $unalignImplied;
+  my $writeBstrb;
+
+
+  # Calculate the number of byte lanes in the transfer
+  $numLanesTrans = HsizeToBytes($size);
+
+  # Calculate the lower order address bits of an equivalent aligned transfer
+  $offsetAligned =
+    $address &
+    (($maxBytesBus - 1) << (FromBin8($size))) &
+    ($maxBytesBus - 1);
+
+  # Calculate aligned, little-endian Bstrb which is the default in the FileReadCore
+  $bstrbCore = CalcBstrb($offsetAligned, $numLanesTrans); # Bstrb in FileRdCore
+
+  # Modify the offset according to the endianness of the transfer, and
+  # must again align the address offset with the size of the transfer
+  $offsetAligned = MakeOffsetBigEndian( $offsetAligned ) if ($endian eq 'big');
+  $offsetAligned &=  (($maxBytesBus - 1) << (FromBin8($size))) &
+                      ($maxBytesBus - 1);
+
+  # Calculate Bstrb based on the aligned address
+  $bstrbAligned = CalcBstrb($offsetAligned, $numLanesTrans); # aligned version of Bstrb
+
+  # Shift specified Bstrb into the correct byte lanes lanes
+  if ($bstrb ne '') {
+    $bstrb = ShiftBstrb($bstrb, $offsetAligned);
+  }
+
+  # The following section of code checks the rules described in the
+  # AHB ARMv6 File Reader Bus Master Technical Reference Manual
+
+  # Computes default byte lane strobes based on size and address
+  # of the transfer if byte lane strobes are not specified by the user
+
+
+  # Calculate Bstrb for the unaligned transfer
+  if ($endian eq 'big') {
+
+    # If big-endian, default Bstrb must be aligned
+    $bstrbDefault = $bstrbAligned;
+
+  } else {
+
+    # Only interested in lower-order address bits up to width of data bus
+    $offset = $address & ($maxBytesBus - 1);
+
+    # Modify the offset according to the endianness of the transfer, and
+    # must again align the address offset with the size of the transfer
+    $offset = MakeOffsetBigEndian( $offset ) if ($endian eq 'big');
+
+    # Calculate the number of byte lanes in the transfer for unaligned transfer
+    $numLanesUnalign = $numLanesTrans - ($offset & ($numLanesTrans - 1));
+
+    # Special case of Bstrb value generated at the end of an unaligned burst
+    if ($endOfUnaligned == 1) {
+
+      # Address offset of original transfer in unaligned burst
+      $seqOffset = hex($seqAddress) & ($maxBytesBus - 1);
+
+      # Calculate the number of byte lanes left over because of unaligned transfer
+      $numLanesUnalign = $seqOffset & ($numLanesUnalign - 1);
+    }
+
+    # If little,endian, Bstrb may be unaligned
+    $bstrbDefault = CalcBstrb($offset, $numLanesUnalign); # default Bstrb for the transfer
+  }
+
+  if ($bstrb ne '') {
+    # If Bstrb is specified, check that the specified Bstrb value is legal
+    CheckBstrbFrame($bstrb, $bstrbDefault)
+      if (not $idleTransfer);
+
+    # Checks if the specified Bstrb value implies an unaligned transfer
+    $unalignImplied = UnalignImplied($bstrb, $bstrbAligned);
+
+    # Bstrb may imply Unalign
+    if ($unalign eq '' ) {
+        $unalign = $unalignImplied;
+    } else {
+      # Verify any specified Unalign field
+      CheckUnalign($unalign, $unalignImplied)
+        if (not $idleTransfer);
+    }
+
+  }  else {
+    # If Bstrb is not specified, use default
+    $bstrb = $bstrbDefault;
+
+    # Checks if the default Bstrb value implies an unaligned transfer
+    $unalignImplied = UnalignImplied($bstrbDefault, $bstrbAligned);
+
+    # In this case, Unalign may not be implied
+    if ($unalign eq '' ) {
+        $unalign = '0';
+    } else {
+      # Verify any specified Unalign field
+      CheckUnalign($unalign, $unalignImplied)
+        if (not $idleTransfer);
+    }
+  }
+
+  # Not allowed to have a sparse/unaligned transfer in big-endian mode
+  if ($endian eq 'big' and not $idleTransfer and $unalign eq '1') {
+    printf "Line %4d: ERROR 103: Transfer cannot be unaligned or sparse".
+           " in big-endian mode\n", $lineNum;
+    $fileErrors++;
+  }
+
+  # If Bstrb is not equal to the default in the FileRdCore, it must be encoded in the file
+  $writeBstrb = ($bstrb == $bstrbCore) ? 0 : 1;
+
+  if ($writeBstrb eq '1') {
+    # Convert to 8-digit hex string for output to data file
+    $bstrb = ToHex32($bstrb)
+  }
+
+  return ($unalign, $bstrb, $writeBstrb);
+}
+
+
+# ------------------------------------------------------------------------------
+# Shift Bstrb into correct byte lanes
+#
+# Assumes 64 bit data representation
+# Input Bstrb is a string of 1 or 0
+# Output Bstrb is numeric
+# ------------------------------------------------------------------------------
+sub ShiftBstrb {
+
+  my $bstrb     = shift;
+  my $offset    = shift;
+
+  my $numLanes  = length($bstrb);
+
+  # mask and data are zero outside the specified transfer
+  my $fullBstrb = '00000000';
+
+  # align the address offset with the length of Bstrb
+  $offset &= (0x100 - $numLanes); # Note 0x100 will cope up to HSIZE =1024 bits
+
+  # Shift Bstrb value to the correct byte lanes
+  substr $fullBstrb, ($maxBytesBus-$offset-$numLanes), $numLanes, $bstrb;
+
+  # Convert to numeric
+  return (FromBin8($fullBstrb));
+}
+
+
+# ------------------------------------------------------------------------------
+# Calculate Bstrb
+#
+# Arguments: address offset, number of byte lanes in the transfer
+# Output Bstrb is numeric
+# ------------------------------------------------------------------------------
+sub CalcBstrb {
+
+  my $offset = shift;
+  my $numLanesTrans = shift;
+
+  my $bstrb;
+
+  # (1 << $numLanesTrans) - 1) is the correct number of strobes for the transfer,
+  # but shifted into the low order end of the data bus. The final shift left
+  # by $offset shifts this value into the correct address lanes.
+  $bstrb = ((1 << $numLanesTrans) - 1) << $offset;
+
+  return $bstrb;
+}
+
+# ------------------------------------------------------------------------------
+# Convert the address offset to big-endian
+#
+# Copes with address offsets up to 0xFF
+# Note! returned offset will need aligning with the data width
+# ------------------------------------------------------------------------------
+sub MakeOffsetBigEndian {
+
+  my $offset = shift;
+
+  # Endianness boundary is the number of bytes within each endianness group
+  #   for little endian, value is 1 (i.e. no effect)
+  #   for ARM (legacy) big-endian, value is always 4 (BE-32: 32-bits)
+  #   for true big-endian, value is equal to the databus width in bytes
+  my $endBdy = 4;
+
+  # Modify the offset according to the endianness of the transfer,
+  # taking into account endianness granularity $endBdy:
+  $offset = ( $offset & (0x100 - $endBdy) )                 # preserve high bits
+          | ( ($endBdy - 1) - ($offset & ($endBdy - 1)) );  # reverse low bits
+
+  return $offset;
+}
+
+# ------------------------------------------------------------------------------
+# Checks user-entered Bstrb is within allowed frame
+#
+# ------------------------------------------------------------------------------
+sub CheckBstrbFrame {
+
+  my $bstrb         = shift;
+  my $bstrbDefault  = shift;
+
+  # Check that the byte lane strobes are valid,
+  # i.e zero outside the size/address frame
+  if (($bstrb & (((1 << $maxBytesBus) - 1) ^ $bstrbDefault)) != 0) {
+    printf "Line %4d: ERROR 102: Byte lane strobes are asserted".
+           " outside the transfer address size frame\n", $lineNum;
+
+    # Un-comment for Debug:
+    #  my $bstrbDefBin = ToBin8($bstrbDefault);
+    #  my $bstrbActBin = ToBin8($bstrb);
+    #  print "  Bstrb default = $bstrbDefBin\n".
+    #        "  Bstrb actual  = $bstrbActBin\n";
+
+    $fileErrors++;
+  }
+
+}
+
+
+# ------------------------------------------------------------------------------
+# Calculate if Bstrb implies Unaligned transfer
+#
+# If the user has specified a byte lane strobe value, it implies
+# an unaligned or aligned transfer. The implied transfer value is obtained
+# by comparing the user defined value with the value that will be
+# calculated for an aligned transfer by the file reader.
+#
+# ------------------------------------------------------------------------------
+sub UnalignImplied {
+
+  my $bstrb         = shift;
+  my $bstrbAligned  = shift;
+
+  my $unalignImp    = '0';
+
+
+  # Generate the implied Unalign value
+  if ($bstrb eq '' or $bstrb == $bstrbAligned) {
+    $unalignImp = '0';
+
+  } else {
+    $unalignImp = '1';
+  }
+
+  return $unalignImp;
+}
+
+# ------------------------------------------------------------------------------
+# Check if the entered UNALIGN values is legal
+#
+# Compare the user defined value with the implied aligned value
+#
+# An error condition arises if the user's Unalign input is set to align (0)
+# and the calculated value is set to Unalign (1).
+#
+# ------------------------------------------------------------------------------
+sub CheckUnalign {
+
+  my $unalign       = shift;
+  my $unalignImp    = shift;
+
+
+  if (($unalign eq '0') & ($unalignImp eq '1')) {
+
+    printf "Line %4d: ERROR 101: Transfer is specified as aligned but".
+           " Bstrb field implies unaligned\n", $lineNum;
+    $fileErrors++;
+  }
+
+}
+
+
+# ------------------------------------------------------------------------------
+# Check that Exclusive access is aligned
+#
+# ------------------------------------------------------------------------------
+sub CheckProtUnalign {
+
+  my $prot    = shift;
+  my $unalign = shift;
+
+  # Only applies to v6 stimuli
+  if  ( ($arch eq 'v6') and
+        ($unalign eq '1') and
+        (substr($prot, 0, 1) eq '1')
+      ) {
+    printf "Line %4d: ERROR 107: Exclusive access cannot be".
+           " unaligned\n", $lineNum;
+    $fileErrors++;
+  }
+}
+
+
+# ------------------------------------------------------------------------------
+# Address Alignment Checks
+#
+# ------------------------------------------------------------------------------
+sub CheckAddrAlign {
+
+  my $size = shift;
+  my $addr = shift;
+  my $unalign = shift;
+
+  my $addrSizeErr;
+
+  # Check if there is an Address/Size mismatch
+  #   Tests if address == address & (0xffffffff << 'HSIZE');
+  if  ( $addr and (
+        ( ($size eq '011') && ($addr !~ /([0-9A-Fa-f]{7})[0|8]/i) ) or
+        ( ($size eq '010') && ($addr !~ /([0-9A-Fa-f]{7})[0|4|8|C]/i) ) or
+        ( ($size eq '001') && ($addr !~ /([0-9A-Fa-f]{7})[0|2|4|6|8|A|C|E|]/i) )
+      ) ) {
+
+    $addrSizeErr = 1;
+
+    if ( $arch eq 'v6' and $unalign eq '1' ) {
+      # set pending addr/size mismatch error flag
+      SetMismatch();
+
+    } else {
+      # report error
+      ResetMismatch();
+      $fileErrors++;
+      AddrSizeErrorRpt($size);
+    }
+
+  } else {
+    $addrSizeErr = 0;
+
+  }
+
+  return $addrSizeErr
+}
+
+
+# ------------------------------------------------------------------------------
+# Report address / size mismatch error
+#
+# ------------------------------------------------------------------------------
+sub AddrSizeErrorRpt {
+
+  my $size = shift;
+
+  # check address alignment
+  if ($size eq '011')  {
+    printf "Line %4d: ERROR 64: Address is not".
+           " dword aligned\n", $lineNum;
+    $fileErrors++;
+
+  } elsif ($size eq '010') {
+    printf "Line %4d: ERROR 64: Address is not".
+           " word aligned\n", $lineNum;
+    $fileErrors++;
+
+  } elsif ($size eq '001') {
+    printf "Line %4d: ERROR 64: Address is not".
+           " halfword aligned\n", $lineNum;
+    $fileErrors++;
+
+  } else {
+    printf "Line %4d: ERROR 64: Address is not aligned with size".
+           " of transfer\n", $lineNum;
+    $fileErrors++;
+  }
+}
+
+
+
+# ------------------------------------------------------------------------------
+# Check for early burst termination
+#
+# Assumes a new burst is starting
+# Arguments: Number of transfers remaining
+#
+# ------------------------------------------------------------------------------
+sub CheckBurstTerm {
+
+  my $count = shift;
+
+  # If there are remaining transfers and burst is not expected to be cancelled
+  if ( ($verbose == 1) and ($count > 0) and $sequence{'RESP'} ne '10') {
+
+    printf "Line %4d: WARNING 216: Burst terminated early by".
+           " insufficient Sequence commands\n", $lineNum;
+    $fileWarnings++;
+  }
+
+  # if pending addr/size mismatch error
+  if (GetMismatch() == 1 and $arch eq 'v6')
+  {
+    ResetMismatch();
+    if ($verbose == 1) {
+      printf "Line %4d: WARNING 236: Unaligned transfer crossing address".
+             " size boundary.\n", $sequence{'LINE'};
+      $fileWarnings++;
+    }
+  }
+
+}
+
+
+# ------------------------------------------------------------------------------
+# Set burst counters for the remaining number of transfers in a burst
+#
+# ------------------------------------------------------------------------------
+sub SetBurstCount  {
+
+  my $currBurst = shift;
+  my $mismatch  = shift;
+
+  my $transCount;
+  my $incrCount;
+
+  # Set the bust counters according to the burst type
+  if    ($currBurst eq '000') {$transCount = 0;  $incrCount = 0;}  # single
+  elsif ($currBurst eq '001') {$transCount = 0;  $incrCount = 1;}  # incr
+  elsif ($currBurst eq '010') {$transCount = 3;  $incrCount = 0;}  # wrap4
+  elsif ($currBurst eq '011') {$transCount = 3;  $incrCount = 0;}  # incr4
+  elsif ($currBurst eq '100') {$transCount = 7;  $incrCount = 0;}  # wrap8
+  elsif ($currBurst eq '101') {$transCount = 7;  $incrCount = 0;}  # incr8
+  elsif ($currBurst eq '110') {$transCount = 15; $incrCount = 0;}  # wrap16
+  elsif ($currBurst eq '111') {$transCount = 15; $incrCount = 0;}  # incr16
+  else                        {$transCount = 0;  $incrCount = 1;}  # incr
+
+  # If a defined-length unaligned burst (i.e. not INCR) is taking place,
+  # there will be an extra transfer
+  if (GetMismatch() == 1 and $currBurst ne '001') {
+    $transCount++;
+  }
+
+  SetTransCount($transCount);
+  SetIncrCount($incrCount);
+
+  return ($transCount, $incrCount);
+}
+
+
+# ------------------------------------------------------------------------------
+# Reset burst counters and check for early burst termination
+#
+# ------------------------------------------------------------------------------
+sub ResetBurstCount
+{
+  # Check that previous burst was not terminated early
+  CheckBurstTerm(GetTransCount());
+
+  # Reset the bust counters to zero
+  SetTransCount(0);
+  SetIncrCount(0);
+}
+
+# Set the transCount counter
+sub SetTransCount
+{
+  $transCount = shift;
+}
+
+# Decrement the transCount counter
+sub DecTransCount
+{
+  # Only valid to decrement the counter if a burst is in progress
+  if ($transCount > 0) {
+    $transCount--;
+  }
+}
+
+
+# Get the value of the transCount counter
+sub GetTransCount
+{
+  return $transCount;
+}
+
+# Increment the incrCount counter
+sub IncIncrCount
+{
+  # Only valid to increment the counter if a burst is in progress
+  if ($incrCount > 0) {
+    $incrCount++;
+  }
+}
+
+# Set the Incr counter
+sub SetIncrCount
+{
+  $incrCount = shift;
+}
+
+
+# Get the value of the incrCount counter
+sub GetIncrCount
+{
+  return $incrCount;
+}
+
+
+# ------------------------------------------------------------------------------
+# Subroutines to set and reset global flag mismatch
+#
+# ------------------------------------------------------------------------------
+sub SetMismatch
+{
+  $mismatch = 1;
+}
+
+sub ResetMismatch
+{
+  $mismatch = 0;
+}
+
+sub GetMismatch
+{
+  return $mismatch;
+}
+
+
+# ------------------------------------------------------------------------------
+# Calculate memory size required for FileReader
+#   Adds up the total number of 32-bit words required to hold the stimulus
+#    output
+#
+# ------------------------------------------------------------------------------
+sub CalcMemory {
+
+my $cmd = shift;
+
+  if ($cmd eq 'W') {
+    $memorySize += 4;                             # Write
+
+  } elsif ($cmd eq 'R') {
+    $memorySize += 6;                             # Read
+
+  } elsif ($cmd eq 'S') {
+    $memorySize += 5;                             # Seq
+
+  } elsif ($cmd eq 'B') {
+    $memorySize += 1;                             # Busy
+
+  } elsif ($cmd eq 'I') {
+    $memorySize += 2;                             # Idle
+
+  } elsif ($cmd eq 'P') {
+    $memorySize += 7;                             # Poll
+
+  } elsif ($cmd eq 'L') {
+    $memorySize += 2;                             # Loop
+
+  } elsif ($cmd eq 'C') {
+    $memorySize += 2 + $command{'COUNT'};         # Comment
+
+  } elsif ($cmd eq 'Q') {
+    $memorySize += 1;                             # Quit
+
+  } else {
+    # Error - invalid command found - should not happen
+    warn "WARNING 255: Invalid Command $currCmd for calculating Memory Size".
+         " at stimulus line $lineNum\n";
+  }
+
+  if ($command{'WRITEBS'} eq '1' )
+  {
+    $memorySize ++;
+  }
+}
+
+
+# ------------------------------------------------------------------------------
+# Converts 3-bit binary string representation of Hsize value to number of bytes
+#
+# ------------------------------------------------------------------------------
+sub HsizeToBytes {
+  return 1 << unpack("C", pack("B8","00000". shift));
+}
+
+
+# ------------------------------------------------------------------------------
+# Converts number of bytes to binary string representation of Hsize
+#
+# ------------------------------------------------------------------------------
+sub BytesToHsize {
+
+  my $transferWidth = shift;
+  my $size = '';
+
+  if    ($transferWidth == 1) {$size = '000'}
+  elsif ($transferWidth == 2) {$size = '001'}
+  elsif ($transferWidth == 4) {$size = '010'}
+  elsif ($transferWidth == 8) {$size = '011'}
+  else {
+    # Transfer wider than 64 bits not supported - should not happen
+    warn "WARNING 254: Unsupported transfer width of $transferWidth bytes".
+         " at stimulus line $lineNum\n";
+  }
+
+  return $size;
+}
+
+
+# ------------------------------------------------------------------------------
+# Converts an n-bit binary string to hex with n/4 digits
+# Note: Only works for whole bytes.
+#
+# ------------------------------------------------------------------------------
+sub BinToHex {
+  unpack('H*', pack('B*', shift));
+}
+
+# ------------------------------------------------------------------------------
+# Converts an numeric value to 8 hex digits
+#
+# ------------------------------------------------------------------------------
+sub ToHex32 {
+  sprintf("%08X", shift);
+}
+
+# ------------------------------------------------------------------------------
+# Converts up to 8 bits binary to a number
+# Note: Wraps at 256
+#
+# ------------------------------------------------------------------------------
+sub FromBin8 {
+    unpack('C', pack('B8',substr('0' x 8 . shift, -8)));
+}
+
+
+# ------------------------------------------------------------------------------
+# Converts a number to an 8-bit binary string
+# Note: Wraps at 256
+#
+# ------------------------------------------------------------------------------
+sub ToBin8 {
+  return unpack( "B8",  pack ('C', shift));
+}
+
+
+# ------------------------------------------------------------------------------
+# Output format definitions
+#
+# ------------------------------------------------------------------------------
+
+
+format WRITECMD =
+@<<<<<<<
+$command{'FUNCTION'}
+@<<<<<<<
+$command{'ADDR'}
+@<<<<<<<
+$command{'DATAH'}
+@<<<<<<<
+$command{'DATAL'}
+@<<<<<<<
+$command{'BSTRBHEX'} if ($command{'WRITEBS'} eq '1')
+.
+
+
+format READCMD =
+@<<<<<<<
+$command{'FUNCTION'}
+@<<<<<<<
+$command{'ADDR'}
+@<<<<<<<
+$command{'DATAH'}
+@<<<<<<<
+$command{'DATAL'}
+@<<<<<<<
+$command{'MASKH'}
+@<<<<<<<
+$command{'MASKL'}
+@<<<<<<<
+$command{'BSTRBHEX'} if ($command{'WRITEBS'} eq '1')
+.
+
+
+format SEQCMD =
+@<<<<<<<
+$command{'FUNCTION'}
+@<<<<<<<
+$command{'DATAH'}
+@<<<<<<<
+$command{'DATAL'}
+@<<<<<<<
+$command{'MASKH'}
+@<<<<<<<
+$command{'MASKL'}
+@<<<<<<<
+$command{'BSTRBHEX'} if ($command{'WRITEBS'} eq '1')
+.
+
+
+format BUSYCMD =
+@<<<<<<<
+$command{'FUNCTION'}
+@<<<<<<<
+$command{'BSTRBHEX'} if ($command{'WRITEBS'} eq '1')
+.
+
+
+format IDLECMD =
+@<<<<<<<
+$command{'FUNCTION'}
+@<<<<<<<
+$command{'ADDR'}
+@<<<<<<<
+$command{'BSTRBHEX'} if ($command{'WRITEBS'} eq '1')
+.
+
+
+format POLLCMD =
+@<<<<<<<
+$command{'FUNCTION'}
+@<<<<<<<
+$command{'TOUT'}
+@<<<<<<<
+$command{'ADDR'}
+@<<<<<<<
+$command{'DATAH'}
+@<<<<<<<
+$command{'DATAL'}
+@<<<<<<<
+$command{'MASKH'}
+@<<<<<<<
+$command{'MASKL'}
+@<<<<<<<
+$command{'BSTRBHEX'} if ($command{'WRITEBS'} eq '1')
+.
+
+
+format LOOPCMD =
+@<<<<<<<
+$command{'FUNCTION'}
+@<<<<<<<
+$command{'NUM'}
+.
+
+
+format COMMCMD =
+@<<<<<<<
+$command{'FUNCTION'}
+@<<<<<<<
+$command{'NUM'}
+@<<<<<<<
+$command{'WORD1'}
+@<<<<<<<
+$command{'WORD2'}   if ($command{'COUNT'} > 1)
+@<<<<<<<
+$command{'WORD3'}   if ($command{'COUNT'} > 2)
+@<<<<<<<
+$command{'WORD4'}   if ($command{'COUNT'} > 3)
+@<<<<<<<
+$command{'WORD5'}   if ($command{'COUNT'} > 4)
+@<<<<<<<
+$command{'WORD6'}   if ($command{'COUNT'} > 5)
+@<<<<<<<
+$command{'WORD7'}   if ($command{'COUNT'} > 6)
+@<<<<<<<
+$command{'WORD8'}   if ($command{'COUNT'} > 7)
+@<<<<<<<
+$command{'WORD9'}   if ($command{'COUNT'} > 8)
+@<<<<<<<
+$command{'WORD10'}  if ($command{'COUNT'} > 9)
+@<<<<<<<
+$command{'WORD11'}  if ($command{'COUNT'} > 10)
+@<<<<<<<
+$command{'WORD12'}  if ($command{'COUNT'} > 11)
+@<<<<<<<
+$command{'WORD13'}  if ($command{'COUNT'} > 12)
+@<<<<<<<
+$command{'WORD14'}  if ($command{'COUNT'} > 13)
+@<<<<<<<
+$command{'WORD15'}  if ($command{'COUNT'} > 14)
+@<<<<<<<
+$command{'WORD16'}  if ($command{'COUNT'} > 15)
+@<<<<<<<
+$command{'WORD17'}  if ($command{'COUNT'} > 16)
+@<<<<<<<
+$command{'WORD18'}  if ($command{'COUNT'} > 17)
+@<<<<<<<
+$command{'WORD19'}  if ($command{'COUNT'} > 18)
+@<<<<<<<
+$command{'WORD20'}  if ($command{'COUNT'} > 19)
+.
+
+
+format QUITCMD =
+@<<<<<<<
+$command{'FUNCTION'}
+.
+
+__END__