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 @ 97

Last change on this file since 97 was 97, checked in by rosiere, 16 years ago

1) Update Prediction Table : statistics
2) Size instruction address on 30 bits
3) Change Log File
4) Add debug_level in simulation configuration file

  • Property svn:keywords set to Id
File size: 33.8 KB
Line 
1#ifdef SYSTEMC
2/*
3 * $Id: Load_store_unit_function_speculative_load_commit_transition.cpp 97 2008-12-19 15:34:00Z 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            uint32_t index_load = (i + reg_LOAD_QUEUE_CHECK_PRIORITY)%_param->_size_load_queue;
60           
61            if (((_load_queue[index_load]._state == LOAD_QUEUE_WAIT_CHECK)   or
62                 (_load_queue[index_load]._state == LOAD_QUEUE_COMMIT_CHECK) or
63                 (_load_queue[index_load]._state == LOAD_QUEUE_CHECK)) and
64                is_operation_memory_load(_load_queue[index_load]._operation))
65              {
66                log_printf(TRACE,Load_store_unit,FUNCTION,"    * Find a load : %d",index_load);
67
68                nb_check++; // use one port
69
70                // find a entry that it need a check
71
72                Tlsq_ptr_t index_store  = _load_queue[index_load]._store_queue_ptr_write;
73                bool       end_check    = false;
74                bool       change_state = false;
75                bool       next         = false;
76
77                // At the first store queue empty, stop check.
78                // Explication :
79                //  * rename logic keep a empty case in the store queue (also size_store_queue > 1)
80                //  * when a store is out of store queue, also it was in head of re order buffer. Also, they are none previous load.
81
82                log_printf(TRACE,Load_store_unit,FUNCTION,"    * index_store : %d",index_store);
83                if (index_store == reg_STORE_QUEUE_PTR_READ)
84                  {
85                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * index_store == reg_STORE_QUEUE_PTR_READ");
86                    end_check    = true;
87                    change_state = true;
88                  }
89                else
90                  {
91                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * index_store != reg_STORE_QUEUE_PTR_READ");
92
93                    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
94
95                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * index_store : %d",index_store);
96                   
97                    switch (_store_queue[index_store]._state)
98                      {
99                      case STORE_QUEUE_VALID_NO_SPECULATIVE : 
100                      case STORE_QUEUE_COMMIT :
101                      case STORE_QUEUE_VALID_SPECULATIVE :
102                        {
103                         
104                          log_printf(TRACE,Load_store_unit,FUNCTION,"      * store have a valid entry");
105                         
106                          // TODO : MMU - nous considérons que les adresses sont physique
107                          bool test_thread_id = true;
108                         
109                          // Test thread id.
110                          if (_param->_have_port_context_id)
111                            test_thread_id &= (_load_queue[index_load]._context_id    == _store_queue[index_store]._context_id);
112                          if (_param->_have_port_front_end_id)
113                            test_thread_id &= (_load_queue[index_load]._front_end_id  == _store_queue[index_store]._front_end_id);
114                          if (_param->_have_port_ooo_engine_id)
115                            test_thread_id &= (_load_queue[index_load]._ooo_engine_id == _store_queue[index_store]._ooo_engine_id);
116                         
117                          if (test_thread_id)
118                            {
119                              log_printf(TRACE,Load_store_unit,FUNCTION,"        * load and store is the same thread.");
120                              // the load and store are in the same thread. Now, we must test address.
121                              Tdcache_address_t load_addr  = _load_queue [index_load ]._address;
122                              Tdcache_address_t store_addr = _store_queue[index_store]._address;
123                             
124                              log_printf(TRACE,Load_store_unit,FUNCTION,"          * load_addr                     : %.8x.",load_addr );
125                              log_printf(TRACE,Load_store_unit,FUNCTION,"          * store_addr                    : %.8x.",store_addr);
126                              log_printf(TRACE,Load_store_unit,FUNCTION,"          * load_addr  & mask_address_msb : %.8x.",load_addr  & _param->_mask_address_msb);
127                              log_printf(TRACE,Load_store_unit,FUNCTION,"          * store_addr & mask_address_msb : %.8x.",store_addr & _param->_mask_address_msb);
128                              // Test if the both address target the same word
129                              if ((load_addr  & _param->_mask_address_msb) == 
130                                  (store_addr & _param->_mask_address_msb))
131                                {
132                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * address_msb is the same.");
133                                  // all case - [] : store, () : load
134                                  // (1) store_max >= load_max and store_min <= load_min  ...[...(...)...]... Ok - inclusion in store
135                                  // (2) store_min >  load_max                            ...[...]...(...)... Ok - no conflit
136                                  // (3) store_max <  load_min                            ...(...)...[...]... Ok - no conflit
137                                  // (4) store_max <  load_max and store_min >  load_min  ...(...[...]...)... Ko - inclusion in load
138                                  // (5) store_max >= load_max and store_min >  load_min  ...[...(...]...)... Ko - conflit
139                                  // (6) store_max <  load_max and store_min <= load_min  ...(...[...)...]... Ko - conflit
140                                  // but :
141                                  // load in the cache is a word !
142                                  // the mask can be make when the load is commited. Also, the rdata content a full word.
143                                  // the only case is (4)
144                                 
145                                  Tgeneral_data_t load_data  = _load_queue [index_load ]._rdata  ;
146                                  Tgeneral_data_t store_data = _store_queue[index_store]._wdata  ;
147                                 
148                                  log_printf(TRACE,Load_store_unit,FUNCTION,"              * load_data  (init) : %.8x",load_data);
149                                  log_printf(TRACE,Load_store_unit,FUNCTION,"              * store_data (init) : %.8x",store_data);
150                                  uint32_t store_num_byte_min = (store_addr & _param->_mask_address_lsb);
151                                  uint32_t store_num_byte_max = store_num_byte_min+(1<<memory_access(_store_queue[index_store]._operation));
152                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * store_num_byte_min : %d",store_num_byte_min);
153                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * store_num_byte_max : %d",store_num_byte_max);
154                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * check_hit          : %x",_load_queue[index_load]._check_hit);
155                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * check_hit_byte     : %x",_load_queue[index_load]._check_hit_byte);
156                                  // The bypass is checked byte per byte
157                                  for (uint32_t byte=store_num_byte_min; byte<store_num_byte_max; byte ++)
158                                    {
159                                      uint32_t mask  = 1<<byte;
160                                      uint32_t index = byte<<3;
161                                      log_printf(TRACE,Load_store_unit,FUNCTION,"              * byte  : %d",byte);
162                                      log_printf(TRACE,Load_store_unit,FUNCTION,"              * mask  : %d",mask);
163                                      log_printf(TRACE,Load_store_unit,FUNCTION,"              * index : %d",index);
164                                      // Accept the bypass if they had not a previous bypass with an another store
165                                      if ((_load_queue[index_load]._check_hit_byte&mask)==0)
166                                        {
167                                          log_printf(TRACE,Load_store_unit,FUNCTION,"              * bypass !!!");
168                                          log_printf(TRACE,Load_store_unit,FUNCTION,"                * rdata_old : %.8x", load_data);
169                                          load_data = insert<Tdcache_data_t>(load_data, store_data, index+8-1, index);
170                                          _load_queue[index_load]._check_hit_byte |= mask;
171                                          _load_queue[index_load]._check_hit       = 1;
172                                          change_state = true;
173
174                                          log_printf(TRACE,Load_store_unit,FUNCTION,"                * rdata_new : %.8x", load_data);
175                                        }
176                                    }
177
178                                  _load_queue[index_load]._rdata = load_data;
179
180                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * check_hit          : %x",_load_queue[index_load]._check_hit);
181                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * check_hit_byte     : %x",_load_queue[index_load]._check_hit_byte);
182
183                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * mask_end_check     : %x",(-1& _param->_mask_address_lsb));
184                                  // The check is finish if all bit is set
185                                  end_check = (_load_queue[index_load]._check_hit_byte == MASK_CHECK_BYTE_HIT);
186                                }
187                            }
188                         
189                          next = true;
190                          break;
191                        }
192                      case STORE_QUEUE_EMPTY :
193                      case STORE_QUEUE_NO_VALID_NO_SPECULATIVE :
194                        {
195                          log_printf(TRACE,Load_store_unit,FUNCTION,"      * store have an invalid entry");
196                          break;
197                        }
198                      }
199                  }
200
201                if (next)
202                  {
203                    log_printf(TRACE,Load_store_unit,FUNCTION,"              * next");
204//                  if (_load_queue[index_load]._store_queue_ptr_write == 0)
205//                    _load_queue[index_load]._store_queue_ptr_write = _param->_size_store_queue-1;
206//                  else
207//                    _load_queue[index_load]._store_queue_ptr_write --;
208                    _load_queue[index_load]._store_queue_ptr_write = index_store; // because the index store have be decrease
209
210                    // 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"
211                    if (index_store == reg_STORE_QUEUE_PTR_READ)
212                      {
213                        end_check    = true;
214                        change_state = true;
215                      }
216                  }
217
218                if (change_state)
219                  {
220                    log_printf(TRACE,Load_store_unit,FUNCTION,"              * change_state");
221
222                    switch (_load_queue[index_load]._state)
223                      {
224                      case LOAD_QUEUE_WAIT_CHECK   : _load_queue[index_load]._state = LOAD_QUEUE_WAIT  ; break;
225                      case LOAD_QUEUE_COMMIT_CHECK : 
226                        {
227                          if (end_check)
228                            _load_queue[index_load]._state = LOAD_QUEUE_COMMIT; 
229                          else
230                            _load_queue[index_load]._state = LOAD_QUEUE_CHECK;
231                          break;
232                        }
233                      case LOAD_QUEUE_CHECK        : 
234                        {
235                          if (end_check)
236                            _load_queue[index_load]._state     = LOAD_QUEUE_COMMIT;
237                          // check find a bypass. A speculative load have been committed : report a speculation miss.
238                          if (_load_queue[index_load]._check_hit != 0)
239                            {
240                              _load_queue[index_load]._exception = EXCEPTION_MEMORY_MISS_SPECULATION;
241                              _load_queue[index_load]._write_rd  = 1; // write the good result
242                            }
243                         
244                          break;
245                        }
246                      default : break;
247                      }
248                    log_printf(TRACE,Load_store_unit,FUNCTION,"                * new state : %d",_load_queue[index_load]._state);
249                    log_printf(TRACE,Load_store_unit,FUNCTION,"                * exception : %d",_load_queue[index_load]._exception);
250                  }
251              }
252            // else : don't use a port
253          }
254       
255        //================================================================
256        // Interface "MEMORY_IN"
257        //================================================================
258       
259        if ((PORT_READ(in_MEMORY_IN_VAL [internal_MEMORY_IN_PORT]) == 1) and
260            (    internal_MEMORY_IN_ACK  == 1))
261          {
262            // Test operation :
263            //~~~~~~~~~~~~~~~~~
264            //  store  in store_queue
265            //  load   in speculation_access_queue
266            //  others in speculation_access_queue
267
268#ifdef DEBUG_TEST
269            if (PORT_READ(in_MEMORY_IN_TYPE [internal_MEMORY_IN_PORT]) != TYPE_MEMORY)
270              throw ERRORMORPHEO(FUNCTION,"The type is different at 'TYPE_MEMORY'");
271#endif
272            Toperation_t    operation            = PORT_READ(in_MEMORY_IN_OPERATION[internal_MEMORY_IN_PORT]);
273            Tgeneral_data_t address              = (PORT_READ(in_MEMORY_IN_IMMEDIAT[internal_MEMORY_IN_PORT]) +
274                                                    PORT_READ(in_MEMORY_IN_DATA_RA [internal_MEMORY_IN_PORT]));
275            bool            exception_alignement = (mask_memory_access(operation) & address) != 0;
276                                                   
277            if (is_operation_memory_store(operation) == true)
278              {
279                // =======================
280                // ===== STORE_QUEUE =====
281                // =======================
282                // There a two store request type :
283                //   - first is operation with address and data
284                //   - second is the information of re order buffer : the store become not speculative and can access at the data cache
285
286                log_printf(TRACE,Load_store_unit,FUNCTION,"    * store_queue");
287                log_printf(TRACE,Load_store_unit,FUNCTION,"      * PUSH");
288               
289                // Write pointer is define in rename stage :
290                Tlsq_ptr_t           index         = PORT_READ(in_MEMORY_IN_STORE_QUEUE_PTR_WRITE[internal_MEMORY_IN_PORT]);
291                log_printf(TRACE,Load_store_unit,FUNCTION,"      * index         : %d",index);
292               
293                // Need read : state and exception.
294                Tstore_queue_state_t old_state     = _store_queue [index]._state;
295                Tstore_queue_state_t new_state     = old_state;
296                bool                 update_info   = false;
297
298                Texception_t         old_exception = _store_queue [index]._exception;
299                Texception_t         new_exception = old_exception;
300
301                // Compute next state
302                switch (old_state)
303                  {
304                  case STORE_QUEUE_EMPTY                   :
305                    {
306                      if (is_operation_memory_store_head(operation) == true)
307                        {
308                          new_state = STORE_QUEUE_NO_VALID_NO_SPECULATIVE;
309
310                          // test if is a speculation
311                          if (operation == OPERATION_MEMORY_STORE_HEAD_KO)
312                            new_exception = EXCEPTION_MEMORY_MISS_SPECULATION;
313                          else
314                            new_exception = EXCEPTION_MEMORY_NONE;
315                        }
316                      else
317                        {
318                          new_state = STORE_QUEUE_VALID_SPECULATIVE;
319
320                          // Test if have an exception
321                          if (exception_alignement == true)
322                            new_exception = EXCEPTION_MEMORY_ALIGNMENT;
323                          else
324                            new_exception = EXCEPTION_MEMORY_NONE;
325
326                          update_info = true;
327                        }
328                      break;
329                    }
330                  case STORE_QUEUE_NO_VALID_NO_SPECULATIVE :
331                    {
332#ifdef DEBUG_TEST
333                      if (is_operation_memory_store_head(operation) == true)
334                        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."));
335#endif
336                      // Test if have a new exception (priority : miss_speculation)
337                      if ((exception_alignement == true) and (old_exception == EXCEPTION_MEMORY_NONE))
338                        new_exception = EXCEPTION_MEMORY_ALIGNMENT;
339                     
340                      if (new_exception != EXCEPTION_MEMORY_NONE)
341                        new_state = STORE_QUEUE_COMMIT;
342                      else
343                        new_state = STORE_QUEUE_VALID_NO_SPECULATIVE;
344                     
345                      update_info = true;
346                      break;
347                    }
348                  case STORE_QUEUE_VALID_SPECULATIVE       :
349                    {
350#ifdef DEBUG_TEST
351                      if (is_operation_memory_store_head(operation) == false)
352                        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."));
353#endif
354                      if (operation == OPERATION_MEMORY_STORE_HEAD_KO)
355                        new_exception = EXCEPTION_MEMORY_MISS_SPECULATION; // great prioritary
356                     
357                      if (new_exception != EXCEPTION_MEMORY_NONE)
358                        new_state = STORE_QUEUE_COMMIT;
359                      else
360                        new_state = STORE_QUEUE_VALID_NO_SPECULATIVE;
361                     
362                      break;
363                    }
364                  case STORE_QUEUE_VALID_NO_SPECULATIVE    :
365                  case STORE_QUEUE_COMMIT                  :
366                    {
367                      throw ErrorMorpheo("<Load_store_unit::function_speculative_load_commit_transition> Invalid state and operation");
368                    }
369                  }
370
371                _store_queue [index]._state     = new_state;
372                _store_queue [index]._exception = new_exception;
373               
374                if (update_info == true)
375                  {
376                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * Update information");
377
378                    _store_queue [index]._context_id           = (not _param->_have_port_context_id   )?0:PORT_READ(in_MEMORY_IN_CONTEXT_ID   [internal_MEMORY_IN_PORT]);
379                    _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]);
380                    _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]);
381                    _store_queue [index]._packet_id            = (not _param->_have_port_rob_ptr      )?0:PORT_READ(in_MEMORY_IN_PACKET_ID    [internal_MEMORY_IN_PORT]);
382                    _store_queue [index]._operation            = operation;
383                    _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]);
384                    _store_queue [index]._address              = address;
385
386                    // reordering data
387                    _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);
388//                  _store_queue [index]._num_reg_rd           = PORT_READ(in_MEMORY_IN_NUM_REG_RD  [internal_MEMORY_IN_PORT]);
389                  }
390              }
391            else
392              {
393                // ====================================
394                // ===== SPECULATIVE_ACCESS_QUEUE =====
395                // ====================================
396
397                // In speculative access queue, they are many type's request
398                log_printf(TRACE,Load_store_unit,FUNCTION,"    * speculative_access_queue");
399                log_printf(TRACE,Load_store_unit,FUNCTION,"      * PUSH");
400               
401                // Write in reservation station
402                uint32_t     index = _speculative_access_queue_control->push();
403
404                log_printf(TRACE,Load_store_unit,FUNCTION,"      * index : %d", index);
405
406                Texception_t exception;
407
408                if (exception_alignement == true)
409                  exception = EXCEPTION_MEMORY_ALIGNMENT;
410                else
411                  exception = EXCEPTION_MEMORY_NONE;
412                               
413                // if exception, don't access at the cache
414                // NOTE : type "other" (lock, invalidate, flush and sync) can't make an alignement exception (access is equivalent at a 8 bits)
415                _speculative_access_queue [index]._state                = (exception == EXCEPTION_MEMORY_NONE)?SPECULATIVE_ACCESS_QUEUE_WAIT_CACHE:SPECULATIVE_ACCESS_QUEUE_WAIT_LOAD_QUEUE;
416                _speculative_access_queue [index]._context_id           = (not _param->_have_port_context_id   )?0:PORT_READ(in_MEMORY_IN_CONTEXT_ID   [internal_MEMORY_IN_PORT]);
417                _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]);
418                _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]);
419                _speculative_access_queue [index]._packet_id            = (not _param->_have_port_rob_ptr      )?0:PORT_READ(in_MEMORY_IN_PACKET_ID    [internal_MEMORY_IN_PORT]);
420
421                _speculative_access_queue [index]._operation            = operation;
422                _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]);
423                _speculative_access_queue [index]._store_queue_ptr_write= PORT_READ(in_MEMORY_IN_STORE_QUEUE_PTR_WRITE[internal_MEMORY_IN_PORT]);
424                _speculative_access_queue [index]._address              = address;
425                // NOTE : is operation is a load, then they are a result and must write in the register file
426                _speculative_access_queue [index]._write_rd             = is_operation_memory_load(operation);
427                _speculative_access_queue [index]._num_reg_rd           = PORT_READ(in_MEMORY_IN_NUM_REG_RD  [internal_MEMORY_IN_PORT]);
428
429                _speculative_access_queue [index]._exception            = exception;
430               
431                log_printf(TRACE,Load_store_unit,FUNCTION,"      * index         : %d",index);
432              }
433          }
434
435        //================================================================
436        // Interface "MEMORY_OUT"
437        //================================================================
438
439        if ((    internal_MEMORY_OUT_VAL  == 1) and
440            (PORT_READ(in_MEMORY_OUT_ACK[0]) == 1))
441          {
442            log_printf(TRACE,Load_store_unit,FUNCTION,"  * MEMORY_OUT transaction");
443
444            switch (internal_MEMORY_OUT_SELECT_QUEUE)
445              {
446              case SELECT_STORE_QUEUE :
447                {
448                  // =======================
449                  // ===== STORE_QUEUE =====
450                  // =======================
451                 
452                  log_printf(TRACE,Load_store_unit,FUNCTION,"    * store_queue [%d]",reg_STORE_QUEUE_PTR_READ);
453           
454                  // Entry flush and increase the read pointer
455                  _store_queue [reg_STORE_QUEUE_PTR_READ]._state = STORE_QUEUE_EMPTY;
456                 
457                  reg_STORE_QUEUE_PTR_READ = (reg_STORE_QUEUE_PTR_READ+1)%_param->_size_store_queue;
458
459                  break;
460                }
461              case SELECT_LOAD_QUEUE :
462                {
463                  // ======================
464                  // ===== LOAD_QUEUE =====
465                  // ======================
466                 
467                  log_printf(TRACE,Load_store_unit,FUNCTION,"    * load_queue  [%d]",internal_MEMORY_OUT_PTR);
468                 
469                  // Entry flush and increase the read pointer
470                 
471                  _load_queue [internal_MEMORY_OUT_PTR]._state = LOAD_QUEUE_EMPTY;
472                 
473                  // reg_LOAD_QUEUE_PTR_READ = (reg_LOAD_QUEUE_PTR_READ+1)%_param->_size_load_queue;
474
475                  break;
476                }
477              case SELECT_LOAD_QUEUE_SPECULATIVE :
478                {
479                  log_printf(TRACE,Load_store_unit,FUNCTION,"    * load_queue  [%d] (speculative)",internal_MEMORY_OUT_PTR);
480                 
481                  _load_queue [internal_MEMORY_OUT_PTR]._state    = LOAD_QUEUE_CHECK;
482                  // NOTE : a speculative load write in the register file.
483                  // if the speculation is a miss, write_rd is re set at 1.
484                  _load_queue [internal_MEMORY_OUT_PTR]._write_rd = 0;
485                  break;
486                }
487
488                break;
489              }
490          }
491
492        //================================================================
493        // Interface "DCACHE_REQ"
494        //================================================================
495        bool load_queue_push = (_speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._state == SPECULATIVE_ACCESS_QUEUE_WAIT_LOAD_QUEUE);
496
497        if ((    internal_DCACHE_REQ_VAL  == 1) and
498            (PORT_READ(in_DCACHE_REQ_ACK[0]) == 1))
499          {
500            log_printf(TRACE,Load_store_unit,FUNCTION,"  * DCACHE_REQ");
501
502            switch (internal_DCACHE_REQ_SELECT_QUEUE)
503              {
504              case SELECT_STORE_QUEUE :
505                {
506                  // =======================
507                  // ===== STORE_QUEUE =====
508                  // =======================
509                 
510                  // Entry flush and increase the read pointer
511                 
512                  _store_queue [reg_STORE_QUEUE_PTR_READ]._state = STORE_QUEUE_COMMIT;
513
514                  break;
515                }
516              case SELECT_LOAD_QUEUE_SPECULATIVE :
517                {
518                  // =========================================
519                  // ===== SELECT_LOAD_QUEUE_SPECULATIVE =====
520                  // =========================================
521
522                  load_queue_push = true;
523                  break;
524                }
525              case SELECT_LOAD_QUEUE :
526                {
527                  throw ErrorMorpheo(_("Invalid selection"));
528                  break;
529                }
530
531                break;
532              }
533          }
534
535        if (load_queue_push)
536          {
537            Tlsq_ptr_t   ptr_write = _speculative_access_queue[internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._load_queue_ptr_write;
538            Toperation_t operation = _speculative_access_queue[internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._operation;
539            Texception_t exception = _speculative_access_queue[internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._exception;
540            bool         have_exception = (exception != EXCEPTION_MEMORY_NONE);
541           
542           
543            if (have_exception)
544              _load_queue [ptr_write]._state = LOAD_QUEUE_COMMIT;
545            else
546              {
547                if (have_dcache_rsp(operation))
548                  {
549                    // load and synchronisation
550                    if (must_check(operation))
551                      {
552                        // load
553                        _load_queue [ptr_write]._state = LOAD_QUEUE_WAIT_CHECK;
554                      }
555                    else
556                      {
557                        // synchronisation
558                        _load_queue [ptr_write]._state = LOAD_QUEUE_WAIT;
559                      }
560                  }
561                else
562                  {
563                    // lock, prefecth, flush and invalidate
564                    _load_queue [ptr_write]._state = LOAD_QUEUE_COMMIT;
565                  }
566              }
567
568            Tdcache_address_t address        = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._address;
569            Tdcache_address_t address_lsb    = (address & _param->_mask_address_lsb);
570            Tdcache_address_t check_hit_byte = gen_mask_not<Tdcache_address_t>(address_lsb+memory_access(operation)+1,address_lsb);
571            _load_queue [ptr_write]._context_id        = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._context_id           ;
572            _load_queue [ptr_write]._front_end_id      = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._front_end_id         ;
573            _load_queue [ptr_write]._ooo_engine_id     = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._ooo_engine_id        ;
574            _load_queue [ptr_write]._packet_id         = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._packet_id            ;
575            _load_queue [ptr_write]._operation         = operation;
576            _load_queue [ptr_write]._store_queue_ptr_write = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._store_queue_ptr_write;
577            _load_queue [ptr_write]._address           = address;
578            _load_queue [ptr_write]._check_hit_byte    = check_hit_byte;
579            _load_queue [ptr_write]._check_hit         = 0;
580            _load_queue [ptr_write]._shift             = address<<3;
581            _load_queue [ptr_write]._is_load_signed    = is_operation_memory_load_signed(operation);
582            _load_queue [ptr_write]._access_size       = memory_size(operation);
583            // NOTE : if have an exception, must write in register, because a depend instruction wait the load data.
584            _load_queue [ptr_write]._write_rd          = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._write_rd             ;
585           
586            _load_queue [ptr_write]._num_reg_rd        = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._num_reg_rd           ;
587            _load_queue [ptr_write]._exception         = exception;
588            _load_queue [ptr_write]._rdata             = address; // to the exception
589           
590            log_printf(TRACE,Load_store_unit,FUNCTION,"    * speculative_access_queue");
591            log_printf(TRACE,Load_store_unit,FUNCTION,"      * POP[%d]",(*_speculative_access_queue_control)[0]);
592           
593            _speculative_access_queue [(*_speculative_access_queue_control)[0]]._state = SPECULATIVE_ACCESS_QUEUE_EMPTY;
594           
595            _speculative_access_queue_control->pop();
596          }
597
598        //================================================================
599        // Interface "DCACHE_RSP"
600        //================================================================
601        if ((PORT_READ(in_DCACHE_RSP_VAL[0])== 1) and
602            (    internal_DCACHE_RSP_ACK == 1))
603          {
604            log_printf(TRACE,Load_store_unit,FUNCTION,"  * DCACHE_RSP");
605
606            // don't use context_id : because there are one queue for all thread
607            //Tcontext_t      context_id = PORT_READ(in_DCACHE_RSP_CONTEXT_ID[0]);
608            Tpacket_t       packet_id  = PORT_READ(in_DCACHE_RSP_PACKET_ID [0]);
609            Tdcache_data_t  rdata      = PORT_READ(in_DCACHE_RSP_RDATA     [0]);
610            Tdcache_error_t error      = PORT_READ(in_DCACHE_RSP_ERROR     [0]);
611
612            log_printf(TRACE,Load_store_unit,FUNCTION,"    * original packet_id : %d", packet_id);
613           
614            if (DCACHE_RSP_IS_LOAD(packet_id) == 1)
615              {
616                packet_id >>= 1;
617
618                log_printf(TRACE,Load_store_unit,FUNCTION,"    * packet is a LOAD  : %d", packet_id);
619 
620
621#ifdef DEBUG_TEST
622                if (not have_dcache_rsp(_load_queue [packet_id]._operation))
623                  throw ErrorMorpheo(_("Receive of respons, but the corresponding operation don't wait a respons."));
624#endif
625               
626               
627                if (error != DCACHE_ERROR_NONE)
628                  {
629                    log_printf(TRACE,Load_store_unit,FUNCTION,"    * have a bus error !!!");
630
631                    _load_queue [packet_id]._exception = EXCEPTION_MEMORY_BUS_ERROR;
632                    _load_queue [packet_id]._state     = LOAD_QUEUE_COMMIT;
633                  }
634                else
635                  {
636                    log_printf(TRACE,Load_store_unit,FUNCTION,"    * have no bus error.");
637                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * previous state : %d.",_load_queue [packet_id]._state);
638
639                    // FIXME : convention : if bus error, the cache return the fautive address !
640                    // But, the load's address is aligned !
641                    _load_queue [packet_id]._rdata = rdata;
642               
643                    switch (_load_queue [packet_id]._state)
644                      {
645                      case LOAD_QUEUE_WAIT_CHECK : _load_queue [packet_id]._state = LOAD_QUEUE_COMMIT_CHECK; break;
646                      case LOAD_QUEUE_WAIT       : _load_queue [packet_id]._state = LOAD_QUEUE_COMMIT      ; break;
647                      default : throw ErrorMorpheo(_("Illegal state (dcache_rsp).")); break;
648                      }
649                  }
650              }
651            else
652              {
653                log_printf(TRACE,Load_store_unit,FUNCTION,"    * packet is a STORE");
654               
655                // TODO : les stores ne génére pas de réponse sauf quand c'est un bus error !!!
656                throw ERRORMORPHEO(FUNCTION,_("dcache_rsp : no respons to a write. (TODO : manage bus error to the store operation.)"));
657              }
658           
659          }
660       
661        // this register is to manage the priority of check -> Round robin
662        reg_LOAD_QUEUE_CHECK_PRIORITY = (reg_LOAD_QUEUE_CHECK_PRIORITY+1)%_param->_size_load_queue;
663       
664       
665#if defined(DEBUG) and (DEBUG>=DEBUG_TRACE)
666        // ***** dump store queue
667        log_printf(TRACE,Load_store_unit,FUNCTION,"  * Dump STORE_QUEUE");
668        log_printf(TRACE,Load_store_unit,FUNCTION,"    * ptr_read : %d",reg_STORE_QUEUE_PTR_READ);
669       
670        for (uint32_t i=0; i<_param->_size_store_queue; i++)
671          {
672            uint32_t j = (reg_STORE_QUEUE_PTR_READ+i)%_param->_size_store_queue;
673
674            log_printf(TRACE,Load_store_unit,FUNCTION,"    [%.4d] %.4d %.4d %.4d, %.4d, %.4d, %.4d, %.8x %.8x, %.2d, %s",
675                       j,
676                       _store_queue[j]._context_id          ,
677                       _store_queue[j]._front_end_id        ,
678                       _store_queue[j]._ooo_engine_id       ,
679                       _store_queue[j]._packet_id           ,
680                       _store_queue[j]._operation           ,
681                       _store_queue[j]._load_queue_ptr_write,
682                       _store_queue[j]._address             ,
683                       _store_queue[j]._wdata               ,
684                     //_store_queue[j]._write_rd            ,
685                     //_store_queue[j]._num_reg_rd          ,
686                       _store_queue[j]._exception           ,
687                       toString(_store_queue[j]._state).c_str());
688          }
689
690        // ***** dump speculative_access queue
691        log_printf(TRACE,Load_store_unit,FUNCTION,"  * Dump SPECULATIVE_ACCESS_QUEUE");
692       
693        for (uint32_t i=0; i<_param->_size_speculative_access_queue; i++)
694          {
695            uint32_t j = (*_speculative_access_queue_control)[i];
696
697            log_printf(TRACE,Load_store_unit,FUNCTION,"    [%.4d] %.4d %.4d %.4d, %.4d, %.4d, %.4d %.4d, %.8x, %.1d %.6d, %.2d, %s",
698                       j,
699                       _speculative_access_queue[j]._context_id          ,
700                       _speculative_access_queue[j]._front_end_id        ,
701                       _speculative_access_queue[j]._ooo_engine_id       ,
702                       _speculative_access_queue[j]._packet_id           ,
703                       _speculative_access_queue[j]._operation           ,
704                       _speculative_access_queue[j]._load_queue_ptr_write,
705                       _speculative_access_queue[j]._store_queue_ptr_write,
706                       _speculative_access_queue[j]._address             ,
707                       _speculative_access_queue[j]._write_rd            ,
708                       _speculative_access_queue[j]._num_reg_rd          ,
709                       _speculative_access_queue[j]._exception           ,
710                       toString(_speculative_access_queue[j]._state).c_str());
711          }
712
713        // ***** dump load queue
714        log_printf(TRACE,Load_store_unit,FUNCTION,"  * Dump LOAD_QUEUE");
715        log_printf(TRACE,Load_store_unit,FUNCTION,"    * ptr_read_check_priority : %d",reg_LOAD_QUEUE_CHECK_PRIORITY);
716       
717        for (uint32_t i=0; i<_param->_size_load_queue; i++)
718          {
719            uint32_t j = i;
720
721            log_printf(TRACE,Load_store_unit,FUNCTION,"    [%.4d] %.4d %.4d %.4d, %.4d, %.4d, %.4d, %.8x %.1x %.1d %.2d %.1d %.2d, %.8x, %.1d %.6d, %.2d, %s",
722                       j,
723                       _load_queue[j]._context_id          ,
724                       _load_queue[j]._front_end_id        ,
725                       _load_queue[j]._ooo_engine_id       ,
726                       _load_queue[j]._packet_id           ,
727                       _load_queue[j]._operation           ,
728                       _load_queue[j]._store_queue_ptr_write,
729                       _load_queue[j]._address             ,
730                       _load_queue[j]._check_hit_byte      , 
731                       _load_queue[j]._check_hit           ,
732                       _load_queue[j]._shift               ,
733                       _load_queue[j]._is_load_signed      ,
734                       _load_queue[j]._access_size         ,
735                       _load_queue[j]._rdata               ,
736                       _load_queue[j]._write_rd            ,
737                       _load_queue[j]._num_reg_rd          ,
738                       _load_queue[j]._exception           ,
739                       toString(_load_queue[j]._state).c_str());
740          }
741#endif
742       
743#ifdef STATISTICS
744        if (usage_is_set(_usage,USE_STATISTICS))
745          {
746            for (uint32_t i=0; i<_param->_size_store_queue; i++)
747              if (_store_queue[i]._state != STORE_QUEUE_EMPTY)
748                (*_stat_use_store_queue) ++;
749            for (uint32_t i=0; i<_param->_size_speculative_access_queue; i++)
750              if (_speculative_access_queue[i]._state != SPECULATIVE_ACCESS_QUEUE_EMPTY)
751                (*_stat_use_speculative_access_queue) ++;
752            for (uint32_t i=0; i<_param->_size_load_queue; i++)
753              if (_load_queue[i]._state != LOAD_QUEUE_EMPTY)
754                (*_stat_use_load_queue) ++;
755          }
756#endif
757      }
758
759    log_end(Load_store_unit,FUNCTION);
760  };
761
762}; // end namespace load_store_unit
763}; // end namespace execute_unit
764}; // end namespace multi_execute_unit
765}; // end namespace execute_loop
766}; // end namespace multi_execute_loop
767}; // end namespace core
768
769}; // end namespace behavioural
770}; // end namespace morpheo             
771#endif
Note: See TracBrowser for help on using the repository browser.