1#! /bin/sh
2
3# $Id: sparc-bus-auto.sh,v 1.1 2006/09/30 12:55:59 fredette Exp $
4
5# ic/sparc/sparc-bus-auto.sh - automatically generates C code
6# for SPARC bus emulation support:
7
8#
9# Copyright (c) 2003, 2005 Matt Fredette
10# All rights reserved.
11#
12# Redistribution and use in source and binary forms, with or without
13# modification, are permitted provided that the following conditions
14# are met:
15# 1. Redistributions of source code must retain the above copyright
16#    notice, this list of conditions and the following disclaimer.
17# 2. Redistributions in binary form must reproduce the above copyright
18#    notice, this list of conditions and the following disclaimer in the
19#    documentation and/or other materials provided with the distribution.
20# 3. All advertising materials mentioning features or use of this software
21#    must display the following acknowledgement:
22#      This product includes software developed by Matt Fredette.
23# 4. The name of the author may not be used to endorse or promote products
24#    derived from this software without specific prior written permission.
25#
26# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29# DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
30# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36# POSSIBILITY OF SUCH DAMAGE.
37#
38
39header=false
40
41for option
42do
43    case $option in
44    --header) header=true ;;
45    esac
46done
47
48PROG=`basename $0`
49cat <<EOF
50/* automatically generated by $PROG, do not edit! */
51_TME_RCSID("\$Id: sparc-bus-auto.sh,v 1.1 2006/09/30 12:55:59 fredette Exp $");
52
53/* it was easiest, but probably not the most correct, to reuse the
54   m68020 bus router, at least for the early SPARCs.  there are
55   probably real differences between the m68020 bus router and the bus
56   router used by the MB89600, for example, but I don't have a
57   datasheet for the latter.  the placement of devices in the Sun
58   4/2x0 address space, however, hints that the two probably are very
59   similar. */
60
61/* we use OP3, OP2, OP1, and OP0 to represent bytes of lesser
62   significance to more significance, respectively, matching Table 5-5
63   in the MC68020 User's Manual (linear page 56 in my .ps copy).
64
65   the Motorola OPn convention numbers bytes by decreasing
66   significance (OP2 is less significant than OP1), and since Motorola
67   CPUs are big-endian, this means that a higher numbered byte is
68   meant to go to a higher address, which is good, because we can then
69   use this to easily form indexes for TME_BUS_LANE_ROUTE, which
70   expects a higher numbered index to correspond to a higher address
71   in memory.
72
73   however, since the same Motorola OPn convention always calls the
74   least significant byte of any value OP3, regardless of the total
75   size of the value, we need to adjust each OPn given the total
76   size of the value, so that OP3 in a 24-bit value means address + 2,
77   but OP3 in a 32-bit value means address + 3: */
78#define SIZ8_OP(n)	((n) - 3)
79#define SIZ16_OP(n)	((n) - 2)
80#define SIZ24_OP(n)	((n) - 1)
81#define SIZ32_OP(n)	((n) - 0)
82EOF
83
84# emit the 32-bit bus router:
85if $header; then :; else
86    echo ""
87    echo "/* the 32-bit bus router used on the early SPARCs: */"
88    echo "static const tme_bus_lane_t tme_sparc32_router[TME_SPARC_BUS_ROUTER_SIZE(TME_BUS32_LOG2)] = {"
89
90    # permute over maximum cycle size:
91    for transfer in 1 2 3 4; do
92	# these are real 68020 SIZ1 and SIZ0 bits:
93	case ${transfer} in
94	1) transfer_bits="01" ;;
95	2) transfer_bits="10" ;;
96	3) transfer_bits="11" ;;
97	4) transfer_bits="00" ;;
98	esac
99
100	# permute over A1 and A0:
101	for address in 0 1 2 3; do
102	    case $address in
103	    0) address_bits=00 ;;
104	    1) address_bits=01 ;;
105	    2) address_bits=10 ;;
106	    3) address_bits=11 ;;
107	    esac
108
109	    # permute over the size of the responding device's port:
110	    for port_size in 1 2 4; do
111
112		# permute over the byte lane position of the responding device's port:
113		for port_pos in 0 1 2 3; do
114
115		    # get a string describing the byte lanes connected
116		    # to this device.  NB that the sparc 32-bit bus
117		    # router assumes that 8-bit devices are always
118		    # connected to D31-D24, and that 16-bit devices
119		    # are always connected to D31-D24 and D23-D16, and
120		    # cannot dynamically adapt to other
121		    # configurations:
122		    port_pos_end=`expr ${port_pos} + ${port_size}`
123		    port_pos_lane=$port_pos
124		    port_lanes=""
125		    while test `expr ${port_pos_lane} \< ${port_pos_end}` = 1; do
126			port_lanes=" D"`expr \( \( ${port_pos_lane} + 1 \) \* 8 \) - 1`"-D"`expr ${port_pos_lane} \* 8`"${port_lanes}"
127			port_pos_lane=`expr ${port_pos_lane} + 1`
128		    done
129		    if test `expr ${port_pos_end} \> 4` = 1; then
130			port_lanes="${port_lanes} - invalid, array placeholder"
131		    elif ( test $port_size = 1 && test $port_pos != 3 ) \
132		         || ( test $port_size = 2 && test $port_pos != 2 ); then
133		        port_lanes="${port_lanes} - incorrect for 32-bit sparc"
134		    fi
135
136		    # find the byte lane that would provide OP3.  note
137		    # that it may not exist (lane < 0), or that it may
138		    # not be within the port:
139		    opn=`expr 4 - ${transfer}`
140		    opn_lane=`expr 3 - \( ${address} % ${port_size} \)`
141		    op3_lane=`expr ${opn_lane} - \( 3 - ${opn} \)`
142
143		    echo ""
144		    echo "  /* [sparc] initiator maximum cycle size: "`expr ${transfer} \* 8`" bits"
145		    echo "     [sparc] initiator A1,A0: ${address_bits}"
146		    echo "     [gen]   responder port size: "`expr ${port_size} \* 8`" bits"
147		    echo "     [gen]   responder port least lane: ${port_pos} (lanes${port_lanes})"
148		    echo "     (code ${transfer}.${address}.${port_size}.${port_pos}, OP3 lane ${op3_lane}): */"
149
150		    # emit the bus router information for each lane:
151		    for lane in 0 1 2 3; do
152			lane_warn=
153
154			# if the sparc expects this byte lane to be connected
155			# to the device at this port size:
156			if test `expr ${lane} \< \( 4 - ${port_size} \)` = 0; then
157
158			    # if this lane is routed by the sparc when
159			    # reading at this transfer size and
160			    # address alignment:
161			    opn=`expr 3 - \( ${lane} - ${op3_lane} \)`
162			    if test `expr ${opn} \> 3` = 0 \
163			       && test `expr ${opn} \< \( 4 - ${transfer} \)` = 0; then
164				lane_read="OP(${opn})"
165
166			    # otherwise this lane isn't routed by the
167			    # sparc when reading at this transfer size
168			    # and address alignment:
169			    else
170				lane_read="IGNORE"
171			    fi
172
173			# otherwise the sparc does not expect this byte
174			# lane to be connected to the device at this
175			# port size:
176			else
177			    lane_read="IGNORE"
178
179			    # if this lane is connected to the device
180			    # anyways, issue a warning:
181			    if test `expr ${lane} \< ${port_pos}` = 0 \
182			       && test `expr ${lane} \< ${port_pos_end}` = 1; then
183				lane_warn=" | TME_BUS_LANE_WARN"
184			    fi
185			fi
186
187			# dispatch on how this lane is routed by the
188			# sparc when writing at this transfer size and
189			# address alignment:
190			case "${transfer_bits}${address_bits}.${lane}" in
191			01??.3) lane_write="OP(3)" ;;
192			01??.2) lane_write="OP(3)" ;;
193			01??.1) lane_write="OP(3)" ;;
194			01??.0) lane_write="OP(3)" ;;
195
196			10?0.3) lane_write="OP(2)" ;;
197			10?0.2) lane_write="OP(3)" ;;
198			10?0.1) lane_write="OP(2)" ;;
199			10?0.0) lane_write="OP(3)" ;;
200
201			10?1.3) lane_write="OP(2)" ;;
202			10?1.2) lane_write="OP(2)" ;;
203			10?1.1) lane_write="OP(3)" ;;
204			10?1.0) lane_write="OP(2)" ;;
205
206			1100.3) lane_write="OP(1)" ;;
207			1100.2) lane_write="OP(2)" ;;
208			1100.1) lane_write="OP(3)" ;;
209			1100.0) lane_write="UNDEF" ;; # XXX this is supposed to be OP0, but we can't deal with that
210
211			1101.3) lane_write="OP(1)" ;;
212			1101.2) lane_write="OP(1)" ;;
213			1101.1) lane_write="OP(2)" ;;
214			1101.0) lane_write="OP(3)" ;;
215
216			1110.3) lane_write="OP(1)" ;;
217			1110.2) lane_write="OP(2)" ;;
218			1110.1) lane_write="OP(1)" ;;
219			1110.0) lane_write="OP(2)" ;;
220
221			1111.3) lane_write="OP(1)" ;;
222			1111.2) lane_write="OP(1)" ;;
223			1111.1) lane_write="OP(2)" ;;
224			1111.0) lane_write="OP(1)" ;;
225
226			0000.3) lane_write="OP(0)" ;;
227			0000.2) lane_write="OP(1)" ;;
228			0000.1) lane_write="OP(2)" ;;
229			0000.0) lane_write="OP(3)" ;;
230
231			0001.3) lane_write="OP(0)" ;;
232			0001.2) lane_write="OP(0)" ;;
233			0001.1) lane_write="OP(1)" ;;
234			0001.0) lane_write="OP(2)" ;;
235
236			0010.3) lane_write="OP(0)" ;;
237			0010.2) lane_write="OP(1)" ;;
238			0010.1) lane_write="OP(0)" ;;
239			0010.0) lane_write="OP(1)" ;;
240
241			0011.3) lane_write="OP(0)" ;;
242			0011.2) lane_write="OP(0)" ;;
243			0011.1) lane_write="OP(1)" ;;
244			0011.0) lane_write="OP(0)" ;;
245
246			esac
247
248			# emit the comment for this lane:
249			echo -n "  /* D"`expr \( \( ${lane} + 1 \) \* 8 \) - 1`"-D"`expr ${lane} \* 8`" */	"
250
251			# if this port size/position combination is
252			# invalid, override everything and abort if
253			# this router entry is ever touched:
254			if test `expr ${port_pos_end} \> 4` = 1; then
255			    echo "TME_BUS_LANE_ABORT,"
256			else
257			    if test $lane_read != "IGNORE"; then
258				if test $lane_read != $lane_write; then
259				    echo "$PROG internal error: code ${transfer}.${address}.${port_size}.${port_pos}, reading $lane_read but writing $lane_write" 1>&2
260				    exit 1
261				fi
262				echo -n "TME_BUS_LANE_ROUTE(SIZ"`expr ${transfer} \* 8`"_$lane_read)"
263			    elif test $lane_write = "UNDEF"; then
264				echo -n "TME_BUS_LANE_UNDEF"
265			    else
266				echo -n "TME_BUS_LANE_ROUTE(SIZ"`expr ${transfer} \* 8`"_$lane_write) | TME_BUS_LANE_ROUTE_WRITE_IGNORE"
267			    fi
268			    echo "${lane_warn},"
269			fi
270		    done
271		done
272	    done
273	done
274   done
275   echo "};"
276fi
277
278cat <<EOF
279#undef SIZ8_OP
280#undef SIZ16_OP
281#undef SIZ24_OP
282#undef SIZ32_OP
283EOF
284
285# done:
286exit 0