214 lines
5.4 KiB
Plaintext
214 lines
5.4 KiB
Plaintext
|
#!/usr/bin/perl
|
||
|
# SPDX-License-Identifier: Apache-2.0
|
||
|
# Copyright 2020 Western Digital Corporation or its affiliates.
|
||
|
#
|
||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
# you may not use this file except in compliance with the License.
|
||
|
# You may obtain a copy of the License at
|
||
|
#
|
||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||
|
#
|
||
|
# Unless required by applicable law or agreed to in writing, software
|
||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
# See the License for the specific language governing permissions and
|
||
|
# limitations under the License.
|
||
|
#
|
||
|
|
||
|
use Getopt::Long;
|
||
|
|
||
|
$helpusage = "placeholder";
|
||
|
|
||
|
GetOptions ('legal' => \$legal,
|
||
|
'in=s' => \$in,
|
||
|
'out=s' => \$out,
|
||
|
'view=s' => \$view ) || die("$helpusage");
|
||
|
|
||
|
|
||
|
if (!defined($in)) { die("must define -in=input"); }
|
||
|
if (!defined($out)) { $out="${in}.out"; }
|
||
|
|
||
|
if ($in eq "decode") { $view="rv32i"; }
|
||
|
elsif ($in eq "cdecode") { $view="rv32c"; }
|
||
|
elsif ($in eq "csrdecode") { $view="csr"; }
|
||
|
|
||
|
if (defined($in)) { printf("in=$in\n"); }
|
||
|
if (defined($out)) { printf("out=$out\n"); }
|
||
|
if (defined($view)) { printf("view=$view\n"); }
|
||
|
|
||
|
@in=`cat $in`;
|
||
|
|
||
|
$gather=0;
|
||
|
|
||
|
$TIMEOUT=50;
|
||
|
|
||
|
foreach $line (@in) {
|
||
|
|
||
|
#printf("$pstate: $line");
|
||
|
|
||
|
if ($line=~/^\s*\#/) { #printf("skip $line");
|
||
|
next; }
|
||
|
|
||
|
if ($gather==1) {
|
||
|
if ($line=~/(\S+)/) {
|
||
|
if ($line=~/}/) { $gather=0; $position=0; next; }
|
||
|
$label=$1;
|
||
|
$label=~s/,//g;
|
||
|
if ($pstate==2) {
|
||
|
if (defined($INPUT{$CVIEW}{$label})) { die("input $label already defined"); }
|
||
|
$INPUT{$CVIEW}{$label}=$position++;
|
||
|
$INPUTLEN{$CVIEW}++;
|
||
|
$INPUTSTR{$CVIEW}.=" $label";
|
||
|
}
|
||
|
elsif ($pstate==3) {
|
||
|
if (defined($OUTPUT{$CVIEW}{$label})) { die("output $label already defined"); }
|
||
|
$OUTPUT{$CVIEW}{$label}=$position++;
|
||
|
$OUTPUTLEN{$CVIEW}++;
|
||
|
$OUTPUTSTR{$CVIEW}.=" $label";
|
||
|
}
|
||
|
else { die("unknown pstate $pstate in gather"); }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($line=~/^.definition/) {
|
||
|
$pstate=1; next;
|
||
|
}
|
||
|
if ($pstate==1) { # definition
|
||
|
if ($line!~/^.output/) {
|
||
|
if ($line=~/(\S+)\s*=\s*(\S+)/) {
|
||
|
$key=$1; $value=$2;
|
||
|
$value=~s/\./-/g;
|
||
|
$value=~s/\[//g;
|
||
|
$value=~s/\]//g;
|
||
|
$DEFINITION{$key}=$value;
|
||
|
}
|
||
|
}
|
||
|
else { $pstate=2; next; }
|
||
|
}
|
||
|
|
||
|
if ($line=~/^.input/) {
|
||
|
$pstate=2; next;
|
||
|
}
|
||
|
|
||
|
if ($pstate==2) { # input
|
||
|
if ($line=~/(\S+)\s*=\s*\{/) {
|
||
|
$CVIEW=$1; $gather=1; next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($line=~/^.output/) {
|
||
|
$pstate=3; next;
|
||
|
}
|
||
|
|
||
|
if ($pstate==3) { # output
|
||
|
if ($line=~/(\S+)\s*=\s*\{/) {
|
||
|
$CVIEW=$1; $gather=1; next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($line=~/^.decode/) {
|
||
|
$pstate=4; next;
|
||
|
}
|
||
|
|
||
|
if ($pstate==4) { # decode
|
||
|
if ($line=~/([^\[]+)\[([^\]]+)\]\s*=\s*\{([^\}]+)\}/) {
|
||
|
$dview=$1; $inst=$2; $body=$3;
|
||
|
$dview=~s/\s+//g;
|
||
|
$inst=~s/\s+//g;
|
||
|
#printf("$dview $inst $body\n");
|
||
|
if ($inst=~/([^\{]+)\{([^-]+)-([^\}]+)\}/) {
|
||
|
$base=$1; $lo=$2; $hi=$3;
|
||
|
$hi++;
|
||
|
for ($i=0; $i<$TIMEOUT && $lo ne $hi; $i++) {
|
||
|
#printf("decode $dview $base$lo\n");
|
||
|
|
||
|
$expand=$base.$lo;
|
||
|
if (!defined($DEFINITION{$expand})) { die("could not find instruction definition for inst $expand"); }
|
||
|
|
||
|
$DECODE{$dview}{$expand}=$body;
|
||
|
$lo++;
|
||
|
}
|
||
|
if ($i == $TIMEOUT) { die("timeout in decode expansion"); }
|
||
|
|
||
|
}
|
||
|
else {
|
||
|
if (!defined($DEFINITION{$inst})) { die("could not find instruction definition for inst $inst"); }
|
||
|
$DECODE{$dview}{$inst}=$body;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
#printf("view $view len %d\n",$OUTPUTLEN{$view});
|
||
|
|
||
|
#printf("$OUTPUTSTR{$view}\n");
|
||
|
|
||
|
|
||
|
# need to switch this somehow based on 16/32
|
||
|
printf(".i %d\n",$INPUTLEN{$view});
|
||
|
|
||
|
if (defined($legal)) {
|
||
|
printf(".o 1\n");
|
||
|
}
|
||
|
else {
|
||
|
printf(".o %d\n",$OUTPUTLEN{$view});
|
||
|
}
|
||
|
|
||
|
printf(".ilb %s\n",$INPUTSTR{$view});
|
||
|
|
||
|
if (defined($legal)) {
|
||
|
printf(".ob legal\n");
|
||
|
}
|
||
|
else {
|
||
|
printf(".ob %s\n",$OUTPUTSTR{$view});
|
||
|
}
|
||
|
|
||
|
if (defined($legal)) {
|
||
|
printf(".type fd\n");
|
||
|
}
|
||
|
else {
|
||
|
printf(".type fr\n");
|
||
|
}
|
||
|
|
||
|
$DEFAULT_TEMPLATE='0'x$OUTPUTLEN{$view};
|
||
|
|
||
|
foreach $inst (sort keys %{ $DECODE{$view} }) {
|
||
|
|
||
|
$body=$DECODE{$view}{$inst};
|
||
|
@sigs=split(' ',$body);
|
||
|
|
||
|
$template=$DEFAULT_TEMPLATE;
|
||
|
foreach $sig (@sigs) {
|
||
|
if (!defined($OUTPUT{$view}{$sig})) { die("could not find output definition for sig $sig in view $view"); }
|
||
|
$position=$OUTPUT{$view}{$sig};
|
||
|
substr($template,$position,1,1);
|
||
|
}
|
||
|
|
||
|
# if (!defined($DEFINITION{$inst})) { die("could not find instruction defintion for inst $inst"); }
|
||
|
|
||
|
printf("# $inst\n");
|
||
|
if (defined($legal)) {
|
||
|
printf("$DEFINITION{$inst} 1\n");
|
||
|
}
|
||
|
else {
|
||
|
printf("$DEFINITION{$inst} $template\n");
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
exit;
|
||
|
|
||
|
foreach $inst (sort keys %DEFINITION) {
|
||
|
$value=$DEFINITION{$inst};
|
||
|
printf("%-10s = $value\n",$inst);
|
||
|
}
|
||
|
|
||
|
|
||
|
foreach $sig (sort keys %{ $OUTPUT{$view} }) {
|
||
|
$position=$OUTPUT{$view}{$sig};
|
||
|
printf("$sig $position\n");
|
||
|
}
|