Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / model / vendor / TLM-2006-11-29 / tlm / tlm_bus / tlm_byte_enable.h
CommitLineData
86530b38
AT
1/*****************************************************************************
2
3 The following code is derived, directly or indirectly, from the SystemC
4 source code Copyright (c) 1996-2004 by all Contributors.
5 All Rights reserved.
6
7 The contents of this file are subject to the restrictions and limitations
8 set forth in the SystemC Open Source License Version 2.4 (the "License");
9 You may not use this file except in compliance with such restrictions and
10 limitations. You may obtain instructions on how to receive a copy of the
11 License at http://www.systemc.org/. Software distributed by Contributors
12 under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
13 ANY KIND, either express or implied. See the License for the specific
14 language governing rights and limitations under the License.
15
16 *****************************************************************************/
17
18
19#ifndef _TLM_BYTE_ENABLE_H_
20#define _TLM_BYTE_ENABLE_H_
21
22/*------------------------------------------------------------------------------
23 * Includes
24 *----------------------------------------------------------------------------*/
25#include "tlm_bus/tlm_type.h"
26
27
28 /*------------------------------------------------------------------------------
29 * Constants
30 *----------------------------------------------------------------------------*/
31
32 /** \defgroup byte_enable_values Predefined byte_enable values
33 * Some predefined byte_enable values (up to 64 bits data)
34 *@{
35 **/
36
37 /** This byte_enable value selects all bytes.
38 * This value is used as default value.
39 **/
40 static const unsigned int NO_BE = 0xffffffff;
41
42 static const unsigned int BYTE_LANE_0 = 0x1; ///< This byte_enable value selects the byte at word address + 0
43 static const unsigned int BYTE_LANE_1 = 0x2; ///< This byte_enable value selects the byte at word address + 1
44 static const unsigned int BYTE_LANE_2 = 0x4; ///< This byte_enable value selects the byte at word address + 2
45 static const unsigned int BYTE_LANE_3 = 0x8; ///< This byte_enable value selects the byte at word address + 3
46 static const unsigned int BYTE_LANE_4 = 0x10; ///< This byte_enable value selects the byte at word address + 4
47 static const unsigned int BYTE_LANE_5 = 0x20; ///< This byte_enable value selects the byte at word address + 5
48 static const unsigned int BYTE_LANE_6 = 0x40; ///< This byte_enable value selects the byte at word address + 6
49 static const unsigned int BYTE_LANE_7 = 0x80; ///< This byte_enable value selects the byte at word address + 7
50
51 static const unsigned int SHORT_LANE_0 = 0x3; ///< This byte_enable value selects the halfword (short) at word address + 0
52 static const unsigned int SHORT_LANE_1 = 0xc; ///< This byte_enable value selects the halfword (short) at word address + 2
53 static const unsigned int SHORT_LANE_2 = 0x30; ///< This byte_enable value selects the halfword (short) at word address + 4
54 static const unsigned int SHORT_LANE_3 = 0xc0; ///< This byte_enable value selects the halfword (short) at word address + 6
55
56 static const unsigned int WORD_LANE_0 = 0x0f; ///< This byte_enable value selects the word at word address + 0
57 static const unsigned int WORD_LANE_1 = 0xf0; ///< This byte_enable value selects the word at word address + 4
58 /* @} */
59
60
61 /*------------------------------------------------------------------------------
62 * Functions
63 *----------------------------------------------------------------------------*/
64
65 /** \defgroup byte_enable_functions Byte enable related template functions
66 * \n
67 * \n The tlm protocol provides the following semantic for the byte enable capability.
68 * Consequently, all the IP models that are compatible with the tlm standard
69 * should conform to the byte enable approach as described below, to ensure a
70 * correct interaction between models when integrated in system platforms.
71 * \n
72 * \n The rule to conform with is as follows (example with 64 bits data):
73 - A byte is identified thanks to its address offset with respect to the word address, e.g:
74 <table>
75 <tr><td>byte location</td> <td> byte_enable value in TLM mode</td></tr>
76 <tr><td>word_address + 0ffset 0</td><td>0x1</td></tr>
77 <tr><td>word_address + 0ffset 1</td><td>0x2</td></tr>
78 <tr><td>word_address + 0ffset 2</td><td>0x4</td></tr>
79 <tr><td>word_address + 0ffset 3</td><td>0x8</td></tr>
80 <tr><td>word_address + 0ffset 4</td><td>0x10</td></tr>
81 <tr><td>word_address + 0ffset 5</td><td>0x20</td></tr>
82 <tr><td>word_address + 0ffset 6</td><td>0x40</td></tr>
83 <tr><td>word_address + 0ffset 7</td><td>0x80</td></tr>
84 </table>
85
86 A bit in the byte_enable denotes a valid byte. All combinations are allowed, e.g. byte_enable = 0x9. In
87 this case, the byte_enable attribute can interpreted as a byte mask.
88
89
90 For the simulated endianness:
91 <table>
92 <tr><td>Endianness</td><td>byte_enable value</td><td>Corresponding address offset</td><td>significance</td></tr>
93 <tr><td> Little endian</td> <td> 0x1 </td><td> address+0 </td><td> Less Significant Byte </td></tr>
94 <tr> <td> </td> <td> 0x2 </td><td> address+1 </td><td> </td></tr>
95 <tr> <td> </td> <td> 0x4 </td><td> address+2 </td><td> </td></tr>
96 <tr> <td> </td> <td> 0x8 </td><td> address+3 </td><td> </td></tr>
97 <tr> <td> </td> <td> 0x10 </td><td> address+4 </td><td> </td></tr>
98 <tr> <td> </td> <td> 0x20 </td><td> address+5 </td><td> </td></tr>
99 <tr> <td> </td> <td> 0x40 </td><td> address+6 </td><td> </td></tr>
100 <tr> <td> </td> <td> 0x80 </td><td> address+7 </td><td> Most Significant Byte</td></tr>
101
102 <tr><td> Big endian </td> <td> 0x1 </td><td> address+0 </td><td> Most Significant Byte </td></tr>
103 <tr> <td> </td> <td> 0x2 </td><td> address+1 </td><td> </td></tr>
104 <tr> <td> </td> <td> 0x4 </td><td> address+2 </td><td> </td></tr>
105 <tr> <td> </td> <td> 0x8 </td><td> address+3 </td><td> </td></tr>
106 <tr> <td> </td> <td> 0x10 </td><td> address+4 </td><td> </td></tr>
107 <tr> <td> </td> <td> 0x20 </td><td> address+5 </td><td> </td></tr>
108 <tr> <td> </td> <td> 0x40 </td><td> address+6 </td><td> </td></tr>
109 <tr> <td> </td> <td> 0x80 </td><td> address+7 </td><td> Less Significant Byte</td></tr>
110
111 </table>
112 - As a consequence, master modules set the byte_enable value according to the required byte address offset.
113 Slave modules that are byte-addressable must be aware of the simulated endianness, and
114 should be independent on the workstation endianness.
115 \n The association byte_enable/byte significance is done according to the simulated endianness.
116 The master might re-align the extracted byte on the LSB according to the simulated endianness if needed
117 (for word-based applications and byte usage).
118
119 Note that for performance reasons, effective storage in the slave module might be done in the workstation endianness.
120
121 Static template functions define the predefined legal values for the byte_enable
122 attribute for the TLM protocol
123 - be_word, be_short, be_byte
124
125 \n These template functions on addresss and data type calculate the byte enable value using the
126 address as entry parameter
127
128 * @{
129 **/
130
131 /// Calculates the minimum "no byte enable" value for specified data type
132 template <typename DATA>
133 inline unsigned int get_no_be() {
134 return( (BYTE_LANE_0 << get_nb_byte<DATA>()) - 1);
135 }
136
137 /// Returns true if the given byte enable value is "no byte_enable" for the datatype bit length
138 template <typename DATA>
139 inline unsigned int is_no_be(unsigned int byte_enable) {
140 unsigned int no_be = get_no_be<DATA>();
141 return((byte_enable & no_be) == no_be);
142 }
143
144
145 /// Calculates the byte_enable for BYTE
146 template <typename ADDRESS, typename DATA>
147 inline unsigned int be_byte(ADDRESS addr) {
148 return(BYTE_LANE_0 << ((addr) & (get_nb_byte<DATA>() - 1)));
149 }
150
151 /// Calculates the byte_enable for SHORT
152 template <typename ADDRESS, typename DATA>
153 inline unsigned int be_short(ADDRESS addr) {
154 return(SHORT_LANE_0 << ((addr) & (get_nb_byte<DATA>() - 2)));
155 }
156
157 /// Calculates the byte_enable for WORD
158 template <typename ADDRESS, typename DATA>
159 inline unsigned int be_word(ADDRESS addr) {
160 return(WORD_LANE_0 << ((addr) & (get_nb_byte<DATA>() - 4)));
161 }
162
163 // Calculates the byte_enable for BYTE (data type with WIDTH bit length)
164 template <typename ADDRESS,int WIDTH>
165 inline unsigned int be_byte(ADDRESS addr) {
166 return(BYTE_LANE_0 << ((addr) & (WIDTH/8 - 1)));
167 }
168
169 // Calculates the byte_enable for SHORT (data type with WIDTH bit length)
170 template <typename ADDRESS, int WIDTH>
171 inline unsigned int be_short(ADDRESS addr) {
172 return(SHORT_LANE_0 << ((addr) & (WIDTH/8 - 2)));
173 }
174
175 // Calculates the byte_enable for WORD (data type with WIDTH bit length)
176 template <typename ADDRESS,int WIDTH>
177 inline unsigned int be_word(ADDRESS addr) {
178 return(WORD_LANE_0 << ((addr) & (WIDTH/8 - 4)));
179 }
180
181 /// Calculates the byte_enable for BYTE, SHORT and WORD using the size parameter (byte number)
182 template <typename ADDRESS,typename DATA>
183 inline unsigned int get_be(ADDRESS addr,unsigned int size) {
184 if (size != get_nb_byte<DATA>()) {
185 switch(size) {
186 case 1:
187 return(BYTE_LANE_0 << ((addr) & (get_nb_byte<DATA>() - 1)));
188 break;
189 case 2:
190 return(SHORT_LANE_0 << ((addr) & (get_nb_byte<DATA>() - 2)));
191 break;
192 case 4:
193 return(WORD_LANE_0 << ((addr) & (get_nb_byte<DATA>() - 4)));
194 break;
195 default:
196 fprintf(stderr,"ERROR\t\tCan't compute byte_enable on a word with %d bytes\n",size);
197 }
198 }
199 return(NO_BE);
200 }
201
202
203 /* @} */
204
205
206 /** \defgroup alignment_functions Data alignment related template functions
207 * Template functions on addresss and data type which return aligned sub word data depending on
208 * the given address and simulated endianness
209 * The first set of functions (align_xxx_to_tlm) is used to shift the data according to
210 * the endianness and the address before send it using the tlm_bus_request
211 * The second set of functions (align_xxx_from_tlm) is used to shift back the data according to
212 * the endianness and the address after receiving it from the tlm_bus_response
213
214 * @{
215 **/
216 /// Returns aligned byte value to write on tlm protocol
217 template <typename ADDRESS, typename DATA>
218 inline DATA align_byte_to_tlm(const ADDRESS& address,const DATA& data,const tlm_endianness endian) {
219 ADDRESS addr_mask = (ADDRESS)(get_nb_byte<DATA>() - 1);
220 DATA tmp = data & 0xff;
221 return(((endian==TLM_BIG_ENDIAN)?(tmp << ((~(address & addr_mask)) & addr_mask)*8):(tmp << (address & addr_mask)*8)));
222 }
223
224 /// Returns aligned short to write on TLM protocol
225 template <typename ADDRESS, typename DATA>
226 inline DATA align_short_to_tlm(const ADDRESS& address,const DATA& data,const tlm_endianness endian) {
227 ADDRESS addr_mask = (ADDRESS)(get_nb_byte<DATA>() - 2);
228 DATA tmp = data & 0xffff;
229 return(((endian==TLM_BIG_ENDIAN)?(tmp << ((~(address & addr_mask)) & addr_mask)*8):(tmp << (address & addr_mask)*8)));
230 }
231
232 /// Returns aligned word read from TLM protocol
233 template <typename ADDRESS, typename DATA>
234 inline DATA align_word_to_tlm(const ADDRESS& address,const DATA& data,const tlm_endianness endian) {
235 ADDRESS addr_mask = (ADDRESS)(get_nb_byte<DATA>() - 4);
236 DATA tmp = data & 0xffffffff;
237 return (((endian==TLM_BIG_ENDIAN)?(tmp << ((~(address & addr_mask)) & addr_mask)*8):(tmp << (address & addr_mask)*8)));
238 }
239
240 /// Aligns the byte value read from TLM protocol
241 template <typename ADDRESS, typename DATA>
242 inline DATA align_byte_from_tlm(const ADDRESS& address,const DATA& data,const tlm_endianness endian) {
243 ADDRESS addr_mask = (ADDRESS)(get_nb_byte<DATA>() - 1);
244 DATA tmp = ((endian==TLM_BIG_ENDIAN)?data >> ((~(address & addr_mask)) & addr_mask)*8:data >> (address & addr_mask)*8);
245 return((tmp & 0xff));
246 }
247
248 /// Aligns the short value read from TLM protocol
249 template <typename ADDRESS, typename DATA>
250 inline DATA align_short_from_tlm(const ADDRESS& address,const DATA& data,const tlm_endianness endian) {
251 ADDRESS addr_mask = (ADDRESS)(get_nb_byte<DATA>() - 2);
252 DATA tmp = ((endian==TLM_BIG_ENDIAN)?data >> ((~(address & addr_mask)) & addr_mask)*8:data >> (address & addr_mask)*8);
253 return((tmp & 0xffff));
254 }
255
256 /// Aligns the word value read from TLM protocol
257 template <typename ADDRESS, typename DATA>
258 inline DATA align_word_from_tlm(const ADDRESS& address,const DATA& data,const tlm_endianness endian) {
259 ADDRESS addr_mask = (ADDRESS)(get_nb_byte<DATA>() - 4);
260 DATA tmp = ((endian==TLM_BIG_ENDIAN)?data >> ((~(address & addr_mask)) & addr_mask)*8:data >> (address & addr_mask)*8);
261 return((tmp & 0xffffffff));
262 }
263
264 /* @} */
265
266#endif /* _TLM_BYTE_ENABLE_H_ */
267
268