hdf2arch.pl: initial commit (processor, memory)
authorSebastian <basti@sraa.de>
Tue, 3 Sep 2013 19:46:47 +0000 (21:46 +0200)
committerSebastian <basti@sraa.de>
Tue, 3 Sep 2013 19:46:47 +0000 (21:46 +0200)
The utility hdf2arch.pl read the Hardware Description File from the
Epiphany SDK and generates a DOL architecture specification in XML format.

example:
$ ./hdf2arch.pl zed_E16G3_512mb.hdf epiphany.xml

This specifies the <processor> and <memory> elements for every eCore in the
Epiphany (called "core_row_col" and "mem_row_col") as well as for the
host cpu and the shared DRAM (called "arm_0" and "shm_0") and includes
some basic sanity checking of the HDF.

The generated file does not specify any <hw_channel>, <writepath> or
<readpath> tags and does not need any flattening.

Since the HDF file does not contain any information about the amount
of local SRAM or even the number of cores in the Epiphany, new chips
will need to be added to this utility. The ARM (with 2 cores) is hard coded,
though.

hdf2arch/hdf2arch.pl [new file with mode: 0755]

diff --git a/hdf2arch/hdf2arch.pl b/hdf2arch/hdf2arch.pl
new file mode 100755 (executable)
index 0000000..d1bc54d
--- /dev/null
@@ -0,0 +1,189 @@
+#!/usr/bin/perl -w
+use strict;
+use v5.010;
+
+use XML::Simple qw(:strict);
+use Data::Dumper;
+
+my $infile  = shift;
+my $outfile = shift;
+my $data;
+
+# supported chips
+my $chips = {
+       'E16G301' => {
+               'cores' => [4, 4],
+               'sram'  => '0x8000',
+       },
+       'E64G401' => {
+               'cores' => [8, 8],
+               'sram'  => '0x8000',
+       },
+};
+
+# parse arguments
+if(!$infile || !$outfile) {
+       say "Usage: hdf2arch <infile> <outfile>";
+       say "\tinfile:  Epiphany HDF file";
+       say "\toutfile: DOL XML file";
+       say "\tSpecify '-' to use standard input/output";
+       exit 1;
+}
+
+# parse HDF file
+my $num_chips;         # number of chips in system
+my @chiplist;          # information about current chip
+my $chipnum = -1;      # current chip
+my $num_emems;         # number of emems in system
+my @ememlist;          # information about current emem
+my $ememnum  = -1;     # current emem
+open (FH, "<$infile") or die("Can't open $infile.");
+while(<FH>) {
+       next if /\/\/.*/;       # skip comment lines
+
+       # globals - ignore them for now
+       #$data->{'version'} = $1 if(/^PLATFORM_VERSION\s+(\S+)\s*$/);
+       #$data->{'regbase'} = $1 if(/^ESYS_REGS_BASE\s+(\S+)\s*$/);
+
+
+       # number of chips
+       if(/^NUM_CHIPS\s+(\S+)\s*$/) {
+               if(!$num_chips) {
+                       $num_chips = $1;
+               } else {
+                       say STDERR "Warning: multiple 'NUM_CHIPS' entries!";
+               }
+       }
+
+       # per-chip information
+       if(/^CHIP\s+(\S+)\s*$/) {
+               my $id = $1;
+               if($chips->{$id}) {
+                       $chipnum++;
+                       $chiplist[$chipnum]->{'id'} = $id;
+                       $chiplist[$chipnum]->{'rows'} =
+                               $chips->{$id}->{'cores'}->[0];
+                       $chiplist[$chipnum]->{'cols'} =
+                               $chips->{$id}->{'cores'}->[1];
+                       $chiplist[$chipnum]->{'sram'} = $chips->{$id}->{'sram'};
+               } else {
+                       say STDERR "Warning: unknown CHIP '$id' - ignoring!";
+                       next;
+               }
+       }
+       $chiplist[$chipnum]->{'row'} = $1 if(/^CHIP_ROW\s+(\S+)\s*$/);
+       $chiplist[$chipnum]->{'col'} = $1 if(/^CHIP_COL\s+(\S+)\s*$/);
+
+       # number of emems
+       if(/^NUM_EXT_MEMS\s+(\S+)\s*$/) {
+               if(!$num_emems) {
+                       $num_emems = $1;
+               } else {
+                       say STDERR "Warning: multiple 'NUM_EXT_EMEM' entries!";
+               }
+       }
+
+
+       # per-emem information
+       if(/^EMEM\s+(\S+)\s*$/) {
+               my $id = $1;
+               if($id eq 'ext-DRAM') {
+                       $ememnum++;
+                       $ememlist[$ememnum]->{'id'} = $id;
+               } else {
+                       say STDERR "Warning: unknown EMEM '$id' - ignoring!";
+                       next;
+               }
+       }
+       $ememlist[$ememnum]->{'base'} = $1 if(/^EMEM_BASE_ADDRESS\s+(\S+)\s*$/);
+       $ememlist[$ememnum]->{'epi'}  = $1 if(/^EMEM_EPI_BASE\s+(\S+)\s*$/);
+       $ememlist[$ememnum]->{'size'} = $1 if(/^EMEM_SIZE\s+(\S+)\s*$/);
+       $ememlist[$ememnum]->{'type'} = $1 if(/^EMEM_TYPE\s+(\S+)\s*$/);
+}
+
+# some simple consistency checks
+if($num_chips != scalar @chiplist) {
+       say STDERR "Warning: NUM_CHIPS does not match the number of CHIPs!";
+}
+if($num_emems != scalar @ememlist) {
+       say STDERR "Warning: NUM_EXT_MEMS does not match the number of EMEMs!";
+}
+
+# generate output data
+$data->{'processor'} = [];
+$data->{'memory'}    = [];
+
+# host processor, epiphany cores and their memories
+push $data->{'processor'}, {
+       'name' => 'arm_0',
+       'type' => 'RISC',
+       'configuration' => [
+               { 'name'  => 'cores',
+                 'value' => '2' },
+       ],
+};
+
+for my $chip(@chiplist) {
+       for my $row (0..$chip->{'rows'}-1) {
+               for my $col (0..$chip->{'cols'}-1) {
+                       my $r = $chip->{'row'} + $row;
+                       my $c = $chip->{'col'} + $col;
+                       push $data->{'processor'}, {
+                               'name' => "core_${r}_${c}",
+                               'type' => 'RISC',
+                               'configuration' => [
+                                       { 'name'  => 'type',
+                                         'value' => $chip->{'id'}, },
+                               ],
+                       };
+
+                       push $data->{'memory'}, {
+                               'name' => "mem_${r}_${c}",
+                               'type' => 'RAM',
+                               'configuration' => [
+                                       { 'name'  => 'size',
+                                         'value' => $chip->{'sram'}, },
+                               ],
+                       };
+               }
+       }
+}
+
+# external memories
+for my $idx(0..(scalar @ememlist-1)) {
+       push $data->{'memory'}, {
+               'name' => "shm_$idx",
+               'type' => "RAM",
+               'configuration' => [
+                       { 'name'  => 'size',
+                         'value' => $ememlist[$idx]->{'size'} },
+                       { 'name'  => 'type',
+                         'value' => $ememlist[$idx]->{'type'} },
+                       { 'name'  => 'base',
+                         'value' => $ememlist[$idx]->{'base'} },
+                       { 'name'  => 'epibase',
+                         'value' => $ememlist[$idx]->{'epi'} },
+               ],
+       };
+}
+
+#say Dumper $data;
+
+# write data in xml format
+$data->{'name'} = 'Adapteva Parallella Architecture';
+$data->{'xmlns'} = 'http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE';
+$data->{'xmlns:xsi'} = 'http://www.w3.org/2001/XMLSchema-instance';
+$data->{'xsi:schemaLocation'} = 'http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE http://www.tik.ee.ethz.ch/~shapes/schema/architecture.xsd';
+my $outxml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".
+               XMLout({'architecture' => $data},
+                       KeyAttr => [],
+                       KeepRoot => 1);
+
+if($outfile eq '-') {
+       say $outxml;
+       exit 0;
+} else {
+       open (FH, ">$outfile");
+       say FH $outxml;
+       close (FH);
+}