#!/usr/bin/perl

use strict;
use integer;

my($infile,$outfile,$depth,$width,$stride) = @ARGV;

$stride = 1 unless (defined($stride));

my $bytesperword = ($width+7) >> 3;

open(my $in,  '<:raw', $infile) or die;
my $data;
my $dlen = read($in,$data,$depth*$bytesperword*$stride);
close($in);

my $sdig = 1;
while ((1 << ($sdig*4)) < $stride) {
    $sdig++;
}
my $adig = 1;
while ((1 << ($adig*4)) < $depth) {
    $adig++;
}

for (my $s = 0; $s < $stride; $s++) {
    my $ofname = $outfile;
    if ($stride > 1) {
	$outfile =~ /^(.*?)(\.\w+)?$/;
	$ofname = sprintf("%s.%d%s", $1, $s, $2);
    }
    
    open(my $out, '>', $ofname) or die;

    printf $out "-- generated from %s\n", $infile;
    if ($stride > 1) {
	printf $out "-- array %d/%d (hex %0${sdig}X of [%0${sdig}X..%0${sdig}X])\n",
	    $s+1, $stride, $s, 0, $stride-1;
    }
    
    printf $out "DEPTH = %d;\n", $depth;
    printf $out "WIDTH = %d;\n", $width;
    printf $out "ADDRESS_RADIX = HEX;\n";
    printf $out "DATA_RADIX = HEX;\n";
    printf $out "CONTENT BEGIN\n";

    my $addr;
    for ($addr = 0; $addr < $depth; $addr++) {
	my $offs = ($addr*$stride+$s)*$bytesperword;
	last if ($offs >= $dlen);
	printf $out "%0${adig}X : ", $addr;
	# Emitting data byte by byte avoids need for bigint
	for (my $b = $bytesperword-1; $b >= 0; $b--) {
	    if ($offs+$b < $dlen) {
		printf $out "%02X", unpack("C", substr($data,$offs+$b,1));
	    }
	}
	printf $out ";\n";
    }

    if ($addr < $depth) {
	printf $out "[%0${adig}X..%0${adig}X] : 00;\n", $addr, $depth-1;
    }

    printf $out "END;\n";
    close($out);
}

if ($stride > 1) {
    # Create an empty file for the benefit of make
    open(my $out, '>', $outfile) or die;
    close($out);
}

exit 0;
    
