#!/bin/sh
perl - $@ <<\ENDOFPERL




sub usage
	{
	print <<EOP;

        hexout2flash [options] file

        -b <base address> : Location in flash to write file, default 0x600000
        -s <sof size>     : Size of equivalent sof file (bytes), default 0xa2a00
	--help            : Print help

"hexout2flash"

After compiling a design in Quartus, if you have generated
a .hexout file, you can use this utility to assist with
writing it into flash memory. This utility will prepend
the necessary Germs monitor commands to erase a section of
flash memory, and relocate the .hexout file to that erased
section.

If your file is called "my_design.hexout", you would
execute the following commands:

    [SOPC Builder]\$ hexout2flash my_design.hexout

    #hexout2flash: Converted my_design.hexout to my_design.flash.

    [SOPC Builder]\$ nios-run -x my_design.flash

This will write the design into flash at location 0x600000, and will
become the default booting user design for the development board.

Each Nios development board uses a particular area of Flash
memory to hold user configurations.

 Board          base address    size
-----------------------------------------------
Apex 20k200     -b 0x180000 -s 0x03f000
Cyclone 1c20    -b 0x600000 -s 0x0a2a00
Stratix 1s10    -b 0x600000 -s 0x0a2a00
Stratix 1s40    -b 0x400000 -s 0x1752da


EOP
	exit(0);
	}

sub numberFrom
	{
	my $x = shift;

	if($x =~ /^0x(.*)$/)
		{
		$x = hex($1);
		}
	return $x;
	}


# ----------------------------------
# FlashAFile
#
# Convert one file to its .flash-like aspect
#

sub FlashAFile
	{
	my $sourceFile = shift;
	my $baseAddr = shift;
        my $sofsize = shift;
	my $resultFile;

        # erase whatever sectors will be overwritten
        my @eraselines_list = ();
        for ( my $offset = 0x0; 
              ($offset < (($sofsize & ~0xFFFF) + 0xFFFF)); 
              $offset += 0x10000) {
          push @eraselines_list, sprintf("e%08x", $baseAddr + $offset);
        }

        my $eraseLines = join "\n", @eraselines_list;

	my $relocateLines = sprintf("r%08x",$baseAddr);

	$resultFile = $sourceFile. ".flash";
	if($resultFile =~ /^(.*).srec.flash$/)
		{
		$resultFile = $1. ".flash";
		}

	open (SOURCEFILE,$sourceFile) or die "Couldn't read from $sourceFile";
	open (RESULTFILE,">$resultFile") or die "Couldn't write to $resultFile";

    my $show_options = sprintf("-b 0x%x -s 0x%x",$baseAddr,$sofsize);

	print RESULTFILE <<EOP;
#
# This file generated by hexout2flash of
# the Nios SDK. This file was a .hexout
# file generated by Quartus, and is now
# prefixed by some commands to erase
# addresses in the user-design areas of flash, 
# and then relocate the design there.
#
# Original file: $sourceFile $show_options
#
$eraseLines
#
# Relocate the next input
#
$relocateLines
#
# Hexout file follows:
#
EOP

	while($line = <SOURCEFILE>)
		{
		# don't print out the 'go' record
		if(! ($line =~ /^S[789]/))
			{
			print RESULTFILE $line;
			}
		}
	close SOURCEFILE;

	# end relocation in monitor
	
	print RESULTFILE "r0\n";
	print RESULTFILE "# End of file.\n";
	close RESULTFILE;

	print "#hexout2flash: Converted $sourceFile to $resultFile.\n";
	return;
	}

# -------------------------------------
# main


sub main
	{
	my $arg;
	my @fileList;
	my $baseAddr = 0x600000;
        my $sofsize = 0xa2a00;

        if (@_ == ()) {
                usage();
        }
	while($arg = shift)
		{
		if($arg eq "-b")
			{
			$baseAddr = numberFrom(shift);
			}
		elsif($arg =~ /-*size/ || $arg eq "-s")
			{
			$sofsize = numberFrom(shift);
			}
		elsif($arg =~ /-*help/ || $arg eq "-?" || $arg eq "-h")
			{
			usage();
			}
		else
			{
			push(@fileList,$arg);
			}
		}
	my $sourceFile;


	print "\n";
	while($sourceFile = shift(@fileList))
		{
		FlashAFile($sourceFile,$baseAddr,$sofsize);
		}
	print "\n";
	}

main(@ARGV);
exit(0);

#end of file
