#! /usr/bin/perl

# MIPS I system
# Copyright 2011-2012 Stefan Schuermans <stefan@blinkenarea.org>
# Copyleft GNU public license V2 or later
#          http://www.gnu.org/copyleft/gpl.html

use strict;
use warnings;

require("crc32.pl");

# parse C data
my @bytes = ();
while (my $line = <>) {
  chomp $line;
  # tcpdump -XX
  if ($line =~ /^ *[0-9A-FXa-fx]+: +([0-9A-Fa-f ]+)/) {
    my $data = $1;
    $data =~ s/  .*$//; # remove ASCII in case the begin was [0-9A-Fa-f]+
    $data =~ s/[^0-9A-Fa-f]//g;
    $data =~ s/(..)/$1,/g;
    for my $part (split(/,/, $data)) {
      if ($part =~ /^([0-9A-Fa-f]{2})/) {
        my $val = $1;
        push (@bytes, hex($val));
      }
    }
  }
  # C data
  elsif ($line =~ /^ *([0-9A-FXa-fx, ]+)/) {
    my $data = $1;
    for my $part (split(/,/, $data)) {
      if ($part =~ /^ *0[xX]([0-9A-Fa-f]{1,2})/) {
        my $val = $1;
        push (@bytes, hex($val));
      }
    }
  }
}

# add CRC
if (@bytes >= 4) {
  my @bytes_no_crc = @bytes;
  my @crc_bytes = ();
  unshift (@crc_bytes, pop(@bytes_no_crc));
  unshift (@crc_bytes, pop(@bytes_no_crc));
  unshift (@crc_bytes, pop(@bytes_no_crc));
  unshift (@crc_bytes, pop(@bytes_no_crc));
  my $crc_calc = crc32([@bytes_no_crc]);
  my $mismatch = 0;
  for (my $i = 0; $i < 4; $i++) {
    if (shift(@crc_bytes) != shift(@{$crc_calc})) {
      $mismatch = 1;
    }
  }
  if ($mismatch) {
    my $crc = crc32([@bytes]);
    push(@bytes, @{$crc});
  } else {
    print STDERR "warning: CRC32 already present -> not added\n";
  }
} else {
  my $crc = crc32([@bytes]);
  push(@bytes, @{$crc});
}

# add preamble
my $pos = 0;
while ($pos < @bytes && $bytes[$pos] == 0x55) {
  $pos++;
}
if ($pos > 4 && $pos < @bytes && $bytes[$pos] == 0xD5) {
  print STDERR "warning: preamble already present -> not added\n";
} else {
  unshift(@bytes, 0xD5);
  for (my $i = 0; $i < 7; $i++) {
    unshift(@bytes, 0x55);
  }
}

# bytes to nibbles
my @nibbles = ();
foreach my $byte (@bytes) {
  push(@nibbles, $byte & 0xF);
  push(@nibbles, $byte >> 4 & 0xF);
}

# output VHDL data
printf("    TYPE t_eth_data IS ARRAY(0 TO %u - 1) OF " . 
       "std_logic_vector(3 DOWNTO 0);\n", @nibbles + 0);
print("    CONSTANT eth_data: t_eth_data := (\n");
for (my $pos = 0; $pos < @nibbles; ) {
  print("       ");
  for (my $i = 0; $i < 8 and $pos < @nibbles; ++$i, ++$pos) {
    if ($pos + 1 < @nibbles) {
      printf(" X\"%X\",", $nibbles[$pos]);
    } else {
      printf(" X\"%X\"", $nibbles[$pos]);
    }
  }
  print("\n");
}
print("        );\n");