xref: /onnv-gate/usr/src/uts/i86pc/cpu/scripts/ao_gendisp.pl (revision 3164:475efbf127ed)
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