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

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

1) Add soc test
2) fix bug (Pc management, Decod and execute, Update prediction ...)

  • Property svn:keywords set to Id
File size: 34.1 KB
Line 
1#ifdef SYSTEMC
2/*
3 * $Id: Load_store_unit_function_speculative_load_commit_transition.cpp 101 2009-01-15 17:19:08Z 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            log_printf(TRACE,Load_store_unit,FUNCTION,"  * MEMORY_IN [%d]",internal_MEMORY_IN_PORT);
263
264            // Test operation :
265            //~~~~~~~~~~~~~~~~~
266            //  store  in store_queue
267            //  load   in speculation_access_queue
268            //  others in speculation_access_queue
269
270#ifdef DEBUG_TEST
271            if (PORT_READ(in_MEMORY_IN_TYPE [internal_MEMORY_IN_PORT]) != TYPE_MEMORY)
272              throw ERRORMORPHEO(FUNCTION,"The type is different at 'TYPE_MEMORY'");
273#endif
274            Toperation_t    operation            = PORT_READ(in_MEMORY_IN_OPERATION[internal_MEMORY_IN_PORT]);
275            Tgeneral_data_t address              = (PORT_READ(in_MEMORY_IN_IMMEDIAT[internal_MEMORY_IN_PORT]) +
276                                                    PORT_READ(in_MEMORY_IN_DATA_RA [internal_MEMORY_IN_PORT]));
277            bool            exception_alignement = (mask_memory_access(operation) & address) != 0;
278                                                   
279            if (is_operation_memory_store(operation) == true)
280              {
281                // =======================
282                // ===== STORE_QUEUE =====
283                // =======================
284                // There a two store request type :
285                //   - first is operation with address and data
286                //   - second is the information of re order buffer : the store become not speculative and can access at the data cache
287
288                log_printf(TRACE,Load_store_unit,FUNCTION,"    * store_queue");
289                log_printf(TRACE,Load_store_unit,FUNCTION,"      * PUSH");
290               
291                // Write pointer is define in rename stage :
292                Tlsq_ptr_t           index         = PORT_READ(in_MEMORY_IN_STORE_QUEUE_PTR_WRITE[internal_MEMORY_IN_PORT]);
293                log_printf(TRACE,Load_store_unit,FUNCTION,"      * index         : %d",index);
294               
295                // Need read : state and exception.
296                Tstore_queue_state_t old_state     = _store_queue [index]._state;
297                Tstore_queue_state_t new_state     = old_state;
298                bool                 update_info   = false;
299
300                Texception_t         old_exception = _store_queue [index]._exception;
301                Texception_t         new_exception = old_exception;
302
303                // Compute next state
304                switch (old_state)
305                  {
306                  case STORE_QUEUE_EMPTY                   :
307                    {
308                      if (is_operation_memory_store_head(operation) == true)
309                        {
310                          new_state = STORE_QUEUE_NO_VALID_NO_SPECULATIVE;
311
312                          // test if is a speculation
313                          if (operation == OPERATION_MEMORY_STORE_HEAD_KO)
314                            new_exception = EXCEPTION_MEMORY_MISS_SPECULATION;
315                          else
316                            new_exception = EXCEPTION_MEMORY_NONE;
317                        }
318                      else
319                        {
320                          new_state = STORE_QUEUE_VALID_SPECULATIVE;
321
322                          // Test if have an exception
323                          if (exception_alignement == true)
324                            new_exception = EXCEPTION_MEMORY_ALIGNMENT;
325                          else
326                            new_exception = EXCEPTION_MEMORY_NONE;
327
328                          update_info = true;
329                        }
330                      break;
331                    }
332                  case STORE_QUEUE_NO_VALID_NO_SPECULATIVE :
333                    {
334#ifdef DEBUG_TEST
335                      if (is_operation_memory_store_head(operation) == true)
336                        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."));
337#endif
338                      // Test if have a new exception (priority : miss_speculation)
339                      if ((exception_alignement == true) and (old_exception == EXCEPTION_MEMORY_NONE))
340                        new_exception = EXCEPTION_MEMORY_ALIGNMENT;
341                     
342                      if (new_exception != EXCEPTION_MEMORY_NONE)
343                        new_state = STORE_QUEUE_COMMIT;
344                      else
345                        new_state = STORE_QUEUE_VALID_NO_SPECULATIVE;
346                     
347                      update_info = true;
348                      break;
349                    }
350                  case STORE_QUEUE_VALID_SPECULATIVE       :
351                    {
352#ifdef DEBUG_TEST
353                      if (is_operation_memory_store_head(operation) == false)
354                        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."));
355#endif
356                      if (operation == OPERATION_MEMORY_STORE_HEAD_KO)
357                        new_exception = EXCEPTION_MEMORY_MISS_SPECULATION; // great prioritary
358                     
359                      if (new_exception != EXCEPTION_MEMORY_NONE)
360                        new_state = STORE_QUEUE_COMMIT;
361                      else
362                        new_state = STORE_QUEUE_VALID_NO_SPECULATIVE;
363                     
364                      break;
365                    }
366                  case STORE_QUEUE_VALID_NO_SPECULATIVE    :
367                  case STORE_QUEUE_COMMIT                  :
368                    {
369                      throw ErrorMorpheo("<Load_store_unit::function_speculative_load_commit_transition> Invalid state and operation");
370                    }
371                  }
372
373                _store_queue [index]._state     = new_state;
374                _store_queue [index]._exception = new_exception;
375               
376                if (update_info == true)
377                  {
378                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * Update information");
379
380                    _store_queue [index]._context_id           = (not _param->_have_port_context_id   )?0:PORT_READ(in_MEMORY_IN_CONTEXT_ID   [internal_MEMORY_IN_PORT]);
381                    _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]);
382                    _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]);
383                    _store_queue [index]._packet_id            = (not _param->_have_port_rob_ptr      )?0:PORT_READ(in_MEMORY_IN_PACKET_ID    [internal_MEMORY_IN_PORT]);
384                    _store_queue [index]._operation            = operation;
385                    _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]);
386                    _store_queue [index]._address              = address;
387
388                    // reordering data
389                    _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);
390//                  _store_queue [index]._num_reg_rd           = PORT_READ(in_MEMORY_IN_NUM_REG_RD  [internal_MEMORY_IN_PORT]);
391                  }
392              }
393            else
394              {
395                // ====================================
396                // ===== SPECULATIVE_ACCESS_QUEUE =====
397                // ====================================
398
399                // In speculative access queue, they are many type's request
400                log_printf(TRACE,Load_store_unit,FUNCTION,"    * speculative_access_queue");
401                log_printf(TRACE,Load_store_unit,FUNCTION,"      * PUSH");
402               
403                // Write in reservation station
404                uint32_t     index = _speculative_access_queue_control->push();
405
406                log_printf(TRACE,Load_store_unit,FUNCTION,"      * index : %d", index);
407
408                Texception_t exception;
409
410                if (exception_alignement == true)
411                  exception = EXCEPTION_MEMORY_ALIGNMENT;
412                else
413                  exception = EXCEPTION_MEMORY_NONE;
414                               
415                // if exception, don't access at the cache
416                // NOTE : type "other" (lock, invalidate, flush and sync) can't make an alignement exception (access is equivalent at a 8 bits)
417                _speculative_access_queue [index]._state                = (exception == EXCEPTION_MEMORY_NONE)?SPECULATIVE_ACCESS_QUEUE_WAIT_CACHE:SPECULATIVE_ACCESS_QUEUE_WAIT_LOAD_QUEUE;
418                _speculative_access_queue [index]._context_id           = (not _param->_have_port_context_id   )?0:PORT_READ(in_MEMORY_IN_CONTEXT_ID   [internal_MEMORY_IN_PORT]);
419                _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]);
420                _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]);
421                _speculative_access_queue [index]._packet_id            = (not _param->_have_port_rob_ptr      )?0:PORT_READ(in_MEMORY_IN_PACKET_ID    [internal_MEMORY_IN_PORT]);
422
423                _speculative_access_queue [index]._operation            = operation;
424                _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]);
425                _speculative_access_queue [index]._store_queue_ptr_write= PORT_READ(in_MEMORY_IN_STORE_QUEUE_PTR_WRITE[internal_MEMORY_IN_PORT]);
426                _speculative_access_queue [index]._address              = address;
427                // NOTE : is operation is a load, then they are a result and must write in the register file
428                _speculative_access_queue [index]._write_rd             = is_operation_memory_load(operation);
429                _speculative_access_queue [index]._num_reg_rd           = PORT_READ(in_MEMORY_IN_NUM_REG_RD  [internal_MEMORY_IN_PORT]);
430
431                _speculative_access_queue [index]._exception            = exception;
432               
433                log_printf(TRACE,Load_store_unit,FUNCTION,"      * index         : %d",index);
434              }
435          }
436
437        //================================================================
438        // Interface "MEMORY_OUT"
439        //================================================================
440
441        if ((    internal_MEMORY_OUT_VAL  == 1) and
442            (PORT_READ(in_MEMORY_OUT_ACK[0]) == 1))
443          {
444            log_printf(TRACE,Load_store_unit,FUNCTION,"  * MEMORY_OUT[0] transaction");
445
446            switch (internal_MEMORY_OUT_SELECT_QUEUE)
447              {
448              case SELECT_STORE_QUEUE :
449                {
450                  // =======================
451                  // ===== STORE_QUEUE =====
452                  // =======================
453                 
454                  log_printf(TRACE,Load_store_unit,FUNCTION,"    * store_queue [%d]",reg_STORE_QUEUE_PTR_READ);
455           
456                  // Entry flush and increase the read pointer
457                  _store_queue [reg_STORE_QUEUE_PTR_READ]._state = STORE_QUEUE_EMPTY;
458                 
459                  reg_STORE_QUEUE_PTR_READ = (reg_STORE_QUEUE_PTR_READ+1)%_param->_size_store_queue;
460
461                  break;
462                }
463              case SELECT_LOAD_QUEUE :
464                {
465                  // ======================
466                  // ===== LOAD_QUEUE =====
467                  // ======================
468                 
469                  log_printf(TRACE,Load_store_unit,FUNCTION,"    * load_queue  [%d]",internal_MEMORY_OUT_PTR);
470                 
471                  // Entry flush and increase the read pointer
472                 
473                  _load_queue [internal_MEMORY_OUT_PTR]._state = LOAD_QUEUE_EMPTY;
474                 
475                  // reg_LOAD_QUEUE_PTR_READ = (reg_LOAD_QUEUE_PTR_READ+1)%_param->_size_load_queue;
476
477                  break;
478                }
479              case SELECT_LOAD_QUEUE_SPECULATIVE :
480                {
481                  log_printf(TRACE,Load_store_unit,FUNCTION,"    * load_queue  [%d] (speculative)",internal_MEMORY_OUT_PTR);
482                 
483                  _load_queue [internal_MEMORY_OUT_PTR]._state    = LOAD_QUEUE_CHECK;
484                  // NOTE : a speculative load write in the register file.
485                  // if the speculation is a miss, write_rd is re set at 1.
486                  _load_queue [internal_MEMORY_OUT_PTR]._write_rd = 0;
487                  break;
488                }
489
490                break;
491              }
492          }
493
494        //================================================================
495        // Interface "DCACHE_REQ"
496        //================================================================
497        bool load_queue_push = (_speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._state == SPECULATIVE_ACCESS_QUEUE_WAIT_LOAD_QUEUE);
498
499        if ((    internal_DCACHE_REQ_VAL  == 1) and
500            (PORT_READ(in_DCACHE_REQ_ACK[0]) == 1))
501          {
502            log_printf(TRACE,Load_store_unit,FUNCTION,"  * DCACHE_REQ[0]");
503
504            switch (internal_DCACHE_REQ_SELECT_QUEUE)
505              {
506              case SELECT_STORE_QUEUE :
507                {
508                  // =======================
509                  // ===== STORE_QUEUE =====
510                  // =======================
511                 
512                  // Entry flush and increase the read pointer
513                 
514                  _store_queue [reg_STORE_QUEUE_PTR_READ]._state = STORE_QUEUE_COMMIT;
515
516                  break;
517                }
518              case SELECT_LOAD_QUEUE_SPECULATIVE :
519                {
520                  // =========================================
521                  // ===== SELECT_LOAD_QUEUE_SPECULATIVE =====
522                  // =========================================
523
524                  load_queue_push = true;
525                  break;
526                }
527              case SELECT_LOAD_QUEUE :
528                {
529                  throw ErrorMorpheo(_("Invalid selection"));
530                  break;
531                }
532
533                break;
534              }
535          }
536
537        if (load_queue_push)
538          {
539            Tlsq_ptr_t   ptr_write = _speculative_access_queue[internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._load_queue_ptr_write;
540            Toperation_t operation = _speculative_access_queue[internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._operation;
541            Texception_t exception = _speculative_access_queue[internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._exception;
542            bool         have_exception = (exception != EXCEPTION_MEMORY_NONE);
543           
544           
545            if (have_exception)
546              _load_queue [ptr_write]._state = LOAD_QUEUE_COMMIT;
547            else
548              {
549                if (have_dcache_rsp(operation))
550                  {
551                    // load and synchronisation
552                    if (must_check(operation))
553                      {
554                        // load
555                        _load_queue [ptr_write]._state = LOAD_QUEUE_WAIT_CHECK;
556                      }
557                    else
558                      {
559                        // synchronisation
560                        _load_queue [ptr_write]._state = LOAD_QUEUE_WAIT;
561                      }
562                  }
563                else
564                  {
565                    // lock, prefecth, flush and invalidate
566                    _load_queue [ptr_write]._state = LOAD_QUEUE_COMMIT;
567                  }
568              }
569
570            Tdcache_address_t address        = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._address;
571            Tdcache_address_t address_lsb    = (address & _param->_mask_address_lsb);
572            Tdcache_address_t check_hit_byte = gen_mask_not<Tdcache_address_t>(address_lsb+memory_access(operation)+1,address_lsb);
573            _load_queue [ptr_write]._context_id        = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._context_id           ;
574            _load_queue [ptr_write]._front_end_id      = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._front_end_id         ;
575            _load_queue [ptr_write]._ooo_engine_id     = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._ooo_engine_id        ;
576            _load_queue [ptr_write]._packet_id         = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._packet_id            ;
577            _load_queue [ptr_write]._operation         = operation;
578            _load_queue [ptr_write]._store_queue_ptr_write = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._store_queue_ptr_write;
579            _load_queue [ptr_write]._address           = address;
580            _load_queue [ptr_write]._check_hit_byte    = check_hit_byte;
581            _load_queue [ptr_write]._check_hit         = 0;
582            _load_queue [ptr_write]._shift             = address<<3;
583            _load_queue [ptr_write]._is_load_signed    = is_operation_memory_load_signed(operation);
584            _load_queue [ptr_write]._access_size       = memory_size(operation);
585            // NOTE : if have an exception, must write in register, because a depend instruction wait the load data.
586            _load_queue [ptr_write]._write_rd          = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._write_rd             ;
587           
588            _load_queue [ptr_write]._num_reg_rd        = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._num_reg_rd           ;
589            _load_queue [ptr_write]._exception         = exception;
590            _load_queue [ptr_write]._rdata             = address; // to the exception
591           
592            log_printf(TRACE,Load_store_unit,FUNCTION,"    * speculative_access_queue");
593            log_printf(TRACE,Load_store_unit,FUNCTION,"      * POP[%d]",(*_speculative_access_queue_control)[0]);
594           
595            _speculative_access_queue [(*_speculative_access_queue_control)[0]]._state = SPECULATIVE_ACCESS_QUEUE_EMPTY;
596           
597            _speculative_access_queue_control->pop();
598          }
599
600        //================================================================
601        // Interface "DCACHE_RSP"
602        //================================================================
603        if ((PORT_READ(in_DCACHE_RSP_VAL[0])== 1) and
604            (    internal_DCACHE_RSP_ACK == 1))
605          {
606            log_printf(TRACE,Load_store_unit,FUNCTION,"  * DCACHE_RSP [0]");
607
608            // don't use context_id : because there are one queue for all thread
609            //Tcontext_t      context_id = PORT_READ(in_DCACHE_RSP_CONTEXT_ID[0]);
610            Tpacket_t       packet_id  = PORT_READ(in_DCACHE_RSP_PACKET_ID [0]);
611            Tdcache_data_t  rdata      = PORT_READ(in_DCACHE_RSP_RDATA     [0]);
612            Tdcache_error_t error      = PORT_READ(in_DCACHE_RSP_ERROR     [0]);
613
614            log_printf(TRACE,Load_store_unit,FUNCTION,"    * original packet_id : %d"  , packet_id);
615            log_printf(TRACE,Load_store_unit,FUNCTION,"    * rdata              : %.8x", rdata);
616            log_printf(TRACE,Load_store_unit,FUNCTION,"    * error              : %d"  , error);
617           
618            if (DCACHE_RSP_IS_LOAD(packet_id) == 1)
619              {
620                packet_id >>= 1;
621
622                log_printf(TRACE,Load_store_unit,FUNCTION,"    * packet is a LOAD  : %d", packet_id);
623 
624
625#ifdef DEBUG_TEST
626                if (not have_dcache_rsp(_load_queue [packet_id]._operation))
627                  throw ErrorMorpheo(_("Receive of respons, but the corresponding operation don't wait a respons."));
628#endif
629
630                _load_queue [packet_id]._rdata = rdata;
631               
632                if (error != DCACHE_ERROR_NONE)
633                  {
634                    log_printf(TRACE,Load_store_unit,FUNCTION,"    * have a bus error !!!");
635
636                    _load_queue [packet_id]._exception = EXCEPTION_MEMORY_BUS_ERROR;
637                    _load_queue [packet_id]._state     = LOAD_QUEUE_COMMIT;
638                  }
639                else
640                  {
641                    log_printf(TRACE,Load_store_unit,FUNCTION,"    * have no bus error.");
642                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * previous state : %d.",_load_queue [packet_id]._state);
643
644                    // FIXME : convention : if bus error, the cache return the fautive address !
645                    // But, the load's address is aligned !
646
647                    switch (_load_queue [packet_id]._state)
648                      {
649                      case LOAD_QUEUE_WAIT_CHECK : _load_queue [packet_id]._state = LOAD_QUEUE_COMMIT_CHECK; break;
650                      case LOAD_QUEUE_WAIT       : _load_queue [packet_id]._state = LOAD_QUEUE_COMMIT      ; break;
651                      default : throw ErrorMorpheo(_("Illegal state (dcache_rsp).")); break;
652                      }
653                  }
654              }
655            else
656              {
657                log_printf(TRACE,Load_store_unit,FUNCTION,"    * packet is a STORE");
658               
659                // TODO : les stores ne génére pas de réponse sauf quand c'est un bus error !!!
660                throw ERRORMORPHEO(FUNCTION,_("dcache_rsp : no respons to a write. (TODO : manage bus error to the store operation.)"));
661              }
662           
663          }
664       
665        // this register is to manage the priority of check -> Round robin
666        reg_LOAD_QUEUE_CHECK_PRIORITY = (reg_LOAD_QUEUE_CHECK_PRIORITY+1)%_param->_size_load_queue;
667       
668       
669#if defined(DEBUG) and (DEBUG>=DEBUG_TRACE)
670        // ***** dump store queue
671        log_printf(TRACE,Load_store_unit,FUNCTION,"  * Dump STORE_QUEUE");
672        log_printf(TRACE,Load_store_unit,FUNCTION,"    * ptr_read : %d",reg_STORE_QUEUE_PTR_READ);
673       
674        for (uint32_t i=0; i<_param->_size_store_queue; i++)
675          {
676            uint32_t j = (reg_STORE_QUEUE_PTR_READ+i)%_param->_size_store_queue;
677
678            log_printf(TRACE,Load_store_unit,FUNCTION,"    [%.4d] %.4d %.4d %.4d, %.4d, %.4d, %.4d, %.8x %.8x, %.2d, %s",
679                       j,
680                       _store_queue[j]._context_id          ,
681                       _store_queue[j]._front_end_id        ,
682                       _store_queue[j]._ooo_engine_id       ,
683                       _store_queue[j]._packet_id           ,
684                       _store_queue[j]._operation           ,
685                       _store_queue[j]._load_queue_ptr_write,
686                       _store_queue[j]._address             ,
687                       _store_queue[j]._wdata               ,
688                     //_store_queue[j]._write_rd            ,
689                     //_store_queue[j]._num_reg_rd          ,
690                       _store_queue[j]._exception           ,
691                       toString(_store_queue[j]._state).c_str());
692          }
693
694        // ***** dump speculative_access queue
695        log_printf(TRACE,Load_store_unit,FUNCTION,"  * Dump SPECULATIVE_ACCESS_QUEUE");
696       
697        for (uint32_t i=0; i<_param->_size_speculative_access_queue; i++)
698          {
699            uint32_t j = (*_speculative_access_queue_control)[i];
700
701            log_printf(TRACE,Load_store_unit,FUNCTION,"    [%.4d] %.4d %.4d %.4d, %.4d, %.4d, %.4d %.4d, %.8x, %.1d %.4d, %.2d, %s",
702                       j,
703                       _speculative_access_queue[j]._context_id          ,
704                       _speculative_access_queue[j]._front_end_id        ,
705                       _speculative_access_queue[j]._ooo_engine_id       ,
706                       _speculative_access_queue[j]._packet_id           ,
707                       _speculative_access_queue[j]._operation           ,
708                       _speculative_access_queue[j]._load_queue_ptr_write,
709                       _speculative_access_queue[j]._store_queue_ptr_write,
710                       _speculative_access_queue[j]._address             ,
711                       _speculative_access_queue[j]._write_rd            ,
712                       _speculative_access_queue[j]._num_reg_rd          ,
713                       _speculative_access_queue[j]._exception           ,
714                       toString(_speculative_access_queue[j]._state).c_str());
715          }
716
717        // ***** dump load queue
718        log_printf(TRACE,Load_store_unit,FUNCTION,"  * Dump LOAD_QUEUE");
719        log_printf(TRACE,Load_store_unit,FUNCTION,"    * ptr_read_check_priority : %d",reg_LOAD_QUEUE_CHECK_PRIORITY);
720       
721        for (uint32_t i=0; i<_param->_size_load_queue; i++)
722          {
723            uint32_t j = i;
724
725            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",
726                       j,
727                       _load_queue[j]._context_id          ,
728                       _load_queue[j]._front_end_id        ,
729                       _load_queue[j]._ooo_engine_id       ,
730                       _load_queue[j]._packet_id           ,
731                       _load_queue[j]._operation           ,
732                       _load_queue[j]._store_queue_ptr_write,
733                       _load_queue[j]._address             ,
734                       _load_queue[j]._check_hit_byte      , 
735                       _load_queue[j]._check_hit           ,
736                       _load_queue[j]._shift               ,
737                       _load_queue[j]._is_load_signed      ,
738                       _load_queue[j]._access_size         ,
739                       _load_queue[j]._rdata               ,
740                       _load_queue[j]._write_rd            ,
741                       _load_queue[j]._num_reg_rd          ,
742                       _load_queue[j]._exception           ,
743                       toString(_load_queue[j]._state).c_str());
744          }
745#endif
746       
747#ifdef STATISTICS
748        if (usage_is_set(_usage,USE_STATISTICS))
749          {
750            for (uint32_t i=0; i<_param->_size_store_queue; i++)
751              if (_store_queue[i]._state != STORE_QUEUE_EMPTY)
752                (*_stat_use_store_queue) ++;
753            for (uint32_t i=0; i<_param->_size_speculative_access_queue; i++)
754              if (_speculative_access_queue[i]._state != SPECULATIVE_ACCESS_QUEUE_EMPTY)
755                (*_stat_use_speculative_access_queue) ++;
756            for (uint32_t i=0; i<_param->_size_load_queue; i++)
757              if (_load_queue[i]._state != LOAD_QUEUE_EMPTY)
758                (*_stat_use_load_queue) ++;
759          }
760#endif
761      }
762
763    log_end(Load_store_unit,FUNCTION);
764  };
765
766}; // end namespace load_store_unit
767}; // end namespace execute_unit
768}; // end namespace multi_execute_unit
769}; // end namespace execute_loop
770}; // end namespace multi_execute_loop
771}; // end namespace core
772
773}; // end namespace behavioural
774}; // end namespace morpheo             
775#endif
Note: See TracBrowser for help on using the repository browser.