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

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

Almost complete design
with Test and test platform

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