Commit | Line | Data |
---|---|---|
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 |