11414Scindi#!/bin/perl 21414Scindi# 31414Scindi# CDDL HEADER START 41414Scindi# 51414Scindi# The contents of this file are subject to the terms of the 61538Sgavinm# Common Development and Distribution License (the "License"). 71538Sgavinm# You may not use this file except in compliance with the License. 81414Scindi# 91414Scindi# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 101414Scindi# or http://www.opensolaris.org/os/licensing. 111414Scindi# See the License for the specific language governing permissions 121414Scindi# and limitations under the License. 131414Scindi# 141414Scindi# When distributing Covered Code, include this CDDL HEADER in each 151414Scindi# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 161414Scindi# If applicable, add the following below this CDDL HEADER, with the 171414Scindi# fields enclosed by brackets "[]" replaced with your own identifying 181414Scindi# information: Portions Copyright [yyyy] [name of copyright owner] 191414Scindi# 201414Scindi# CDDL HEADER END 211414Scindi# 221414Scindi 231414Scindi# 241414Scindi# Copyright 2006 Sun Microsystems, Inc. All rights reserved. 251414Scindi# Use is subject to license terms. 261414Scindi# 271414Scindi# ident "%Z%%M% %I% %E% SMI" 281414Scindi# 291414Scindi 301414Scindiuse strict; 311414Scindiuse File::Basename; 321414Scindi 331414Scindimy $PROGNAME = basename($0); 341414Scindi 351414Scindimy ($funcunit, $error); 361414Scindimy @funcunits = (); 37*3164Sgavinmmy @errorrefs = (); 38*3164Sgavinm 39*3164Sgavinmmy $codelinesin = 0; # number of input 'code' lines for an ereport type 40*3164Sgavinmmy $codeoutlen = 0; # number of output lines from sub state_code 411414Scindi 421414Scindimy $state = "initial"; 431414Scindi 441414Scindisub usage() { 451414Scindi print STDERR "Usage: $PROGNAME inputfile\n"; 461414Scindi exit(2); 471414Scindi} 481414Scindi 491414Scindisub bail() { 501414Scindi print STDERR "$PROGNAME: ", join(" ", @_), "\n"; 511414Scindi exit(1); 521414Scindi} 531414Scindi 541414Scindisub parsebail() { 551414Scindi print STDERR "$PROGNAME: $::infile: $.: ", join(" ", @_), "\n"; 561414Scindi exit(1); 571414Scindi} 581414Scindi 59*3164Sgavinmsub error_alloc() { 60*3164Sgavinm my @a = (); 61*3164Sgavinm 62*3164Sgavinm push(@::errorrefs, \@a); 63*3164Sgavinm return (\@a); 64*3164Sgavinm} 65*3164Sgavinm 66*3164Sgavinmsub error_dup() { 67*3164Sgavinm my ($drop) = @_; 68*3164Sgavinm my $newref = &error_alloc(); 69*3164Sgavinm 70*3164Sgavinm my $zeroref = $::errorrefs[0]; 71*3164Sgavinm 72*3164Sgavinm my $n = $#$zeroref - $drop; 73*3164Sgavinm 74*3164Sgavinm @$newref = @$zeroref[0 .. $n]; 75*3164Sgavinm} 76*3164Sgavinm 77*3164Sgavinmsub code_lines() { 78*3164Sgavinm return ($::codelinesin++); 79*3164Sgavinm} 80*3164Sgavinm 81*3164Sgavinmsub error_init() { 82*3164Sgavinm &error_alloc(); 83*3164Sgavinm $::codelinesin = 0; 84*3164Sgavinm} 85*3164Sgavinm 86*3164Sgavinmsub error_reset() { 87*3164Sgavinm @::errorrefs = (); 88*3164Sgavinm $::codelinesin = 0; 89*3164Sgavinm $::codeoutlen = 0; 90*3164Sgavinm} 91*3164Sgavinm 92*3164Sgavinmsub errout() { 93*3164Sgavinm my ($line) = @_; 94*3164Sgavinm 95*3164Sgavinm foreach my $ref (@::errorrefs) { 96*3164Sgavinm push(@$ref, $line); 97*3164Sgavinm } 98*3164Sgavinm} 99*3164Sgavinm 100*3164Sgavinmsub errout_N() { 101*3164Sgavinm my ($instance, $line) = @_; 102*3164Sgavinm my $ref = @::errorrefs[$instance]; 103*3164Sgavinm push(@$ref, $line); 104*3164Sgavinm return 1; 105*3164Sgavinm} 106*3164Sgavinm 107*3164Sgavinmsub print_errout() { 108*3164Sgavinm foreach my $ref (@::errorrefs) { 109*3164Sgavinm print @$ref; 110*3164Sgavinm } 111*3164Sgavinm} 112*3164Sgavinm 1131414Scindisub print_header() { 1141414Scindi print "#include \"ao_mca_disp.h\"\n\n"; 1151414Scindi} 1161414Scindi 1171414Scindisub print_footer() { 118*3164Sgavinm print 'const ao_error_disp_t *ao_error_disp[] = {' . "\n"; 1191414Scindi 1201414Scindi foreach my $name (@funcunits) { 1211414Scindi print "\t$name,\n"; 1221414Scindi } 1231414Scindi 1241414Scindi print "};\n"; 1251414Scindi} 1261414Scindi 1271414Scindisub funcunit_begin() { 1281414Scindi my $arrnm = "ao_error_disp_" . $_[0]; 1291414Scindi print "static const ao_error_disp_t " . $arrnm . "[] = {\n"; 1301414Scindi 1311414Scindi @funcunits = (@funcunits, $arrnm); 1321414Scindi} 1331414Scindi 1341414Scindisub funcunit_end() { 135*3164Sgavinm print "\t{ NULL }\n};\n\n"; 1361414Scindi} 1371414Scindi 1381414Scindisub error_begin() { 1391414Scindi my ($ereport_name) = @_; 1401414Scindi 1411414Scindi $ereport_name =~ tr/[a-z]./[A-Z]_/; 1421414Scindi my $flags_name = $ereport_name; 1431414Scindi $flags_name =~ s/EREPORT_/EREPORT_PAYLOAD_FLAGS_/; 1441414Scindi 145*3164Sgavinm &errout("\tFM_$ereport_name,\n\tFM_$flags_name,\n"); 1461414Scindi} 1471414Scindi 1481414Scindisub error_end() { 149*3164Sgavinm &errout("\t},\n\n"); 150*3164Sgavinm 151*3164Sgavinm &print_errout(); 152*3164Sgavinm 153*3164Sgavinm &error_reset(); 1541414Scindi} 1551414Scindi 1561414Scindisub print_bits() { 1571414Scindi my $name = $_[0]; 1581414Scindi my @bits = @_[1..$#_]; 159*3164Sgavinm my $out = ""; 1601414Scindi 1611414Scindi if (@bits == 0) { 162*3164Sgavinm $out = "\t0,"; 1631414Scindi } elsif (@bits == 1) { 164*3164Sgavinm $out = "\t$bits[0],"; 1651414Scindi } else { 166*3164Sgavinm $out = "\t( " . join(" | ", @bits) . " ),"; 1671414Scindi } 1681414Scindi 169*3164Sgavinm $out .= " /* $name */" if (defined $name); 170*3164Sgavinm $out .= "\n"; 171*3164Sgavinm 172*3164Sgavinm return ($out); 1731414Scindi} 1741414Scindi 1751414Scindisub field_burst() { 1761414Scindi my ($field, $valuesref, $name, $prefix) = @_; 1771414Scindi 1781414Scindi if ($field eq "-") { 1791414Scindi return (); 1801414Scindi } 1811414Scindi 1821414Scindi map { 1831414Scindi if (!defined ${$valuesref}{$_}) { 1841414Scindi &parsebail("unknown $name value `$_'"); 1851414Scindi } 1861414Scindi $_ = ${$valuesref}{$_}; 1871414Scindi tr/[a-z]/[A-Z]/; 1881414Scindi $prefix . "_" . $_; 1891414Scindi } split(/\//, $field); 1901414Scindi} 1911414Scindi 1921414Scindisub bin2dec() { 1931414Scindi my $bin = $_[0]; 1941414Scindi my $dec = 0; 1951414Scindi 1961414Scindi foreach my $bit (split(//, $bin)) { 1971414Scindi $dec = $dec * 2 + ($bit eq "1" ? 1 : 0); 1981414Scindi } 1991414Scindi 2001414Scindi $dec; 2011414Scindi} 2021414Scindi 2031414Scindisub state_funcunit() { 2041414Scindi my $val = $_[0]; 2051414Scindi 2061414Scindi if (defined $::funcunit) { 2071414Scindi &funcunit_end(); 2081414Scindi } 2091414Scindi 2101414Scindi $::funcunit = $val; 2111414Scindi undef $::error; 2121414Scindi &funcunit_begin($::funcunit); 2131414Scindi} 2141414Scindi 2151414Scindisub state_desc() { 2161414Scindi my $desc = $_[0]; 2171414Scindi 218*3164Sgavinm &error_init(); 219*3164Sgavinm 220*3164Sgavinm &errout("\t/* $desc */\n\t{\n"); 2211414Scindi} 2221414Scindi 2231414Scindisub state_error() { 2241414Scindi $::error = $_[0]; 2251414Scindi &error_begin($::error); 2261414Scindi} 2271414Scindi 2281414Scindisub state_mask_on() { 2291414Scindi @::mask_on = map { tr/[a-z]/[A-Z]/; $_; } split(/,\s*/, $_[0]); 2301414Scindi} 2311414Scindi 2321414Scindisub state_mask_off() { 2331414Scindi my @mask_off = map { tr/[a-z]/[A-Z]/; $_; } split(/,\s*/, $_[0]); 2341414Scindi 235*3164Sgavinm &errout(&print_bits("mask", @::mask_on, @mask_off)); 236*3164Sgavinm &errout(&print_bits("mask_res", @::mask_on)); 2371414Scindi} 2381414Scindi 2391414Scindisub state_code() { 240*3164Sgavinm my ($ext, $type, $pp, $t, $r4, $addr, $ii, $ll, $tt) = 241*3164Sgavinm split(/\s+/, $_[0]); 2421414Scindi 2431414Scindi my %tt_values = ( instr => 1, data => 1, gen => 1, '-' => 1 ); 2441414Scindi my %ll_values = ( l0 => 1, l1 => 1, l2 => 1, lg => 1 ); 2451414Scindi 2461414Scindi my %r4_values = ( 2471414Scindi gen => 'gen', 2481414Scindi rd => 'rd', 2491414Scindi wr => 'wr', 2501414Scindi drd => 'drd', 2511414Scindi dwr => 'dwr', 2521414Scindi ird => 'ird', 2531414Scindi pf => 'prefetch', 2541414Scindi ev => 'evict', 2551414Scindi snp => 'snoop', 2561414Scindi '-' => '-'); 2571414Scindi 2581414Scindi my %pp_values = ( 2591414Scindi src => 'src', 2601414Scindi rsp => 'rsp', 2611414Scindi obs => 'obs', 2621414Scindi gen => 'gen', 2631414Scindi '-' => '-' ); 2641414Scindi 2651414Scindi my %t_values = ( 0 => 1, 1 => 1, '-' => 1 ); 2661414Scindi 2671414Scindi my %ii_values = ( 2681414Scindi mem => 'mem', 2691414Scindi io => 'io', 2701414Scindi gen => 'gen', 2711414Scindi '-' => '-' ); 2721414Scindi 273*3164Sgavinm my $instance = &code_lines(); 274*3164Sgavinm if ($instance > 0) { 275*3164Sgavinm &error_dup($::codeoutlen); # dup info thus far 276*3164Sgavinm } 277*3164Sgavinm 2781414Scindi if (!defined $tt_values{$tt}) { 2791414Scindi &parsebail("unknown tt value `$tt'"); 2801414Scindi } 2811414Scindi 2821414Scindi if (!defined $ll_values{$ll}) { 2831414Scindi &parsebail("unknown ll value `$ll'"); 2841414Scindi } 2851414Scindi 2861414Scindi my @r4 = &field_burst($r4, \%r4_values, "r4", "AO_MCA_R4_BIT"); 2871414Scindi 2881414Scindi my @pp = ($pp eq '-') ? () : 2891414Scindi &field_burst($pp, \%pp_values, "pp", "AO_MCA_PP_BIT"); 2901414Scindi 2911414Scindi if (!defined $t_values{$t}) { 2921414Scindi &parsebail("unknown t value `$t'"); 2931414Scindi } 2941414Scindi 2951414Scindi my @ii = ($ii eq '-') ? () : 2961414Scindi &field_burst($ii, \%ii_values, "ii", "AO_MCA_II_BIT"); 2971414Scindi 2981414Scindi map { 2991414Scindi tr/[a-z]/[A-Z]/; 3001414Scindi } ($ii, $ll, $tt); 3011414Scindi 3021414Scindi if ($type eq "bus") { 3031414Scindi if ($pp eq "-" || $t eq "-" || $r4 eq "-" || $ii eq "-" || 3041414Scindi $ll eq "-" || 3051414Scindi $tt ne "-") { 3061414Scindi &parsebail("invalid members for bus code type"); 3071414Scindi } 3081414Scindi 309*3164Sgavinm $::codeoutlen += &errout_N($instance, "\tAMD_ERRCODE_MKBUS(" . 3101414Scindi "0, " . # pp 3111414Scindi "AMD_ERRCODE_T_" . ($t ? "TIMEOUT" : "NONE") . ", " . 3121414Scindi "0, " . # r4 3131414Scindi "0, " . # ii 314*3164Sgavinm "AMD_ERRCODE_LL_$ll),\n"); 3151414Scindi 3161414Scindi } elsif ($type eq "mem") { 3171414Scindi if ($r4 eq "-" || $tt eq "-" || $ll eq "-" || 3181414Scindi $pp ne "-" || $t ne "-" || $ii ne "-") { 3191414Scindi &parsebail("invalid members for mem code type"); 3201414Scindi } 3211414Scindi 322*3164Sgavinm $::codeoutlen += &errout_N($instance, "\tAMD_ERRCODE_MKMEM(" . 3231414Scindi "0, " . # r4 3241414Scindi "AMD_ERRCODE_TT_$tt, " . 325*3164Sgavinm "AMD_ERRCODE_LL_$ll),\n"); 3261414Scindi 3271414Scindi } elsif ($type eq "tlb") { 3281414Scindi if ($tt eq "-" || $ll eq "-" || 3291414Scindi $r4 ne "-" || $pp ne "-" || $t ne "-" || $ii ne "-") { 3301414Scindi &parsebail("invalid members for tlb code type"); 3311414Scindi } 3321414Scindi 333*3164Sgavinm $::codeoutlen += &errout_N($instance, "\tAMD_ERRCODE_MKTLB(" . 3341414Scindi "AMD_ERRCODE_TT_$tt, " . 335*3164Sgavinm "AMD_ERRCODE_LL_$ll),\n"); 3361414Scindi } else { 3371414Scindi &parsebail("unknown code type `$type'"); 3381414Scindi } 3391414Scindi 340*3164Sgavinm $::codeoutlen += &errout_N($instance, "\t" . &bin2dec($ext) . 341*3164Sgavinm ", /* ext code $ext */\n"); 342*3164Sgavinm 343*3164Sgavinm $::codeoutlen += &errout_N($instance, &print_bits("pp_bits", @pp)); 344*3164Sgavinm $::codeoutlen += &errout_N($instance, &print_bits("ii_bits", @ii)); 345*3164Sgavinm $::codeoutlen += &errout_N($instance, &print_bits("r4_bits", @r4)); 346*3164Sgavinm 347*3164Sgavinm my $valid_hi; 348*3164Sgavinm my $valid_lo; 3491414Scindi 350*3164Sgavinm if ($addr eq "none") { 351*3164Sgavinm $valid_hi = $valid_lo = 0; 352*3164Sgavinm } elsif ($addr =~ /<(\d+):(\d+)>/) { 353*3164Sgavinm $valid_hi = $1; 354*3164Sgavinm $valid_lo = $2; 355*3164Sgavinm } else { 356*3164Sgavinm &parsebail("invalid addr specification"); 357*3164Sgavinm } 358*3164Sgavinm $::codeoutlen += &errout_N($instance, "\t" . $valid_hi . 359*3164Sgavinm ", /* addr valid hi */\n"); 360*3164Sgavinm $::codeoutlen += &errout_N($instance, "\t" . $valid_lo . 361*3164Sgavinm ", /* addr valid lo */\n"); 3621414Scindi} 3631414Scindi 3641414Scindisub state_panic() { 3651538Sgavinm my @vals = split(/,\s*/, $_[0]); 3661414Scindi 3671538Sgavinm if ($#vals < 0) { 368*3164Sgavinm &errout("\t0, /* panic_when */\n"); 3691414Scindi } else { 3701538Sgavinm @vals = map { tr/[a-z]/[A-Z]/; "AO_AED_PANIC_" . $_; } @vals; 371*3164Sgavinm &errout(&print_bits("panic_when", @vals)); 3721414Scindi } 3731414Scindi} 3741414Scindi 3751414Scindisub state_flags() { 3761414Scindi my @flags = split(/,\s*/, $_[0]); 3771414Scindi 3781414Scindi @flags = map { tr/[a-z]/[A-Z]/; "AO_AED_F_" . $_; } @flags; 3791414Scindi 380*3164Sgavinm &errout(&print_bits("flags", @flags)); 3811414Scindi} 3821414Scindi 3831414Scindimy %stateparse = ( 384*3164Sgavinm funcunit => [ \&state_funcunit, 'desc' ], 385*3164Sgavinm desc => [ \&state_desc, 'error' ], 386*3164Sgavinm error => [ \&state_error, 'mask on' ], 387*3164Sgavinm 'mask on' => [ \&state_mask_on, 'mask off' ], 388*3164Sgavinm 'mask off' => [ \&state_mask_off, 'code' ], 389*3164Sgavinm code => [ \&state_code, 'code|panic' ], 390*3164Sgavinm panic => [ \&state_panic, 'flags' ], 391*3164Sgavinm flags => [ \&state_flags, 'initial' ] 3921414Scindi); 3931414Scindi 3941414Scindiusage unless (@ARGV == 1); 3951414Scindi 3961414Scindimy $infile = $ARGV[0]; 3971414Scindiopen(INFILE, "<$infile") || &bail("failed to open $infile: $!"); 3981414Scindi 3991414Scindi&print_header(); 4001414Scindi 4011414Scindiwhile (<INFILE>) { 4021414Scindi chop; 4031414Scindi 4041414Scindi /^#/ && next; 4051414Scindi /^$/ && next; 4061414Scindi 4071414Scindi if (!/^\s*(\S[^=]*\S)\s*=\s*(\S.*)?$/) { 4081414Scindi &parsebail("failed to parse"); 4091414Scindi } 4101414Scindi 4111414Scindi my ($keyword, $val) = ($1, $2); 4121414Scindi 4131414Scindi if ($state eq "initial") { 4141414Scindi if ($keyword eq "funcunit") { 4151414Scindi $state = "funcunit"; 4161414Scindi } elsif ($keyword eq "desc") { 4171414Scindi $state = "desc"; 4181414Scindi } else { 4191414Scindi &parsebail("unexpected keyword $keyword between " . 4201414Scindi "errors"); 4211414Scindi } 4221414Scindi 4231414Scindi } elsif ($state eq "desc") { 4241414Scindi if ($keyword eq "funcunit") { 4251414Scindi $state = "funcunit"; 4261414Scindi } 4271414Scindi } 4281414Scindi 429*3164Sgavinm if (!($keyword =~ /$state/)) { 430*3164Sgavinm &parsebail("keyword `$keyword' invalid here; expected " . 431*3164Sgavinm "`$state'"); 4321414Scindi } 433*3164Sgavinm $state = $keyword; # disambiguate between multiple legal states 4341414Scindi 4351414Scindi if (!defined $stateparse{$state}) { 4361414Scindi &parsebail("attempt to transition to invalid state `$state'"); 4371414Scindi } 4381414Scindi 4391414Scindi my ($handler, $next) = @{$stateparse{$state}}; 4401414Scindi 4411414Scindi &{$handler}($val); 4421414Scindi 4431414Scindi $state = $next; 4441414Scindi 4451414Scindi if ($state eq "initial") { 4461414Scindi &error_end(); 4471414Scindi } 4481414Scindi} 4491414Scindi 4501414Scindiclose(INFILE); 4511414Scindi 4521414Scindiif ($state ne "initial" && $state ne "desc") { 4531414Scindi &bail("input file ended prematurely"); 4541414Scindi} 4551414Scindi 4561414Scindiif (defined $::funcunit) { 4571414Scindi &funcunit_end(); 4581414Scindi} else { 4591414Scindi &bail("no functional units defined"); 4601414Scindi} 4611414Scindi 4621414Scindi&print_footer; 463