source: trunk/IPs/systemC/processor/Morpheo/Behavioural/Core/Multi_Execute_loop/Execute_loop/Multi_Execute_unit/Execute_unit/Load_store_unit/src/Load_store_unit_function_speculative_load_commit_transition.cpp @ 104

Last change on this file since 104 was 104, checked in by rosiere, 15 years ago

Fix Bug :
1) Load Store Unit : check big endian
2) Commit unit & RAT : add retire_event interface

  • Property svn:keywords set to Id
File size: 42.4 KB
Line 
1#ifdef SYSTEMC
2/*
3 * $Id: Load_store_unit_function_speculative_load_commit_transition.cpp 104 2009-01-21 21:53:13Z rosiere $
4 *
5 * [ Description ]
6 *
7 */
8
9#include "Behavioural/Core/Multi_Execute_loop/Execute_loop/Multi_Execute_unit/Execute_unit/Load_store_unit/include/Load_store_unit.h"
10
11namespace morpheo                    {
12namespace behavioural {
13namespace core {
14namespace multi_execute_loop {
15namespace execute_loop {
16namespace multi_execute_unit {
17namespace execute_unit {
18namespace load_store_unit {
19
20
21#undef  FUNCTION
22#define FUNCTION "Load_store_unit::function_speculative_load_commit_transition"
23  void Load_store_unit::function_speculative_load_commit_transition (void)
24  {
25    log_begin(Load_store_unit,FUNCTION);
26    log_function(Load_store_unit,FUNCTION,_name.c_str());
27
28    if (PORT_READ(in_NRESET) == 0)
29      {
30        // Reset : clear all queue
31        _speculative_access_queue_control->clear();
32
33        reg_STORE_QUEUE_PTR_READ = 0;
34        reg_LOAD_QUEUE_CHECK_PRIORITY  = 0;
35
36        for (uint32_t i=0; i< _param->_size_store_queue             ; i++)
37          _store_queue              [i]._state = STORE_QUEUE_EMPTY;
38
39        for (uint32_t i=0; i< _param->_size_load_queue              ; i++)
40          _load_queue               [i]._state = LOAD_QUEUE_EMPTY;
41
42        for (uint32_t i=0; i< _param->_size_speculative_access_queue; i++)
43          _speculative_access_queue [i]._state = SPECULATIVE_ACCESS_QUEUE_EMPTY;
44      }
45    else
46      {
47        //================================================================
48        // Interface "PORT_CHECK"
49        //================================================================
50       
51        // Plusieurs moyens de faire la verification de dépendance entre les loads et les stores.
52        //  1) un load ne peut vérifier qu'un store par cycle. Dans ce cas port_check <= size_load_queue
53        //  2) un load tente de vérifier le maximum de store par cycle. Dans ce cas ce n'est pas du pointeur d'écriture qu'il lui faut mais un vecteur de bit indiquant quel store à déjà été testé. De plus il faut un bit indiquant qu'il y a un match mais que ce n'est pas forcément le premier.
54
55        // solution 1)
56        log_printf(TRACE,Load_store_unit,FUNCTION,"  * CHECK");
57        for (uint32_t i=0, nb_check=0; (nb_check<_param->_nb_port_check) and (i<_param->_size_load_queue); i++)
58          {
59            // Get an index from load queue
60            uint32_t index_load = (i + reg_LOAD_QUEUE_CHECK_PRIORITY)%_param->_size_load_queue;
61
62            // Test if this load must ckecked store queue
63            if (((_load_queue[index_load]._state == LOAD_QUEUE_WAIT_CHECK) or
64                 (_load_queue[index_load]._state == LOAD_QUEUE_COMMIT_CHECK) or
65                 (_load_queue[index_load]._state == LOAD_QUEUE_CHECK)) and
66                is_operation_memory_load(_load_queue[index_load]._operation))
67              {
68                log_printf(TRACE,Load_store_unit,FUNCTION,"    * Find a load : %d",index_load);
69
70                nb_check++; // use one port
71
72                // find a entry that it need a check
73                Tlsq_ptr_t index_store  = _load_queue[index_load]._store_queue_ptr_write;
74                // Init variable
75                bool       end_check    = false;
76                bool       change_state = false;
77                bool       next         = false;
78
79                // At the first store queue empty, stop check.
80                // Explication :
81                //  * rename logic keep a empty case in the store queue (also size_store_queue > 1)
82                //  * when a store is out of store queue, also it was in head of re order buffer. Also, they are none previous load.
83
84                log_printf(TRACE,Load_store_unit,FUNCTION,"    * index_store : %d",index_store);
85                if (index_store == reg_STORE_QUEUE_PTR_READ)
86                  {
87                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * index_store == reg_STORE_QUEUE_PTR_READ");
88                    end_check    = true;
89                    change_state = true;
90                  }
91                else
92                  {
93                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * index_store != reg_STORE_QUEUE_PTR_READ");
94
95                    index_store = (index_store-1)%(_param->_size_store_queue); // store_queue_ptr_write target the next slot to write, also the slot is not significatif when the load is renaming
96
97                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * index_store : %d",index_store);
98                   
99                    // switch on store_queue state
100                    switch (_store_queue[index_store]._state)
101                      {
102                      case STORE_QUEUE_VALID_NO_SPECULATIVE : 
103                      case STORE_QUEUE_COMMIT :
104                      case STORE_QUEUE_VALID_SPECULATIVE :
105                        {
106                         
107                          log_printf(TRACE,Load_store_unit,FUNCTION,"      * store have a valid entry");
108                         
109                          // TODO : MMU - nous considérons que les adresses sont physique
110                          bool test_thread_id = true;
111                         
112                          // Test thread id
113                          if (_param->_have_port_context_id)
114                            test_thread_id &= (_load_queue[index_load]._context_id    == _store_queue[index_store]._context_id);
115                          if (_param->_have_port_front_end_id)
116                            test_thread_id &= (_load_queue[index_load]._front_end_id  == _store_queue[index_store]._front_end_id);
117                          if (_param->_have_port_ooo_engine_id)
118                            test_thread_id &= (_load_queue[index_load]._ooo_engine_id == _store_queue[index_store]._ooo_engine_id);
119                         
120                          if (test_thread_id)
121                            {
122                              // the load and store are in the same thread. Now, we must test address.
123
124                              log_printf(TRACE,Load_store_unit,FUNCTION,"        * load and store is the same thread.");
125                              Tdcache_address_t load_addr  = _load_queue [index_load ]._address;
126                              Tdcache_address_t store_addr = _store_queue[index_store]._address;
127                             
128                              log_printf(TRACE,Load_store_unit,FUNCTION,"          * load_addr                     : %.8x.",load_addr );
129                              log_printf(TRACE,Load_store_unit,FUNCTION,"          * store_addr                    : %.8x.",store_addr);
130                              log_printf(TRACE,Load_store_unit,FUNCTION,"          * load_addr  & mask_address_msb : %.8x.",load_addr  & _param->_mask_address_msb);
131                              log_printf(TRACE,Load_store_unit,FUNCTION,"          * store_addr & mask_address_msb : %.8x.",store_addr & _param->_mask_address_msb);
132                              // Test if the both address target the same "word"
133                              if ((load_addr  & _param->_mask_address_msb) == 
134                                  (store_addr & _param->_mask_address_msb))
135                                {
136                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * address_msb is the same.");
137                                  // all case - [] : store, () : load
138                                  // (1) store_max >= load_max and store_min <= load_min  ...[...(...)...]... Ok - inclusion in store
139                                  // (2) store_min >  load_max                            ...[...]...(...)... Ok - no conflit
140                                  // (3) store_max <  load_min                            ...(...)...[...]... Ok - no conflit
141                                  // (4) store_max <  load_max and store_min >  load_min  ...(...[...]...)... Ko - inclusion in load
142                                  // (5) store_max >= load_max and store_min >  load_min  ...[...(...]...)... Ko - conflit
143                                  // (6) store_max <  load_max and store_min <= load_min  ...(...[...)...]... Ko - conflit
144                                  // but :
145                                  // load in the cache is a word !
146                                  // the mask can be make when the load is commited. Also, the rdata content a full word.
147                                  // the only case is (4)
148                                 
149                                  // Read data
150                                  Tgeneral_data_t load_data  = _load_queue [index_load ]._rdata  ;
151                                  Tgeneral_data_t store_data = _store_queue[index_store]._wdata  ;
152                                 
153                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * load_data  (before): 0x%.8x",load_data);
154                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * store_data (before): 0x%.8x",store_data);
155
156                                  uint32_t store_nb_byte     = (1<<memory_access(_store_queue[index_store]._operation));
157
158                                  // Take interval to the store
159                                  uint32_t store_num_byte_min = (store_addr & _param->_mask_address_lsb);
160                                  uint32_t store_num_byte_max = store_num_byte_min+store_nb_byte;
161
162                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * store_num_byte_min : %d",store_num_byte_min);
163                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * store_num_byte_max : %d",store_num_byte_max);
164                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * check_hit          : %x",_load_queue[index_load]._check_hit);
165                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * check_hit_byte     : %x",_load_queue[index_load]._check_hit_byte);
166                                  // The bypass is checked byte per byte
167                                  // Is same endianness : because to change endianness, we must write in special register. Also the pipeline is flushed.
168                                  bool is_big_endian = true;
169
170                                  for (uint32_t num_store_byte=store_num_byte_min; num_store_byte<store_num_byte_max; num_store_byte ++)
171                                    {
172                                      // Make a mask
173                                      uint32_t num_load_byte;
174
175                                      if (is_big_endian)
176                                        {
177                                          // sd 0 : 0 1 2 3 4 5 6 7
178                                          // ld 0 : 0 1 2 3 4 5 6 7 >>  0
179                                          // lw 0 :         0 1 2 3 >>  0 -4
180                                          // lw 4 : 4 5 6 7         >> 32 +4
181                                          // lh 0 :             0 1 >>  0 -6
182                                          // lh 2 :         2 3     >> 16 -2
183                                          // lh 4 :     4 5         >> 32 +2
184                                          // lh 6 : 6 7             >> 48 +6
185                                          // lb 0 :               0 >>  0 -7
186                                          // lb 1 :             1   >>  8 -5
187                                          // lb 2 :           2     >> 16 -3
188                                          // lb 3 :         3       >> 24 -1
189                                          // lb 4 :       4         >> 32 +1
190                                          // lb 5 :     5           >> 40 +3
191                                          // lb 6 :   6             >> 48 +5
192                                          // lb 7 : 7               >> 56 +7
193
194                                          // diff : (store_nb_byte + load_nb_byte) - 2*nb_load_byte*((num_store_byte+1)
195
196                                          // store duplicate = all store access can be see as full size_data store
197                                          uint32_t load_nb_byte = (1<<memory_access(_load_queue [index_load ]._operation));
198
199//                                           log_printf(TRACE,Load_store_unit,FUNCTION,"                * num_store_byte       : %d",num_store_byte);
200//                                           log_printf(TRACE,Load_store_unit,FUNCTION,"                * size_general_data>>3 : %d",(_param->_size_general_data>>3));
201//                                           log_printf(TRACE,Load_store_unit,FUNCTION,"                * load_nb_byte         : %d",load_nb_byte);
202//                                           log_printf(TRACE,Load_store_unit,FUNCTION,"                * x = ((_param->_size_general_data>>3)+load_nb_byte-2*load_nb_byte*(num_store_byte/load_nb_byte+1)) = %d+%d-%d*%d = %d"
203//                                                      , (_param->_size_general_data>>3)
204//                                                      , load_nb_byte
205//                                                      , 2*load_nb_byte
206//                                                      ,((num_store_byte/load_nb_byte)+1)
207//                                                      ,((_param->_size_general_data>>3)+load_nb_byte-2*load_nb_byte*((num_store_byte/load_nb_byte)+1)));
208                                         
209
210                                          num_load_byte =num_store_byte+((_param->_size_general_data>>3)+load_nb_byte-2*load_nb_byte*((num_store_byte/load_nb_byte)+1));
211                                        }
212                                      else
213                                        {
214                                          // sd 0 : 0 1 2 3 4 5 6 7
215                                          // ld 0 : 0 1 2 3 4 5 6 7 >>  0
216                                          // lw 0 :         4 5 6 7 >>  0
217                                          // lw 4 : 0 1 2 3         >> 32
218                                          // lh 0 :             6 7 >>  0
219                                          // lh 2 :         4 5     >> 16
220                                          // lh 4 :     2 3         >> 32
221                                          // lh 6 : 0 1             >> 48
222                                          // lb 0 :               7 >>  0
223                                          // lb 1 :             6   >>  8
224                                          // lb 2 :           5     >> 16
225                                          // lb 3 :         4       >> 24
226                                          // lb 4 :       3         >> 32
227                                          // lb 5 :     2           >> 40
228                                          // lb 6 :   1             >> 48
229                                          // lb 7 : 0               >> 56
230                                         
231                                          num_load_byte = num_store_byte;
232                                        }
233                                     
234                                      uint32_t mask  = 1<<num_load_byte;
235
236                                      log_printf(TRACE,Load_store_unit,FUNCTION,"              * num_store_byte : %d",num_store_byte);
237                                      log_printf(TRACE,Load_store_unit,FUNCTION,"              * num_load_byte  : %d",num_load_byte);
238                                      log_printf(TRACE,Load_store_unit,FUNCTION,"              * mask           : %d",mask);
239
240                                      // Accept the bypass if :
241                                      //   * they have not a previous bypass with an another store
242                                      //   * it's a valid request of load
243                                      if ((_load_queue[index_load]._check_hit_byte&mask)==0)
244                                        {
245                                          // Note : Store is duplicate = all store access can be see as full size_data store
246
247                                          uint32_t num_store_bit_min = num_store_byte<<3; //*8
248//                                         uint32_t num_store_bit_max = num_store_bit_min+8-1;
249                                          uint32_t num_load_bit_min  = num_load_byte <<3; //*8
250                                          uint32_t num_load_bit_max  = num_load_bit_min+8-1;
251
252                                          log_printf(TRACE,Load_store_unit,FUNCTION,"              * bypass !!!");
253//                                        log_printf(TRACE,Load_store_unit,FUNCTION,"              * interval store : [%d:%d]",num_store_bit_max,num_store_bit_min);
254                                          log_printf(TRACE,Load_store_unit,FUNCTION,"              * interval store : [..:%d]",num_store_bit_min);
255                                          log_printf(TRACE,Load_store_unit,FUNCTION,"              * interval load  : [%d:%d]",num_load_bit_max,num_load_bit_min);
256                                          log_printf(TRACE,Load_store_unit,FUNCTION,"                * rdata_old : 0x%.8x", load_data);
257
258                                          load_data = ((((store_data>>num_store_bit_min) & 0xff) << num_load_bit_min) |
259                                                       mask_not<Tdcache_data_t>(load_data,num_load_bit_max,num_load_bit_min));
260
261                                          _load_queue[index_load]._check_hit_byte |= mask;
262                                          _load_queue[index_load]._check_hit       = 1;
263                                          change_state = true;
264
265                                          log_printf(TRACE,Load_store_unit,FUNCTION,"                * rdata_new : 0x%.8x", load_data);
266                                        }
267                                    }
268
269                                  _load_queue[index_load]._rdata = load_data;
270                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * load_data  (after) : 0x%.8x",load_data);
271
272                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * check_hit          : %x",_load_queue[index_load]._check_hit);
273                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * check_hit_byte     : %x",_load_queue[index_load]._check_hit_byte);
274
275                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * mask_end_check     : %x",(-1& _param->_mask_address_lsb));
276                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * mask_check_hit_byte: %x",_param->_mask_check_hit_byte);
277                                  // The check is finish if all bit is set
278                                  end_check = (_load_queue[index_load]._check_hit_byte == _param->_mask_check_hit_byte);
279                                }
280                            }
281                         
282                          next = true;
283                          break;
284                        }
285                      case STORE_QUEUE_EMPTY :
286                      case STORE_QUEUE_NO_VALID_NO_SPECULATIVE :
287                        {
288                          log_printf(TRACE,Load_store_unit,FUNCTION,"      * store have an invalid entry");
289                          break;
290                        }
291                      }
292                  }
293
294                if (next)
295                  {
296                    log_printf(TRACE,Load_store_unit,FUNCTION,"              * next");
297//                  if (_load_queue[index_load]._store_queue_ptr_write == 0)
298//                    _load_queue[index_load]._store_queue_ptr_write = _param->_size_store_queue-1;
299//                  else
300//                    _load_queue[index_load]._store_queue_ptr_write --;
301                    _load_queue[index_load]._store_queue_ptr_write = index_store; // because the index store have be decrease
302
303                    // FIXME : peut n'est pas obliger de faire cette comparaison. Au prochain cycle on le détectera que les pointeur sont égaux. Ceci évitera d'avoir deux comparateurs avec le registre "reg_STORE_QUEUE_PTR_READ"
304                    if (index_store == reg_STORE_QUEUE_PTR_READ)
305                      {
306                        end_check    = true;
307                        change_state = true;
308                      }
309                  }
310
311                if (change_state)
312                  {
313                    log_printf(TRACE,Load_store_unit,FUNCTION,"              * change_state");
314
315                    switch (_load_queue[index_load]._state)
316                      {
317                      case LOAD_QUEUE_WAIT_CHECK   : _load_queue[index_load]._state = LOAD_QUEUE_WAIT  ; break;
318                      case LOAD_QUEUE_COMMIT_CHECK : 
319                        {
320                          if (end_check)
321                            _load_queue[index_load]._state = LOAD_QUEUE_COMMIT; 
322                          else
323                            _load_queue[index_load]._state = LOAD_QUEUE_CHECK;
324                          break;
325                        }
326                      case LOAD_QUEUE_CHECK        : 
327                        {
328                          if (end_check)
329                            _load_queue[index_load]._state     = LOAD_QUEUE_COMMIT;
330                          // check find a bypass. A speculative load have been committed : report a speculation miss.
331                          if (_load_queue[index_load]._check_hit != 0)
332                            {
333                              _load_queue[index_load]._exception = EXCEPTION_MEMORY_MISS_SPECULATION;
334                              _load_queue[index_load]._write_rd  = 1; // write the good result
335                            }
336                         
337                          break;
338                        }
339                      default : break;
340                      }
341                    log_printf(TRACE,Load_store_unit,FUNCTION,"                * new state : %d",_load_queue[index_load]._state);
342                    log_printf(TRACE,Load_store_unit,FUNCTION,"                * exception : %d",_load_queue[index_load]._exception);
343                  }
344              }
345            // else : don't use a port
346          }
347       
348        //================================================================
349        // Interface "MEMORY_IN"
350        //================================================================
351       
352        if ((PORT_READ(in_MEMORY_IN_VAL [internal_MEMORY_IN_PORT]) == 1) and
353            (    internal_MEMORY_IN_ACK  == 1))
354          {
355            log_printf(TRACE,Load_store_unit,FUNCTION,"  * MEMORY_IN [%d]",internal_MEMORY_IN_PORT);
356
357            // Test operation :
358            //~~~~~~~~~~~~~~~~~
359            //  store  in store_queue
360            //  load   in speculation_access_queue
361            //  others in speculation_access_queue
362
363#ifdef DEBUG_TEST
364            if (PORT_READ(in_MEMORY_IN_TYPE [internal_MEMORY_IN_PORT]) != TYPE_MEMORY)
365              throw ERRORMORPHEO(FUNCTION,"The type is different at 'TYPE_MEMORY'");
366#endif
367            Toperation_t    operation            = PORT_READ(in_MEMORY_IN_OPERATION[internal_MEMORY_IN_PORT]);
368            Tgeneral_data_t address              = (PORT_READ(in_MEMORY_IN_IMMEDIAT[internal_MEMORY_IN_PORT]) +
369                                                    PORT_READ(in_MEMORY_IN_DATA_RA [internal_MEMORY_IN_PORT]));
370            bool            exception_alignement = (mask_memory_access(operation) & address) != 0;
371                                                   
372            if (is_operation_memory_store(operation) == true)
373              {
374                // =======================
375                // ===== STORE_QUEUE =====
376                // =======================
377                // There a two store request type :
378                //   - first is operation with address and data
379                //   - second is the information of re order buffer : the store become not speculative and can access at the data cache
380
381                log_printf(TRACE,Load_store_unit,FUNCTION,"    * store_queue");
382                log_printf(TRACE,Load_store_unit,FUNCTION,"      * PUSH");
383               
384                // Write pointer is define in rename stage :
385                Tlsq_ptr_t           index         = PORT_READ(in_MEMORY_IN_STORE_QUEUE_PTR_WRITE[internal_MEMORY_IN_PORT]);
386                log_printf(TRACE,Load_store_unit,FUNCTION,"      * index         : %d",index);
387               
388                // Need read : state and exception.
389                Tstore_queue_state_t old_state     = _store_queue [index]._state;
390                Tstore_queue_state_t new_state     = old_state;
391                bool                 update_info   = false;
392
393                Texception_t         old_exception = _store_queue [index]._exception;
394                Texception_t         new_exception = old_exception;
395
396                // Compute next state
397                switch (old_state)
398                  {
399                  case STORE_QUEUE_EMPTY                   :
400                    {
401                      if (is_operation_memory_store_head(operation) == true)
402                        {
403                          new_state = STORE_QUEUE_NO_VALID_NO_SPECULATIVE;
404
405                          // test if is a speculation
406                          if (operation == OPERATION_MEMORY_STORE_HEAD_KO)
407                            new_exception = EXCEPTION_MEMORY_MISS_SPECULATION;
408                          else
409                            new_exception = EXCEPTION_MEMORY_NONE;
410                        }
411                      else
412                        {
413                          new_state = STORE_QUEUE_VALID_SPECULATIVE;
414
415                          // Test if have an exception
416                          if (exception_alignement == true)
417                            new_exception = EXCEPTION_MEMORY_ALIGNMENT;
418                          else
419                            new_exception = EXCEPTION_MEMORY_NONE;
420
421                          update_info = true;
422                        }
423                      break;
424                    }
425                  case STORE_QUEUE_NO_VALID_NO_SPECULATIVE :
426                    {
427#ifdef DEBUG_TEST
428                      if (is_operation_memory_store_head(operation) == true)
429                        throw ErrorMorpheo(_("Transaction in memory_in's interface, actual state of store_queue is \"STORE_QUEUE_NO_VALID_NO_SPECULATIVE\", also a previous store_head have been receiveid. But this operation is a store_head."));
430#endif
431                      // Test if have a new exception (priority : miss_speculation)
432                      if ((exception_alignement == true) and (old_exception == EXCEPTION_MEMORY_NONE))
433                        new_exception = EXCEPTION_MEMORY_ALIGNMENT;
434                     
435                      if (new_exception != EXCEPTION_MEMORY_NONE)
436                        new_state = STORE_QUEUE_COMMIT;
437                      else
438                        new_state = STORE_QUEUE_VALID_NO_SPECULATIVE;
439                     
440                      update_info = true;
441                      break;
442                    }
443                  case STORE_QUEUE_VALID_SPECULATIVE       :
444                    {
445#ifdef DEBUG_TEST
446                      if (is_operation_memory_store_head(operation) == false)
447                        throw ErrorMorpheo(_("Transaction in memory_in's interface, actual state of store_queue is \"STORE_QUEUE_VALID_SPECULATIVE\", also a previous access with register and address have been receiveid. But this operation is a not store_head."));
448#endif
449                      if (operation == OPERATION_MEMORY_STORE_HEAD_KO)
450                        new_exception = EXCEPTION_MEMORY_MISS_SPECULATION; // great prioritary
451                     
452                      if (new_exception != EXCEPTION_MEMORY_NONE)
453                        new_state = STORE_QUEUE_COMMIT;
454                      else
455                        new_state = STORE_QUEUE_VALID_NO_SPECULATIVE;
456                     
457                      break;
458                    }
459                  case STORE_QUEUE_VALID_NO_SPECULATIVE    :
460                  case STORE_QUEUE_COMMIT                  :
461                    {
462                      throw ErrorMorpheo("<Load_store_unit::function_speculative_load_commit_transition> Invalid state and operation");
463                    }
464                  }
465
466                _store_queue [index]._state     = new_state;
467                _store_queue [index]._exception = new_exception;
468               
469                if (update_info == true)
470                  {
471                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * Update information");
472
473                    _store_queue [index]._context_id           = (not _param->_have_port_context_id   )?0:PORT_READ(in_MEMORY_IN_CONTEXT_ID   [internal_MEMORY_IN_PORT]);
474                    _store_queue [index]._front_end_id         = (not _param->_have_port_front_end_id )?0:PORT_READ(in_MEMORY_IN_FRONT_END_ID [internal_MEMORY_IN_PORT]);
475                    _store_queue [index]._ooo_engine_id        = (not _param->_have_port_ooo_engine_id)?0:PORT_READ(in_MEMORY_IN_OOO_ENGINE_ID[internal_MEMORY_IN_PORT]);
476                    _store_queue [index]._packet_id            = (not _param->_have_port_rob_ptr      )?0:PORT_READ(in_MEMORY_IN_PACKET_ID    [internal_MEMORY_IN_PORT]);
477                    _store_queue [index]._operation            = operation;
478                    _store_queue [index]._load_queue_ptr_write = (not _param->_have_port_load_queue_ptr)?0:PORT_READ(in_MEMORY_IN_LOAD_QUEUE_PTR_WRITE[internal_MEMORY_IN_PORT]);
479                    _store_queue [index]._address              = address;
480
481                    // reordering data
482                    _store_queue [index]._wdata                = duplicate<Tgeneral_data_t>(_param->_size_general_data,PORT_READ(in_MEMORY_IN_DATA_RB[internal_MEMORY_IN_PORT]), memory_size(operation), 0); 
483//                  _store_queue [index]._num_reg_rd           = PORT_READ(in_MEMORY_IN_NUM_REG_RD  [internal_MEMORY_IN_PORT]);
484                  }
485              }
486            else
487              {
488                // ====================================
489                // ===== SPECULATIVE_ACCESS_QUEUE =====
490                // ====================================
491
492                // In speculative access queue, they are many type's request
493                log_printf(TRACE,Load_store_unit,FUNCTION,"    * speculative_access_queue");
494                log_printf(TRACE,Load_store_unit,FUNCTION,"      * PUSH");
495               
496                // Write in reservation station
497                uint32_t     index = _speculative_access_queue_control->push();
498
499                log_printf(TRACE,Load_store_unit,FUNCTION,"      * index : %d", index);
500
501                Texception_t exception;
502
503                if (exception_alignement == true)
504                  exception = EXCEPTION_MEMORY_ALIGNMENT;
505                else
506                  exception = EXCEPTION_MEMORY_NONE;
507                               
508                // if exception, don't access at the cache
509                // NOTE : type "other" (lock, invalidate, flush and sync) can't make an alignement exception (access is equivalent at a 8 bits)
510                _speculative_access_queue [index]._state                = (exception == EXCEPTION_MEMORY_NONE)?SPECULATIVE_ACCESS_QUEUE_WAIT_CACHE:SPECULATIVE_ACCESS_QUEUE_WAIT_LOAD_QUEUE;
511                _speculative_access_queue [index]._context_id           = (not _param->_have_port_context_id   )?0:PORT_READ(in_MEMORY_IN_CONTEXT_ID   [internal_MEMORY_IN_PORT]);
512                _speculative_access_queue [index]._front_end_id         = (not _param->_have_port_front_end_id )?0:PORT_READ(in_MEMORY_IN_FRONT_END_ID [internal_MEMORY_IN_PORT]);
513                _speculative_access_queue [index]._ooo_engine_id        = (not _param->_have_port_ooo_engine_id)?0:PORT_READ(in_MEMORY_IN_OOO_ENGINE_ID[internal_MEMORY_IN_PORT]);
514                _speculative_access_queue [index]._packet_id            = (not _param->_have_port_rob_ptr      )?0:PORT_READ(in_MEMORY_IN_PACKET_ID    [internal_MEMORY_IN_PORT]);
515
516                _speculative_access_queue [index]._operation            = operation;
517                _speculative_access_queue [index]._load_queue_ptr_write = (not _param->_have_port_load_queue_ptr)?0:PORT_READ(in_MEMORY_IN_LOAD_QUEUE_PTR_WRITE[internal_MEMORY_IN_PORT]);
518                _speculative_access_queue [index]._store_queue_ptr_write= PORT_READ(in_MEMORY_IN_STORE_QUEUE_PTR_WRITE[internal_MEMORY_IN_PORT]);
519                _speculative_access_queue [index]._address              = address;
520                // NOTE : is operation is a load, then they are a result and must write in the register file
521                _speculative_access_queue [index]._write_rd             = is_operation_memory_load(operation);
522                _speculative_access_queue [index]._num_reg_rd           = PORT_READ(in_MEMORY_IN_NUM_REG_RD  [internal_MEMORY_IN_PORT]);
523
524                _speculative_access_queue [index]._exception            = exception;
525               
526                log_printf(TRACE,Load_store_unit,FUNCTION,"      * index         : %d",index);
527              }
528          }
529
530        //================================================================
531        // Interface "MEMORY_OUT"
532        //================================================================
533
534        if ((    internal_MEMORY_OUT_VAL  == 1) and
535            (PORT_READ(in_MEMORY_OUT_ACK[0]) == 1))
536          {
537            log_printf(TRACE,Load_store_unit,FUNCTION,"  * MEMORY_OUT[0] transaction");
538
539            switch (internal_MEMORY_OUT_SELECT_QUEUE)
540              {
541              case SELECT_STORE_QUEUE :
542                {
543                  // =======================
544                  // ===== STORE_QUEUE =====
545                  // =======================
546                 
547                  log_printf(TRACE,Load_store_unit,FUNCTION,"    * store_queue [%d]",reg_STORE_QUEUE_PTR_READ);
548           
549                  // Entry flush and increase the read pointer
550                  _store_queue [reg_STORE_QUEUE_PTR_READ]._state = STORE_QUEUE_EMPTY;
551                 
552                  reg_STORE_QUEUE_PTR_READ = (reg_STORE_QUEUE_PTR_READ+1)%_param->_size_store_queue;
553
554                  break;
555                }
556              case SELECT_LOAD_QUEUE :
557                {
558                  // ======================
559                  // ===== LOAD_QUEUE =====
560                  // ======================
561                 
562                  log_printf(TRACE,Load_store_unit,FUNCTION,"    * load_queue  [%d]",internal_MEMORY_OUT_PTR);
563                 
564                  // Entry flush and increase the read pointer
565                 
566                  _load_queue [internal_MEMORY_OUT_PTR]._state = LOAD_QUEUE_EMPTY;
567                 
568                  // reg_LOAD_QUEUE_PTR_READ = (reg_LOAD_QUEUE_PTR_READ+1)%_param->_size_load_queue;
569
570                  break;
571                }
572              case SELECT_LOAD_QUEUE_SPECULATIVE :
573                {
574                  log_printf(TRACE,Load_store_unit,FUNCTION,"    * load_queue  [%d] (speculative)",internal_MEMORY_OUT_PTR);
575                 
576                  _load_queue [internal_MEMORY_OUT_PTR]._state    = LOAD_QUEUE_CHECK;
577                  // NOTE : a speculative load write in the register file.
578                  // if the speculation is a miss, write_rd is re set at 1.
579                  _load_queue [internal_MEMORY_OUT_PTR]._write_rd = 0;
580                  break;
581                }
582
583                break;
584              }
585          }
586
587        //================================================================
588        // Interface "DCACHE_REQ"
589        //================================================================
590        bool load_queue_push = (_speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._state == SPECULATIVE_ACCESS_QUEUE_WAIT_LOAD_QUEUE);
591
592        if ((    internal_DCACHE_REQ_VAL  == 1) and
593            (PORT_READ(in_DCACHE_REQ_ACK[0]) == 1))
594          {
595            log_printf(TRACE,Load_store_unit,FUNCTION,"  * DCACHE_REQ [0]");
596
597            switch (internal_DCACHE_REQ_SELECT_QUEUE)
598              {
599              case SELECT_STORE_QUEUE :
600                {
601                  // =======================
602                  // ===== STORE_QUEUE =====
603                  // =======================
604                 
605                  // Entry flush and increase the read pointer
606                 
607                  _store_queue [reg_STORE_QUEUE_PTR_READ]._state = STORE_QUEUE_COMMIT;
608
609                  break;
610                }
611              case SELECT_LOAD_QUEUE_SPECULATIVE :
612                {
613                  // =========================================
614                  // ===== SELECT_LOAD_QUEUE_SPECULATIVE =====
615                  // =========================================
616
617                  load_queue_push = true;
618                  break;
619                }
620              case SELECT_LOAD_QUEUE :
621                {
622                  throw ErrorMorpheo(_("Invalid selection"));
623                  break;
624                }
625
626                break;
627              }
628          }
629
630        if (load_queue_push)
631          {
632            Tlsq_ptr_t   ptr_write = _speculative_access_queue[internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._load_queue_ptr_write;
633            Toperation_t operation = _speculative_access_queue[internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._operation;
634            Texception_t exception = _speculative_access_queue[internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._exception;
635            bool         have_exception = (exception != EXCEPTION_MEMORY_NONE);
636           
637            if (have_exception)
638              _load_queue [ptr_write]._state = LOAD_QUEUE_COMMIT;
639            else
640              {
641                if (have_dcache_rsp(operation))
642                  {
643                    // load and synchronisation
644                    if (must_check(operation))
645                      {
646                        // load
647                        _load_queue [ptr_write]._state = LOAD_QUEUE_WAIT_CHECK;
648                      }
649                    else
650                      {
651                        // synchronisation
652                        _load_queue [ptr_write]._state = LOAD_QUEUE_WAIT;
653                      }
654                  }
655                else
656                  {
657                    // lock, prefecth, flush and invalidate
658                    _load_queue [ptr_write]._state = LOAD_QUEUE_COMMIT;
659                  }
660              }
661
662            Tdcache_address_t address        = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._address;
663            Tdcache_address_t address_lsb    = (address & _param->_mask_address_lsb);
664            Tdcache_address_t check_hit_byte = gen_mask_not<Tdcache_address_t>(address_lsb+(memory_size(operation)>>3)-1,address_lsb) & _param->_mask_check_hit_byte;
665
666            log_printf(TRACE,Load_store_unit,FUNCTION,"    * address                 : 0x%.8x", address);
667            log_printf(TRACE,Load_store_unit,FUNCTION,"    * address_lsb             : 0x%.8x", address_lsb);
668            log_printf(TRACE,Load_store_unit,FUNCTION,"    * operation               : %d", operation);
669            log_printf(TRACE,Load_store_unit,FUNCTION,"    * memory_size             : %d", memory_size(operation));
670            log_printf(TRACE,Load_store_unit,FUNCTION,"    * check_hit_byte          : 0x%x", check_hit_byte);
671
672            _load_queue [ptr_write]._context_id            = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._context_id;
673            _load_queue [ptr_write]._front_end_id          = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._front_end_id;
674            _load_queue [ptr_write]._ooo_engine_id         = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._ooo_engine_id;
675            _load_queue [ptr_write]._packet_id             = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._packet_id;
676            _load_queue [ptr_write]._operation             = operation;
677            _load_queue [ptr_write]._store_queue_ptr_write = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._store_queue_ptr_write;
678            _load_queue [ptr_write]._address               = address;
679            _load_queue [ptr_write]._check_hit_byte        = check_hit_byte;
680            _load_queue [ptr_write]._check_hit             = 0;
681            _load_queue [ptr_write]._shift                 = address_lsb<<3;// *8
682            _load_queue [ptr_write]._is_load_signed        = is_operation_memory_load_signed(operation);
683            _load_queue [ptr_write]._access_size           = memory_size(operation);
684            // NOTE : if have an exception, must write in register, because a depend instruction wait the load data.
685            _load_queue [ptr_write]._write_rd              = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._write_rd             ;
686           
687            _load_queue [ptr_write]._num_reg_rd            = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._num_reg_rd           ;
688            _load_queue [ptr_write]._exception             = exception;
689            _load_queue [ptr_write]._rdata                 = address; // to the exception
690           
691            log_printf(TRACE,Load_store_unit,FUNCTION,"    * speculative_access_queue");
692            log_printf(TRACE,Load_store_unit,FUNCTION,"      * POP[%d]",(*_speculative_access_queue_control)[0]);
693           
694            _speculative_access_queue [(*_speculative_access_queue_control)[0]]._state = SPECULATIVE_ACCESS_QUEUE_EMPTY;
695           
696            _speculative_access_queue_control->pop();
697          }
698
699        //================================================================
700        // Interface "DCACHE_RSP"
701        //================================================================
702        if ((PORT_READ(in_DCACHE_RSP_VAL[0])== 1) and
703            (    internal_DCACHE_RSP_ACK == 1))
704          {
705            log_printf(TRACE,Load_store_unit,FUNCTION,"  * DCACHE_RSP [0]");
706
707            // don't use context_id : because there are one queue for all thread
708            //Tcontext_t      context_id = PORT_READ(in_DCACHE_RSP_CONTEXT_ID[0]);
709            Tpacket_t       packet_id  = PORT_READ(in_DCACHE_RSP_PACKET_ID [0]);
710            Tdcache_data_t  rdata      = PORT_READ(in_DCACHE_RSP_RDATA     [0]);
711            Tdcache_error_t error      = PORT_READ(in_DCACHE_RSP_ERROR     [0]);
712
713            log_printf(TRACE,Load_store_unit,FUNCTION,"    * original packet_id : %d"  , packet_id);
714            log_printf(TRACE,Load_store_unit,FUNCTION,"    * rdata              : %.8x", rdata);
715            log_printf(TRACE,Load_store_unit,FUNCTION,"    * error              : %d"  , error);
716           
717            if (DCACHE_RSP_IS_LOAD(packet_id) == 1)
718              {
719                packet_id >>= 1;
720
721                log_printf(TRACE,Load_store_unit,FUNCTION,"    * packet is a LOAD  : %d", packet_id);
722 
723
724#ifdef DEBUG_TEST
725                if (not have_dcache_rsp(_load_queue [packet_id]._operation))
726                  throw ErrorMorpheo(_("Receive of respons, but the corresponding operation don't wait a respons."));
727#endif
728
729                Tdcache_data_t data = _load_queue [packet_id]._rdata;
730
731                log_printf(TRACE,Load_store_unit,FUNCTION,"    * data construction");
732                log_printf(TRACE,Load_store_unit,FUNCTION,"      * data from cache     : 0x%.8x",rdata);
733                log_printf(TRACE,Load_store_unit,FUNCTION,"      * data (before)       : 0x%.8x", data);
734                log_printf(TRACE,Load_store_unit,FUNCTION,"      * check_hit_byte      : 0x%x"  ,_load_queue [packet_id]._check_hit_byte);
735                for (uint32_t i=0;i<(_param->_size_general_data>>3)/*8*/; ++i)
736                  // Test if this byte has been checked
737                  if ((_load_queue [packet_id]._check_hit_byte & (1<<i)) == 0)
738                    {
739                      log_printf(TRACE,Load_store_unit,FUNCTION,"      * no previous check ]%d:%d]",(i+1)<<3,i<<3);
740                      data = insert<Tdcache_data_t>(data,rdata,((i+1)<<3)-1,i<<3);
741                    }
742                log_printf(TRACE,Load_store_unit,FUNCTION,"      * data (after)        : 0x%.8x", data);
743               
744                _load_queue [packet_id]._rdata = data;
745               
746                if (error != DCACHE_ERROR_NONE)
747                  {
748                    log_printf(TRACE,Load_store_unit,FUNCTION,"    * have a bus error !!!");
749
750                    _load_queue [packet_id]._exception = EXCEPTION_MEMORY_BUS_ERROR;
751                    _load_queue [packet_id]._state     = LOAD_QUEUE_COMMIT;
752                  }
753                else
754                  {
755                    log_printf(TRACE,Load_store_unit,FUNCTION,"    * have no bus error.");
756                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * previous state : %d.",_load_queue [packet_id]._state);
757
758                    // FIXME : convention : if bus error, the cache return the fautive address !
759                    // But, the load's address is aligned !
760
761                    switch (_load_queue [packet_id]._state)
762                      {
763                      case LOAD_QUEUE_WAIT_CHECK : _load_queue [packet_id]._state = LOAD_QUEUE_COMMIT_CHECK; break;
764                      case LOAD_QUEUE_WAIT       : _load_queue [packet_id]._state = LOAD_QUEUE_COMMIT      ; break;
765                      default : throw ErrorMorpheo(_("Illegal state (dcache_rsp).")); break;
766                      }
767                  }
768              }
769            else
770              {
771                log_printf(TRACE,Load_store_unit,FUNCTION,"    * packet is a STORE");
772               
773                // TODO : les stores ne génére pas de réponse sauf quand c'est un bus error !!!
774                throw ERRORMORPHEO(FUNCTION,_("dcache_rsp : no respons to a write. (TODO : manage bus error to the store operation.)"));
775              }
776           
777          }
778       
779        // this register is to manage the priority of check -> Round robin
780        reg_LOAD_QUEUE_CHECK_PRIORITY = (reg_LOAD_QUEUE_CHECK_PRIORITY+1)%_param->_size_load_queue;
781       
782       
783#if defined(DEBUG) and (DEBUG>=DEBUG_TRACE)
784        // ***** dump store queue
785        log_printf(TRACE,Load_store_unit,FUNCTION,"  * Dump STORE_QUEUE");
786        log_printf(TRACE,Load_store_unit,FUNCTION,"    * ptr_read : %d",reg_STORE_QUEUE_PTR_READ);
787       
788        for (uint32_t i=0; i<_param->_size_store_queue; i++)
789          {
790            uint32_t j = (reg_STORE_QUEUE_PTR_READ+i)%_param->_size_store_queue;
791
792            log_printf(TRACE,Load_store_unit,FUNCTION,"    [%.4d] %.4d %.4d %.4d, %.4d, %.4d, %.4d, %.8x %.8x, %.2d, %s",
793                       j,
794                       _store_queue[j]._context_id          ,
795                       _store_queue[j]._front_end_id        ,
796                       _store_queue[j]._ooo_engine_id       ,
797                       _store_queue[j]._packet_id           ,
798                       _store_queue[j]._operation           ,
799                       _store_queue[j]._load_queue_ptr_write,
800                       _store_queue[j]._address             ,
801                       _store_queue[j]._wdata               ,
802                     //_store_queue[j]._write_rd            ,
803                     //_store_queue[j]._num_reg_rd          ,
804                       _store_queue[j]._exception           ,
805                       toString(_store_queue[j]._state).c_str());
806          }
807
808        // ***** dump speculative_access queue
809        log_printf(TRACE,Load_store_unit,FUNCTION,"  * Dump SPECULATIVE_ACCESS_QUEUE");
810       
811        for (uint32_t i=0; i<_param->_size_speculative_access_queue; i++)
812          {
813            uint32_t j = (*_speculative_access_queue_control)[i];
814
815            log_printf(TRACE,Load_store_unit,FUNCTION,"    [%.4d] %.4d %.4d %.4d, %.4d, %.4d, %.4d %.4d, %.8x, %.1d %.4d, %.2d, %s",
816                       j,
817                       _speculative_access_queue[j]._context_id          ,
818                       _speculative_access_queue[j]._front_end_id        ,
819                       _speculative_access_queue[j]._ooo_engine_id       ,
820                       _speculative_access_queue[j]._packet_id           ,
821                       _speculative_access_queue[j]._operation           ,
822                       _speculative_access_queue[j]._load_queue_ptr_write,
823                       _speculative_access_queue[j]._store_queue_ptr_write,
824                       _speculative_access_queue[j]._address             ,
825                       _speculative_access_queue[j]._write_rd            ,
826                       _speculative_access_queue[j]._num_reg_rd          ,
827                       _speculative_access_queue[j]._exception           ,
828                       toString(_speculative_access_queue[j]._state).c_str());
829          }
830
831        // ***** dump load queue
832        log_printf(TRACE,Load_store_unit,FUNCTION,"  * Dump LOAD_QUEUE");
833        log_printf(TRACE,Load_store_unit,FUNCTION,"    * ptr_read_check_priority : %d",reg_LOAD_QUEUE_CHECK_PRIORITY);
834       
835        for (uint32_t i=0; i<_param->_size_load_queue; i++)
836          {
837            uint32_t j = i;
838
839            log_printf(TRACE,Load_store_unit,FUNCTION,"    [%.4d] %.4d %.4d %.4d, %.4d, %.4d, %.4d, %.8x %.1x %.1d %.2d %.1d %.2d, %.8x, %.1d %.4d, %.2d, %s",
840                       j,
841                       _load_queue[j]._context_id          ,
842                       _load_queue[j]._front_end_id        ,
843                       _load_queue[j]._ooo_engine_id       ,
844                       _load_queue[j]._packet_id           ,
845                       _load_queue[j]._operation           ,
846                       _load_queue[j]._store_queue_ptr_write,
847                       _load_queue[j]._address             ,
848                       _load_queue[j]._check_hit_byte      , 
849                       _load_queue[j]._check_hit           ,
850                       _load_queue[j]._shift               ,
851                       _load_queue[j]._is_load_signed      ,
852                       _load_queue[j]._access_size         ,
853                       _load_queue[j]._rdata               ,
854                       _load_queue[j]._write_rd            ,
855                       _load_queue[j]._num_reg_rd          ,
856                       _load_queue[j]._exception           ,
857                       toString(_load_queue[j]._state).c_str());
858          }
859#endif
860       
861#ifdef STATISTICS
862        if (usage_is_set(_usage,USE_STATISTICS))
863          {
864            for (uint32_t i=0; i<_param->_size_store_queue; i++)
865              if (_store_queue[i]._state != STORE_QUEUE_EMPTY)
866                (*_stat_use_store_queue) ++;
867            for (uint32_t i=0; i<_param->_size_speculative_access_queue; i++)
868              if (_speculative_access_queue[i]._state != SPECULATIVE_ACCESS_QUEUE_EMPTY)
869                (*_stat_use_speculative_access_queue) ++;
870            for (uint32_t i=0; i<_param->_size_load_queue; i++)
871              if (_load_queue[i]._state != LOAD_QUEUE_EMPTY)
872                (*_stat_use_load_queue) ++;
873          }
874#endif
875      }
876
877    log_end(Load_store_unit,FUNCTION);
878  };
879
880}; // end namespace load_store_unit
881}; // end namespace execute_unit
882}; // end namespace multi_execute_unit
883}; // end namespace execute_loop
884}; // end namespace multi_execute_loop
885}; // end namespace core
886
887}; // end namespace behavioural
888}; // end namespace morpheo             
889#endif
Note: See TracBrowser for help on using the repository browser.