17aec1d6eScindi#!/bin/perl
27aec1d6eScindi#
37aec1d6eScindi# CDDL HEADER START
47aec1d6eScindi#
57aec1d6eScindi# The contents of this file are subject to the terms of the
6*a307a255Sgavinm# Common Development and Distribution License (the "License").
7*a307a255Sgavinm# You may not use this file except in compliance with the License.
87aec1d6eScindi#
97aec1d6eScindi# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107aec1d6eScindi# or http://www.opensolaris.org/os/licensing.
117aec1d6eScindi# See the License for the specific language governing permissions
127aec1d6eScindi# and limitations under the License.
137aec1d6eScindi#
147aec1d6eScindi# When distributing Covered Code, include this CDDL HEADER in each
157aec1d6eScindi# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167aec1d6eScindi# If applicable, add the following below this CDDL HEADER, with the
177aec1d6eScindi# fields enclosed by brackets "[]" replaced with your own identifying
187aec1d6eScindi# information: Portions Copyright [yyyy] [name of copyright owner]
197aec1d6eScindi#
207aec1d6eScindi# CDDL HEADER END
217aec1d6eScindi#
227aec1d6eScindi
237aec1d6eScindi#
247aec1d6eScindi# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
257aec1d6eScindi# Use is subject to license terms.
267aec1d6eScindi#
277aec1d6eScindi# ident	"%Z%%M%	%I%	%E% SMI"
287aec1d6eScindi#
297aec1d6eScindi
307aec1d6eScindiuse strict;
317aec1d6eScindiuse File::Basename;
327aec1d6eScindi
337aec1d6eScindimy $PROGNAME = basename($0);
347aec1d6eScindi
357aec1d6eScindimy ($funcunit, $error);
367aec1d6eScindimy @funcunits = ();
377aec1d6eScindi
387aec1d6eScindimy $state = "initial";
397aec1d6eScindi
407aec1d6eScindisub usage() {
417aec1d6eScindi	print STDERR "Usage: $PROGNAME inputfile\n";
427aec1d6eScindi	exit(2);
437aec1d6eScindi}
447aec1d6eScindi
457aec1d6eScindisub bail() {
467aec1d6eScindi	print STDERR "$PROGNAME: ", join(" ", @_), "\n";
477aec1d6eScindi	exit(1);
487aec1d6eScindi}
497aec1d6eScindi
507aec1d6eScindisub parsebail() {
517aec1d6eScindi	print STDERR "$PROGNAME: $::infile: $.: ", join(" ", @_), "\n";
527aec1d6eScindi	exit(1);
537aec1d6eScindi}
547aec1d6eScindi
557aec1d6eScindisub print_header() {
567aec1d6eScindi	print "#include \"ao_mca_disp.h\"\n\n";
577aec1d6eScindi}
587aec1d6eScindi
597aec1d6eScindisub print_footer() {
607aec1d6eScindi	print "const ao_error_disp_t *ao_error_disp[] = {\n";
617aec1d6eScindi
627aec1d6eScindi	foreach my $name (@funcunits) {
637aec1d6eScindi		print "\t$name,\n";
647aec1d6eScindi	}
657aec1d6eScindi
667aec1d6eScindi	print "};\n";
677aec1d6eScindi}
687aec1d6eScindi
697aec1d6eScindisub funcunit_begin() {
707aec1d6eScindi	my $arrnm = "ao_error_disp_" . $_[0];
717aec1d6eScindi	print "static const ao_error_disp_t " . $arrnm . "[] = {\n";
727aec1d6eScindi
737aec1d6eScindi	@funcunits = (@funcunits, $arrnm);
747aec1d6eScindi}
757aec1d6eScindi
767aec1d6eScindisub funcunit_end() {
777aec1d6eScindi	print "\tNULL\n};\n\n";
787aec1d6eScindi}
797aec1d6eScindi
807aec1d6eScindisub error_begin() {
817aec1d6eScindi	my ($ereport_name) = @_;
827aec1d6eScindi
837aec1d6eScindi	$ereport_name =~ tr/[a-z]./[A-Z]_/;
847aec1d6eScindi	my $flags_name = $ereport_name;
857aec1d6eScindi	$flags_name =~ s/EREPORT_/EREPORT_PAYLOAD_FLAGS_/;
867aec1d6eScindi
877aec1d6eScindi	print "\tFM_$ereport_name,\n\tFM_$flags_name,\n";
887aec1d6eScindi}
897aec1d6eScindi
907aec1d6eScindisub error_end() {
917aec1d6eScindi	print "\t},\n\n";
927aec1d6eScindi}
937aec1d6eScindi
947aec1d6eScindisub print_bits() {
957aec1d6eScindi	my $name = $_[0];
967aec1d6eScindi	my @bits = @_[1..$#_];
977aec1d6eScindi
987aec1d6eScindi	if (@bits == 0) {
997aec1d6eScindi		print "\t0,";
1007aec1d6eScindi	} elsif (@bits == 1) {
1017aec1d6eScindi		print "\t$bits[0],";
1027aec1d6eScindi	} else {
1037aec1d6eScindi		print "\t( ", join(" | ", @bits), " ),";
1047aec1d6eScindi	}
1057aec1d6eScindi
106*a307a255Sgavinm	print " /* $name */" if (defined $name);
107*a307a255Sgavinm	print "\n";
1087aec1d6eScindi}
1097aec1d6eScindi
1107aec1d6eScindisub field_burst() {
1117aec1d6eScindi	my ($field, $valuesref, $name, $prefix) = @_;
1127aec1d6eScindi
1137aec1d6eScindi	if ($field eq "-") {
1147aec1d6eScindi		return ();
1157aec1d6eScindi	}
1167aec1d6eScindi
1177aec1d6eScindi	map {
1187aec1d6eScindi		if (!defined ${$valuesref}{$_}) {
1197aec1d6eScindi			&parsebail("unknown $name value `$_'");
1207aec1d6eScindi		}
1217aec1d6eScindi		$_ = ${$valuesref}{$_};
1227aec1d6eScindi		tr/[a-z]/[A-Z]/;
1237aec1d6eScindi		$prefix . "_" . $_;
1247aec1d6eScindi	} split(/\//, $field);
1257aec1d6eScindi}
1267aec1d6eScindi
1277aec1d6eScindisub bin2dec() {
1287aec1d6eScindi	my $bin = $_[0];
1297aec1d6eScindi	my $dec = 0;
1307aec1d6eScindi
1317aec1d6eScindi	foreach my $bit (split(//, $bin)) {
1327aec1d6eScindi		$dec = $dec * 2 + ($bit eq "1" ? 1 : 0);
1337aec1d6eScindi	}
1347aec1d6eScindi
1357aec1d6eScindi	$dec;
1367aec1d6eScindi}
1377aec1d6eScindi
1387aec1d6eScindisub state_funcunit() {
1397aec1d6eScindi	my $val = $_[0];
1407aec1d6eScindi
1417aec1d6eScindi	if (defined $::funcunit) {
1427aec1d6eScindi		&funcunit_end();
1437aec1d6eScindi	}
1447aec1d6eScindi
1457aec1d6eScindi	$::funcunit = $val;
1467aec1d6eScindi	undef $::error;
1477aec1d6eScindi	&funcunit_begin($::funcunit);
1487aec1d6eScindi}
1497aec1d6eScindi
1507aec1d6eScindisub state_desc() {
1517aec1d6eScindi	my $desc = $_[0];
1527aec1d6eScindi
1537aec1d6eScindi	print "\t/* $desc */\n\t{\n";
1547aec1d6eScindi}
1557aec1d6eScindi
1567aec1d6eScindisub state_error() {
1577aec1d6eScindi	$::error = $_[0];
1587aec1d6eScindi	&error_begin($::error);
1597aec1d6eScindi}
1607aec1d6eScindi
1617aec1d6eScindisub state_mask_on() {
1627aec1d6eScindi	@::mask_on = map { tr/[a-z]/[A-Z]/; $_; } split(/,\s*/, $_[0]);
1637aec1d6eScindi}
1647aec1d6eScindi
1657aec1d6eScindisub state_mask_off() {
1667aec1d6eScindi	my @mask_off = map { tr/[a-z]/[A-Z]/; $_; } split(/,\s*/, $_[0]);
1677aec1d6eScindi
1687aec1d6eScindi	&print_bits("mask", @::mask_on, @mask_off);
1697aec1d6eScindi	&print_bits("mask_res", @::mask_on);
1707aec1d6eScindi}
1717aec1d6eScindi
1727aec1d6eScindisub state_code() {
1737aec1d6eScindi	my ($ext, $type, $pp, $t, $r4, $ii, $ll, $tt) = split(/\s+/, $_[0]);
1747aec1d6eScindi
1757aec1d6eScindi	my %tt_values = ( instr => 1, data => 1, gen => 1, '-' => 1 );
1767aec1d6eScindi	my %ll_values = ( l0 => 1, l1 => 1, l2 => 1, lg => 1 );
1777aec1d6eScindi
1787aec1d6eScindi	my %r4_values = (
1797aec1d6eScindi		gen => 'gen',
1807aec1d6eScindi		rd => 'rd',
1817aec1d6eScindi		wr => 'wr',
1827aec1d6eScindi		drd => 'drd',
1837aec1d6eScindi		dwr => 'dwr',
1847aec1d6eScindi		ird => 'ird',
1857aec1d6eScindi		pf => 'prefetch',
1867aec1d6eScindi		ev => 'evict',
1877aec1d6eScindi		snp => 'snoop',
1887aec1d6eScindi	        '-' => '-');
1897aec1d6eScindi
1907aec1d6eScindi	my %pp_values = (
1917aec1d6eScindi		src => 'src',
1927aec1d6eScindi		rsp => 'rsp',
1937aec1d6eScindi		obs => 'obs',
1947aec1d6eScindi		gen => 'gen',
1957aec1d6eScindi		'-' => '-' );
1967aec1d6eScindi
1977aec1d6eScindi	my %t_values = ( 0 => 1, 1 => 1, '-' => 1 );
1987aec1d6eScindi
1997aec1d6eScindi	my %ii_values = (
2007aec1d6eScindi		mem => 'mem',
2017aec1d6eScindi		io => 'io',
2027aec1d6eScindi		gen => 'gen',
2037aec1d6eScindi		'-' => '-' );
2047aec1d6eScindi
2057aec1d6eScindi	if (!defined $tt_values{$tt}) {
2067aec1d6eScindi		&parsebail("unknown tt value `$tt'");
2077aec1d6eScindi	}
2087aec1d6eScindi
2097aec1d6eScindi	if (!defined $ll_values{$ll}) {
2107aec1d6eScindi		&parsebail("unknown ll value `$ll'");
2117aec1d6eScindi	}
2127aec1d6eScindi
2137aec1d6eScindi	my @r4 = &field_burst($r4, \%r4_values, "r4", "AO_MCA_R4_BIT");
2147aec1d6eScindi
2157aec1d6eScindi	my @pp = ($pp eq '-') ? () :
2167aec1d6eScindi	    &field_burst($pp, \%pp_values, "pp", "AO_MCA_PP_BIT");
2177aec1d6eScindi
2187aec1d6eScindi	if (!defined $t_values{$t}) {
2197aec1d6eScindi		&parsebail("unknown t value `$t'");
2207aec1d6eScindi	}
2217aec1d6eScindi
2227aec1d6eScindi	my @ii = ($ii eq '-') ? () :
2237aec1d6eScindi	    &field_burst($ii, \%ii_values, "ii", "AO_MCA_II_BIT");
2247aec1d6eScindi
2257aec1d6eScindi	map {
2267aec1d6eScindi		tr/[a-z]/[A-Z]/;
2277aec1d6eScindi	} ($ii, $ll, $tt);
2287aec1d6eScindi
2297aec1d6eScindi	if ($type eq "bus") {
2307aec1d6eScindi		if ($pp eq "-" || $t eq "-" || $r4 eq "-" || $ii eq "-" ||
2317aec1d6eScindi		    $ll eq "-" ||
2327aec1d6eScindi		    $tt ne "-") {
2337aec1d6eScindi			&parsebail("invalid members for bus code type");
2347aec1d6eScindi		}
2357aec1d6eScindi
2367aec1d6eScindi		print "\tAMD_ERRCODE_MKBUS(" .
2377aec1d6eScindi		    "0, " . # pp
2387aec1d6eScindi		    "AMD_ERRCODE_T_" . ($t ? "TIMEOUT" : "NONE") . ", " .
2397aec1d6eScindi		    "0, " . # r4
2407aec1d6eScindi		    "0, " . # ii
2417aec1d6eScindi		    "AMD_ERRCODE_LL_$ll),\n";
2427aec1d6eScindi
2437aec1d6eScindi	} elsif ($type eq "mem") {
2447aec1d6eScindi		if ($r4 eq "-" || $tt eq "-" || $ll eq "-" ||
2457aec1d6eScindi		    $pp ne "-" || $t ne "-" || $ii ne "-") {
2467aec1d6eScindi			&parsebail("invalid members for mem code type");
2477aec1d6eScindi		}
2487aec1d6eScindi
2497aec1d6eScindi		print "\tAMD_ERRCODE_MKMEM(" .
2507aec1d6eScindi		    "0, " . # r4
2517aec1d6eScindi		    "AMD_ERRCODE_TT_$tt, " .
2527aec1d6eScindi		    "AMD_ERRCODE_LL_$ll),\n";
2537aec1d6eScindi
2547aec1d6eScindi	} elsif ($type eq "tlb") {
2557aec1d6eScindi		if ($tt eq "-" || $ll eq "-" ||
2567aec1d6eScindi		    $r4 ne "-" || $pp ne "-" || $t ne "-" || $ii ne "-") {
2577aec1d6eScindi			&parsebail("invalid members for tlb code type");
2587aec1d6eScindi		}
2597aec1d6eScindi
2607aec1d6eScindi		print "\tAMD_ERRCODE_MKTLB(" .
2617aec1d6eScindi		    "AMD_ERRCODE_TT_$tt, " .
2627aec1d6eScindi		    "AMD_ERRCODE_LL_$ll),\n";
2637aec1d6eScindi	} else {
2647aec1d6eScindi		&parsebail("unknown code type `$type'");
2657aec1d6eScindi	}
2667aec1d6eScindi
2677aec1d6eScindi	print "\t" . &bin2dec($ext) . ", /* ext code $ext */\n";
2687aec1d6eScindi
2697aec1d6eScindi	&print_bits("pp_bits", @pp);
2707aec1d6eScindi	&print_bits("ii_bits", @ii);
2717aec1d6eScindi	&print_bits("r4_bits", @r4);
2727aec1d6eScindi}
2737aec1d6eScindi
2747aec1d6eScindisub state_panic() {
275*a307a255Sgavinm	my @vals = split(/,\s*/, $_[0]);
2767aec1d6eScindi
277*a307a255Sgavinm	if ($#vals < 0) {
2787aec1d6eScindi		print "\t0, /* panic_when */\n";
2797aec1d6eScindi	} else {
280*a307a255Sgavinm		@vals = map { tr/[a-z]/[A-Z]/; "AO_AED_PANIC_" . $_; } @vals;
281*a307a255Sgavinm		&print_bits("panic_when", @vals);
2827aec1d6eScindi	}
2837aec1d6eScindi}
2847aec1d6eScindi
2857aec1d6eScindisub state_flags() {
2867aec1d6eScindi	my @flags = split(/,\s*/, $_[0]);
2877aec1d6eScindi
2887aec1d6eScindi	@flags = map { tr/[a-z]/[A-Z]/; "AO_AED_F_" . $_; } @flags;
2897aec1d6eScindi
2907aec1d6eScindi	&print_bits("flags", @flags);
2917aec1d6eScindi}
2927aec1d6eScindi
2937aec1d6eScindimy %stateparse = (
2947aec1d6eScindi	funcunit	=> [ \&state_funcunit, "desc" ],
2957aec1d6eScindi	desc		=> [ \&state_desc, "error" ],
2967aec1d6eScindi	error		=> [ \&state_error, "mask on" ],
2977aec1d6eScindi	'mask on'	=> [ \&state_mask_on, "mask off" ],
2987aec1d6eScindi	'mask off'	=> [ \&state_mask_off, "code" ],
2997aec1d6eScindi	code		=> [ \&state_code, "panic" ],
3007aec1d6eScindi	panic		=> [ \&state_panic, "flags" ],
3017aec1d6eScindi	flags		=> [ \&state_flags, "initial" ]
3027aec1d6eScindi);
3037aec1d6eScindi
3047aec1d6eScindiusage unless (@ARGV == 1);
3057aec1d6eScindi
3067aec1d6eScindimy $infile = $ARGV[0];
3077aec1d6eScindiopen(INFILE, "<$infile") || &bail("failed to open $infile: $!");
3087aec1d6eScindi
3097aec1d6eScindi&print_header();
3107aec1d6eScindi
3117aec1d6eScindiwhile (<INFILE>) {
3127aec1d6eScindi	chop;
3137aec1d6eScindi
3147aec1d6eScindi	/^#/ && next;
3157aec1d6eScindi	/^$/ && next;
3167aec1d6eScindi
3177aec1d6eScindi	if (!/^\s*(\S[^=]*\S)\s*=\s*(\S.*)?$/) {
3187aec1d6eScindi		&parsebail("failed to parse");
3197aec1d6eScindi	}
3207aec1d6eScindi
3217aec1d6eScindi	my ($keyword, $val) = ($1, $2);
3227aec1d6eScindi
3237aec1d6eScindi	if ($state eq "initial") {
3247aec1d6eScindi		if ($keyword eq "funcunit") {
3257aec1d6eScindi			$state = "funcunit";
3267aec1d6eScindi		} elsif ($keyword eq "desc") {
3277aec1d6eScindi			$state = "desc";
3287aec1d6eScindi		} else {
3297aec1d6eScindi			&parsebail("unexpected keyword $keyword between " .
3307aec1d6eScindi			    "errors");
3317aec1d6eScindi		}
3327aec1d6eScindi
3337aec1d6eScindi	} elsif ($state eq "desc") {
3347aec1d6eScindi		if ($keyword eq "funcunit") {
3357aec1d6eScindi			$state = "funcunit";
3367aec1d6eScindi		}
3377aec1d6eScindi	}
3387aec1d6eScindi
3397aec1d6eScindi	if ($keyword ne $state) {
3407aec1d6eScindi		&parsebail("keyword `$keyword' invalid here; expected `$state'");
3417aec1d6eScindi	}
3427aec1d6eScindi
3437aec1d6eScindi	if (!defined $stateparse{$state}) {
3447aec1d6eScindi		&parsebail("attempt to transition to invalid state `$state'");
3457aec1d6eScindi	}
3467aec1d6eScindi
3477aec1d6eScindi	my ($handler, $next) = @{$stateparse{$state}};
3487aec1d6eScindi
3497aec1d6eScindi	&{$handler}($val);
3507aec1d6eScindi
3517aec1d6eScindi	$state = $next;
3527aec1d6eScindi
3537aec1d6eScindi	if ($state eq "initial") {
3547aec1d6eScindi		&error_end();
3557aec1d6eScindi	}
3567aec1d6eScindi}
3577aec1d6eScindi
3587aec1d6eScindiclose(INFILE);
3597aec1d6eScindi
3607aec1d6eScindiif ($state ne "initial" && $state ne "desc") {
3617aec1d6eScindi	&bail("input file ended prematurely");
3627aec1d6eScindi}
3637aec1d6eScindi
3647aec1d6eScindiif (defined $::funcunit) {
3657aec1d6eScindi	&funcunit_end();
3667aec1d6eScindi} else {
3677aec1d6eScindi	&bail("no functional units defined");
3687aec1d6eScindi}
3697aec1d6eScindi
3707aec1d6eScindi&print_footer;
371