| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  | #!/usr/bin/perl | 
					
						
							| 
									
										
										
										
											2020-05-16 02:28:59 +08:00
										 |  |  | # 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. | 
					
						
							|  |  |  | # | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | use Getopt::Long; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | $helpusage = "placeholder"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GetOptions ('legal'  => \$legal, | 
					
						
							| 
									
										
										
										
											2020-02-20 10:25:04 +08:00
										 |  |  |             'in=s'   => \$in, | 
					
						
							|  |  |  |             'out=s'  => \$out, | 
					
						
							|  |  |  |             'view=s' => \$view ) || die("$helpusage"); | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-20 10:25:04 +08:00
										 |  |  |     if ($line=~/^\s*\#/) { #printf("skip $line"); | 
					
						
							|  |  |  |                            next; } | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ($gather==1) { | 
					
						
							| 
									
										
										
										
											2020-02-20 10:25:04 +08:00
										 |  |  |         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"); } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ($line=~/^.definition/) { | 
					
						
							| 
									
										
										
										
											2020-02-20 10:25:04 +08:00
										 |  |  |         $pstate=1; next; | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |      if ($pstate==1) {  # definition | 
					
						
							| 
									
										
										
										
											2020-02-20 10:25:04 +08:00
										 |  |  |         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; } | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ($line=~/^.input/) { | 
					
						
							| 
									
										
										
										
											2020-02-20 10:25:04 +08:00
										 |  |  |         $pstate=2; next; | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ($pstate==2) {  # input | 
					
						
							| 
									
										
										
										
											2020-02-20 10:25:04 +08:00
										 |  |  |         if ($line=~/(\S+)\s*=\s*\{/) { | 
					
						
							|  |  |  |             $CVIEW=$1; $gather=1; next; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ($line=~/^.output/) { | 
					
						
							| 
									
										
										
										
											2020-02-20 10:25:04 +08:00
										 |  |  |         $pstate=3; next; | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ($pstate==3) {  # output | 
					
						
							| 
									
										
										
										
											2020-02-20 10:25:04 +08:00
										 |  |  |         if ($line=~/(\S+)\s*=\s*\{/) { | 
					
						
							|  |  |  |             $CVIEW=$1; $gather=1; next; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ($line=~/^.decode/) { | 
					
						
							| 
									
										
										
										
											2020-02-20 10:25:04 +08:00
										 |  |  |         $pstate=4; next; | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    if ($pstate==4) {  # decode | 
					
						
							| 
									
										
										
										
											2020-02-20 10:25:04 +08:00
										 |  |  |         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; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #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} }) { | 
					
						
							| 
									
										
										
										
											2020-02-20 10:25:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  |     $body=$DECODE{$view}{$inst}; | 
					
						
							|  |  |  |     @sigs=split(' ',$body); | 
					
						
							| 
									
										
										
										
											2020-02-20 10:25:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  |     $template=$DEFAULT_TEMPLATE; | 
					
						
							|  |  |  |     foreach $sig (@sigs) { | 
					
						
							| 
									
										
										
										
											2020-02-20 10:25:04 +08:00
										 |  |  |         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); | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #    if (!defined($DEFINITION{$inst})) { die("could not find instruction defintion for inst $inst"); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     printf("# $inst\n"); | 
					
						
							|  |  |  |     if (defined($legal)) { | 
					
						
							| 
									
										
										
										
											2020-02-20 10:25:04 +08:00
										 |  |  |         printf("$DEFINITION{$inst} 1\n"); | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2020-02-20 10:25:04 +08:00
										 |  |  |         printf("$DEFINITION{$inst} $template\n"); | 
					
						
							| 
									
										
										
										
											2019-06-04 22:57:48 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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"); | 
					
						
							|  |  |  | } |