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

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

1) Correct bug in link two signal
2) Fix error detected with valgrind
3) modif distexe script

  • Property svn:keywords set to Id
File size: 65.5 KB
Line 
1#ifdef SYSTEMC
2/*
3 * $Id: Load_store_unit_function_speculative_load_commit_transition.cpp 128 2009-06-26 08:43:23Z 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#include "Behavioural/include/Identification.h"
11
12namespace morpheo                    {
13namespace behavioural {
14namespace core {
15namespace multi_execute_loop {
16namespace execute_loop {
17namespace multi_execute_unit {
18namespace execute_unit {
19namespace load_store_unit {
20
21template <typename T>
22T swapBytes (T data, uint32_t size_data, uint32_t size_access)
23{
24  uint64_t x = static_cast<uint64_t>(data);
25
26//   switch (size_data)
27//     {
28//     case 2 : // 16 bits
29//       {
30//         switch (size_access)
31//           {
32//           case 2 :
33//             {
34//               x = ((((x>> 8)&0xff) <<  0) |
35//                    (((x>> 0)&0xff) <<  8) );
36//               break;
37//             }
38//           default :
39//             {
40//               break;
41//             }
42//           }
43//         break;
44//       }
45//     case 4 : // 32 bits
46//       {
47//         switch (size_access)
48//           {
49//           case 2 :
50//             {
51//               x = ((((x>> 8)&0xff) <<  0) |
52//                    (((x>> 0)&0xff) <<  8) |
53//                    (((x>>24)&0xff) << 16) |
54//                    (((x>>16)&0xff) << 24) );
55//               break;
56//             }
57//           case 4 :
58//             {
59//               x = ((((x>>24)&0xff) <<  0) |
60//                    (((x>>16)&0xff) <<  8) |
61//                    (((x>> 8)&0xff) << 16) |
62//                    (((x>> 0)&0xff) << 24) );
63//               break;
64//             }
65//           default :
66//             {
67//               break;
68//             }
69//           }
70//         break;
71//       }
72//     case 8 : // 64 bits
73//       {
74//         switch (size_access)
75//           {
76//           case 2 :
77//             {
78//               x = ((((x>> 8)&0xff) <<  0) |
79//                    (((x>> 0)&0xff) <<  8) |
80//                    (((x>>24)&0xff) << 16) |
81//                    (((x>>16)&0xff) << 24) |
82//                    (((x>>40)&0xff) << 32) |
83//                    (((x>>32)&0xff) << 40) |
84//                    (((x>>56)&0xff) << 48) |
85//                    (((x>>48)&0xff) << 56) );
86//               break;
87//             }
88//           case 4 :
89//             {
90//               x = ((((x>>24)&0xff) <<  0) |
91//                    (((x>>16)&0xff) <<  8) |
92//                    (((x>> 8)&0xff) << 16) |
93//                    (((x>> 0)&0xff) << 24) |
94//                    (((x>>56)&0xff) << 32) |
95//                    (((x>>48)&0xff) << 40) |
96//                    (((x>>40)&0xff) << 48) |
97//                    (((x>>32)&0xff) << 56) );
98//               break;
99//             }
100//           case 8 :
101//             {
102//               x = ((((x>>56)&0xff) <<  0) |
103//                    (((x>>48)&0xff) <<  8) |
104//                    (((x>>40)&0xff) << 16) |
105//                    (((x>>32)&0xff) << 24) |
106//                    (((x>>24)&0xff) << 32) |
107//                    (((x>>16)&0xff) << 40) |
108//                    (((x>> 8)&0xff) << 48) |
109//                    (((x>> 0)&0xff) << 56) );
110//               break;
111//             }
112//           default :
113//             {
114//               break;
115//             }
116//           }
117//         break;
118//       }
119//     default :
120//       {
121//         break;
122//       }
123//     }
124
125
126  uint64_t y=0;
127
128  for (uint32_t i=0; i<size_data; i+=size_access)
129    {
130      uint32_t offset = i<<3;
131
132      switch (size_access)
133        {
134        case 1 :
135          {
136            y = x;
137            break;
138          }
139        case 2 : 
140          {
141            y |= ((((x>>( 8+offset))&0xff) << ( 0+offset)) |
142                  (((x>>( 0+offset))&0xff) << ( 8+offset)) );
143            break;
144          }
145        case 4 : 
146          {
147            y |= ((((x>>(24+offset))&0xff) << ( 0+offset)) |
148                  (((x>>(16+offset))&0xff) << ( 8+offset)) |
149                  (((x>>( 8+offset))&0xff) << (16+offset)) |
150                  (((x>>( 0+offset))&0xff) << (24+offset)) );
151            break;
152          }
153        case 8 : 
154          {
155            y |= ((((x>>(56+offset))&0xff) << ( 0+offset)) |
156                  (((x>>(48+offset))&0xff) << ( 8+offset)) |
157                  (((x>>(40+offset))&0xff) << (16+offset)) |
158                  (((x>>(32+offset))&0xff) << (24+offset)) |
159                  (((x>>(24+offset))&0xff) << (32+offset)) |
160                  (((x>>(16+offset))&0xff) << (40+offset)) |
161                  (((x>>( 8+offset))&0xff) << (48+offset)) |
162                  (((x>>( 0+offset))&0xff) << (56+offset)) );
163            break;
164          }
165        default :
166            {
167              break;
168            }
169        }
170    }
171
172  return static_cast<T>(y);
173}
174
175template <typename T>
176T swapBits (T data, uint32_t size_data, uint32_t size_access)
177{
178  uint8_t x = static_cast<uint8_t>(data);
179
180  uint8_t y=0;
181
182  for (uint32_t i=0; i<size_data; i+=size_access)
183    {
184      uint32_t offset = i;
185
186      switch (size_access)
187        {
188        case 1 :
189          {
190            y = x;
191            break;
192          }
193        case 2 : 
194          {
195            y |= ((((x>>( 1+offset))&0x1) << ( 0+offset)) |
196                  (((x>>( 0+offset))&0x1) << ( 1+offset)) );
197            break;
198          }
199        case 4 : 
200          {
201            y |= ((((x>>( 3+offset))&0x1) << ( 0+offset)) |
202                  (((x>>( 2+offset))&0x1) << ( 1+offset)) |
203                  (((x>>( 1+offset))&0x1) << ( 2+offset)) |
204                  (((x>>( 0+offset))&0x1) << ( 3+offset)) );
205            break;
206          }
207        case 8 : 
208          {
209            y |= ((((x>>( 7+offset))&0x1) << ( 0+offset)) |
210                  (((x>>( 6+offset))&0x1) << ( 1+offset)) |
211                  (((x>>( 5+offset))&0x1) << ( 2+offset)) |
212                  (((x>>( 4+offset))&0x1) << ( 3+offset)) |
213                  (((x>>( 3+offset))&0x1) << ( 4+offset)) |
214                  (((x>>( 2+offset))&0x1) << ( 5+offset)) |
215                  (((x>>( 1+offset))&0x1) << ( 6+offset)) |
216                  (((x>>( 0+offset))&0x1) << ( 7+offset)) );
217            break;
218          }
219        default :
220            {
221              break;
222            }
223        }
224    }
225
226  return static_cast<T>(y);
227}
228
229#undef  FUNCTION
230#define FUNCTION "Load_store_unit::function_speculative_load_commit_transition"
231  void Load_store_unit::function_speculative_load_commit_transition (void)
232  {
233    log_begin(Load_store_unit,FUNCTION);
234    log_function(Load_store_unit,FUNCTION,_name.c_str());
235
236    if (PORT_READ(in_NRESET) == 0)
237      {
238        // Reset : clear all queue
239        _speculative_access_queue_control->clear();
240
241        reg_STORE_QUEUE_PTR_READ       = 0;
242        reg_LOAD_QUEUE_CHECK_PRIORITY  = 0;
243
244        for (uint32_t i=0; i< _param->_size_store_queue             ; i++)
245          {
246            reg_STORE_QUEUE_NB_CHECK  [i] = 0;
247            _store_queue              [i]._state                 = STORE_QUEUE_EMPTY;
248            _store_queue              [i]._context_id            = 0; // not necessary
249            _store_queue              [i]._front_end_id          = 0; // not necessary
250            _store_queue              [i]._ooo_engine_id         = 0; // not necessary
251            _store_queue              [i]._packet_id             = 0; // not necessary
252            _store_queue              [i]._operation             = 0; // not necessary
253            _store_queue              [i]._load_queue_ptr_write  = 0; // not necessary
254            _store_queue              [i]._address               = 0; // not necessary
255            _store_queue              [i]._wdata                 = 0; // not necessary
256//          _store_queue              [i]._write_rd              = 0; // not necessary
257//          _store_queue              [i]._num_reg_rd            = 0; // not necessary
258            _store_queue              [i]._exception             = 0; // not necessary
259            _store_queue              [i]._send_commit           = 0; // not necessary
260          }
261
262        for (uint32_t i=0; i< _param->_size_load_queue              ; i++)
263          {
264            _load_queue               [i]._state                 = LOAD_QUEUE_EMPTY;
265            _load_queue               [i]._context_id            = 0; // not necessary
266            _load_queue               [i]._front_end_id          = 0; // not necessary
267            _load_queue               [i]._ooo_engine_id         = 0; // not necessary
268            _load_queue               [i]._packet_id             = 0; // not necessary
269            _load_queue               [i]._operation             = 0; // not necessary
270            _load_queue               [i]._store_queue_ptr_write = 0; // not necessary
271            _load_queue               [i]._store_queue_ptr_read  = 0; // not necessary
272            _load_queue               [i]._store_queue_empty     = 0; // not necessary
273            _load_queue               [i]._address               = 0; // not necessary
274            _load_queue               [i]._check_hit_byte        = 0; // not necessary
275            _load_queue               [i]._check_hit             = 0; // not necessary
276            _load_queue               [i]._shift                 = 0; // not necessary
277            _load_queue               [i]._is_load_signed        = 0; // not necessary
278            _load_queue               [i]._access_size           = 0; // not necessary
279            _load_queue               [i]._rdata                 = 0; // not necessary
280            _load_queue               [i]._write_rd              = 0; // not necessary
281            _load_queue               [i]._num_reg_rd            = 0; // not necessary
282            _load_queue               [i]._exception             = 0; // not necessary
283          }
284
285        for (uint32_t i=0; i< _param->_size_speculative_access_queue; i++)
286          {
287            _speculative_access_queue [i]._state                 = SPECULATIVE_ACCESS_QUEUE_EMPTY;
288            _speculative_access_queue [i]._context_id            = 0; // not necessary
289            _speculative_access_queue [i]._front_end_id          = 0; // not necessary
290            _speculative_access_queue [i]._ooo_engine_id         = 0; // not necessary
291            _speculative_access_queue [i]._packet_id             = 0; // not necessary
292            _speculative_access_queue [i]._operation             = 0; // not necessary
293            _speculative_access_queue [i]._load_queue_ptr_write  = 0; // not necessary
294            _speculative_access_queue [i]._store_queue_ptr_write = 0; // not necessary
295            _speculative_access_queue [i]._store_queue_ptr_read  = 0; // not necessary
296            _speculative_access_queue [i]._store_queue_empty     = 0; // not necessary
297            _speculative_access_queue [i]._address               = 0; // not necessary
298            _speculative_access_queue [i]._write_rd              = 0; // not necessary
299            _speculative_access_queue [i]._num_reg_rd            = 0; // not necessary
300            _speculative_access_queue [i]._exception             = 0; // not necessary
301          }
302      }
303    else
304      {
305        // load_queue_push if speculative_access_queue have access at the dcache, or they have an event
306        bool load_queue_push = (_speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._state == SPECULATIVE_ACCESS_QUEUE_WAIT_LOAD_QUEUE);
307
308        //================================================================
309        // Interface "MEMORY_OUT"
310        //================================================================
311
312        if ((    internal_MEMORY_OUT_VAL  == 1) and
313            (PORT_READ(in_MEMORY_OUT_ACK[0]) == 1))
314          {
315            log_printf(TRACE,Load_store_unit,FUNCTION,"  * MEMORY_OUT[0] transaction");
316
317            switch (internal_MEMORY_OUT_SELECT_QUEUE)
318              {
319              case SELECT_STORE_QUEUE :
320                {
321                  // =======================
322                  // ===== STORE_QUEUE =====
323                  // =======================
324                 
325                  log_printf(TRACE,Load_store_unit,FUNCTION,"    * store_queue [%d]",internal_MEMORY_OUT_PTR);
326           
327                  // Entry flush and increase the read pointer
328                  if (_store_queue [internal_MEMORY_OUT_PTR]._send_commit)
329                    {
330                      _store_queue [internal_MEMORY_OUT_PTR]._state = STORE_QUEUE_EMPTY;
331                      reg_STORE_QUEUE_PTR_READ = (reg_STORE_QUEUE_PTR_READ+1)%_param->_size_store_queue;
332                    }
333                  else
334                    _store_queue [internal_MEMORY_OUT_PTR]._send_commit = true;
335
336                  break;
337                }
338              case SELECT_LOAD_QUEUE :
339                {
340                  // ======================
341                  // ===== LOAD_QUEUE =====
342                  // ======================
343                 
344                  log_printf(TRACE,Load_store_unit,FUNCTION,"    * load_queue  [%d]",internal_MEMORY_OUT_PTR);
345                 
346                  // Entry flush and increase the read pointer
347                 
348                  _load_queue [internal_MEMORY_OUT_PTR]._state = LOAD_QUEUE_EMPTY;
349                 
350                  // reg_LOAD_QUEUE_PTR_READ = (reg_LOAD_QUEUE_PTR_READ+1)%_param->_size_load_queue;
351
352                  break;
353                }
354              case SELECT_LOAD_QUEUE_SPECULATIVE :
355                {
356                  log_printf(TRACE,Load_store_unit,FUNCTION,"    * load_queue  [%d] (speculative)",internal_MEMORY_OUT_PTR);
357                 
358                  // !!! WARNING !!!
359                  // !!! Test special case :
360                  // !!! in a cycle an instruction can check the last store AND commit instruction
361                  // !!! also the memory_out is before the port_check
362
363                  _load_queue [internal_MEMORY_OUT_PTR]._state    = LOAD_QUEUE_CHECK;
364                  // NOTE : a speculative load write in the register file.
365                  // if the speculation is a miss, write_rd is re set at 1.
366                  _load_queue [internal_MEMORY_OUT_PTR]._write_rd = 0;
367
368#ifdef STATISTICS
369                  if (usage_is_set(_usage,USE_STATISTICS))
370                    (*_stat_nb_inst_load_commit_speculative) ++;
371#endif
372
373                  break;
374                }
375
376                break;
377              }
378          }
379
380        //================================================================
381        // Interface "PORT_CHECK"
382        //================================================================
383       
384        // Plusieurs moyens de faire la verification de dépendance entre les loads et les stores.
385        //  1) un load ne peut vérifier qu'un store par cycle. Dans ce cas port_check <= size_load_queue
386        //  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.
387
388        // solution 1)
389        log_printf(TRACE,Load_store_unit,FUNCTION,"  * CHECK");
390        for (uint32_t i=0, nb_check=0; (nb_check<_param->_nb_port_check) and (i<_param->_size_load_queue); i++)
391          {
392            // Get an index from load queue
393            uint32_t index_load_queue = (i + reg_LOAD_QUEUE_CHECK_PRIORITY)%_param->_size_load_queue;
394
395            // Test if this load must ckecked store queue
396            if (((_load_queue[index_load_queue]._state == LOAD_QUEUE_WAIT_CHECK) or
397                 (_load_queue[index_load_queue]._state == LOAD_QUEUE_COMMIT_CHECK) or
398                 (_load_queue[index_load_queue]._state == LOAD_QUEUE_CHECK)) and
399                is_operation_memory_load(_load_queue[index_load_queue]._operation))
400              {
401                log_printf(TRACE,Load_store_unit,FUNCTION,"    * Find a load : %d",index_load_queue);
402
403                nb_check++; // use one port
404
405                // find a entry that it need a check
406                Tlsq_ptr_t store_queue_ptr_write = _load_queue[index_load_queue]._store_queue_ptr_write;
407                Tlsq_ptr_t store_queue_ptr_read  = _load_queue[index_load_queue]._store_queue_ptr_read ;
408                Tlsq_ptr_t store_queue_empty     = _load_queue[index_load_queue]._store_queue_empty    ;
409//              Tlsq_ptr_t store_queue_ptr_write_old = store_queue_ptr_write;
410
411                // Init variable
412                bool       end_check    = false;
413                bool       change_state = false;
414                bool       next         = false;
415
416                // At the first store queue empty, stop check.
417                // Explication :
418                //  * rename logic keep a empty case in the store queue (also size_store_queue > 1)
419                //  * when a store is out of store queue, also it was in head of re order buffer. Also, they are none previous load.
420
421                log_printf(TRACE,Load_store_unit,FUNCTION,"    * store_queue_ptr_write    : %d",store_queue_ptr_write);
422                log_printf(TRACE,Load_store_unit,FUNCTION,"    * store_queue_ptr_read     : %d",store_queue_ptr_read );
423//              log_printf(TRACE,Load_store_unit,FUNCTION,"    * store_queue_empty        : %d",store_queue_empty );
424                log_printf(TRACE,Load_store_unit,FUNCTION,"    * reg_STORE_QUEUE_PTR_READ : %d",reg_STORE_QUEUE_PTR_READ);
425
426                if ((store_queue_ptr_write ==     store_queue_ptr_read) or
427                    (store_queue_ptr_write == reg_STORE_QUEUE_PTR_READ))
428//              if (store_queue_empty)
429                  {
430                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * store_queue_ptr_write == store_queue_ptr_read");
431                    end_check    = true;
432                    change_state = true;
433                  }
434                else
435                  {
436                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * store_queue_ptr_write != store_queue_ptr_read");
437
438                    store_queue_ptr_write = (store_queue_ptr_write-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
439
440                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * store_queue_ptr_write : %d",store_queue_ptr_write);
441                   
442                    // switch on store_queue state
443                    switch (_store_queue[store_queue_ptr_write]._state)
444                      {
445                      case STORE_QUEUE_VALID_NO_SPECULATIVE : 
446                      case STORE_QUEUE_COMMIT :
447                      case STORE_QUEUE_VALID_SPECULATIVE :
448                        {
449                         
450                          log_printf(TRACE,Load_store_unit,FUNCTION,"      * store have a valid entry");
451                         
452                          // TODO : MMU - nous considérons que les adresses sont physique
453                          bool test_thread_id = true;
454                         
455                          // Test thread id
456                          if (_param->_have_port_context_id)
457                            test_thread_id &= (_load_queue[index_load_queue]._context_id    == _store_queue[store_queue_ptr_write]._context_id);
458                          if (_param->_have_port_front_end_id)
459                            test_thread_id &= (_load_queue[index_load_queue]._front_end_id  == _store_queue[store_queue_ptr_write]._front_end_id);
460                          if (_param->_have_port_ooo_engine_id)
461                            test_thread_id &= (_load_queue[index_load_queue]._ooo_engine_id == _store_queue[store_queue_ptr_write]._ooo_engine_id);
462                         
463                          if (test_thread_id)
464                            {
465                              // the load and store are in the same thread. Now, we must test address.
466
467                              log_printf(TRACE,Load_store_unit,FUNCTION,"        * load and store is the same thread.");
468                              Tdcache_address_t load_addr  = _load_queue [index_load_queue ]._address;
469                              Tdcache_address_t store_addr = _store_queue[store_queue_ptr_write]._address;
470                             
471                              log_printf(TRACE,Load_store_unit,FUNCTION,"          * load_addr                     : %.8x.",load_addr );
472                              log_printf(TRACE,Load_store_unit,FUNCTION,"          * store_addr                    : %.8x.",store_addr);
473                              log_printf(TRACE,Load_store_unit,FUNCTION,"          * load_addr  & mask_address_msb : %.8x.",load_addr  & _param->_mask_address_msb);
474                              log_printf(TRACE,Load_store_unit,FUNCTION,"          * store_addr & mask_address_msb : %.8x.",store_addr & _param->_mask_address_msb);
475                              // Test if the both address target the same "word"
476                              if ((load_addr  & _param->_mask_address_msb) == 
477                                  (store_addr & _param->_mask_address_msb))
478                                {
479                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * address_msb is the same.");
480                                  // all case - [] : store, () : load
481                                  // (1) store_max >= load_max and store_min <= load_min  ...[...(...)...]... Ok - inclusion in store
482                                  // (2) store_min >  load_max                            ...[...]...(...)... Ok - no conflit
483                                  // (3) store_max <  load_min                            ...(...)...[...]... Ok - no conflit
484                                  // (4) store_max <  load_max and store_min >  load_min  ...(...[...]...)... Ko - inclusion in load
485                                  // (5) store_max >= load_max and store_min >  load_min  ...[...(...]...)... Ko - conflit
486                                  // (6) store_max <  load_max and store_min <= load_min  ...(...[...)...]... Ko - conflit
487                                  // but :
488                                  // load in the cache is a word !
489                                  // the mask can be make when the load is commited. Also, the rdata content a full word.
490                                  // the only case is (4)
491                                 
492                                  // Read data
493                                  bool is_big_endian = true;
494
495                                  Tgeneral_data_t   load_data      = _load_queue [index_load_queue ]._rdata  ;
496                                  Tgeneral_data_t   store_data     = _store_queue[store_queue_ptr_write]._wdata  ;
497                                  Tdcache_address_t check_hit_byte = _load_queue [index_load_queue ]._check_hit_byte;
498                                  Tcontrol_t        check_hit      = _load_queue [index_load_queue ]._check_hit;
499                                  uint32_t          load_size_access  = memory_size(_load_queue [index_load_queue ]._operation)>>3;
500                                  uint32_t          store_size_access = memory_size(_store_queue[store_queue_ptr_write]._operation)>>3;
501
502                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * is_big_endian           : %d",is_big_endian);
503                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * load_data               : 0x%.8x",load_data);
504                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * store_data              : 0x%.8x",store_data);
505                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * check_hit_byte          : %x",check_hit_byte);
506                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * check_hit               : %d",check_hit);
507
508                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * load_size_access        : %d",load_size_access );
509                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * store_size_access       : %d",store_size_access);
510
511                                  if (is_big_endian)
512                                    {
513                                      // swap in little endian
514                                      load_data      = swapBytes<Tgeneral_data_t  >(load_data     , _param->_size_general_data>>3,load_size_access);
515                                      store_data     = swapBytes<Tgeneral_data_t  >(store_data    , _param->_size_general_data>>3,store_size_access);
516                                      check_hit_byte = swapBits <Tdcache_address_t>(check_hit_byte, _param->_size_general_data>>3,load_size_access);
517                                     
518                                     
519                                      log_printf(TRACE,Load_store_unit,FUNCTION,"            * load_data      (swap 1) : 0x%.8x",load_data);
520                                      log_printf(TRACE,Load_store_unit,FUNCTION,"            * store_data     (swap 1) : 0x%.8x",store_data);
521                                      log_printf(TRACE,Load_store_unit,FUNCTION,"            * check_hit_byte (swap 1) : %x",check_hit_byte);
522                                    }
523
524                                  uint32_t store_nb_byte     = (1<<memory_access(_store_queue[store_queue_ptr_write]._operation));
525
526                                  // Take interval to the store
527                                  uint32_t store_num_byte_min = (store_addr & _param->_mask_address_lsb);
528                                  uint32_t store_num_byte_max = store_num_byte_min+store_nb_byte;
529
530                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * store_num_byte_min      : %d",store_num_byte_min);
531                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * store_num_byte_max      : %d",store_num_byte_max);
532
533//                                   uint32_t load_nb_byte      = (1<<memory_access(_load_queue[index_load_queue]._operation));
534
535//                                uint32_t load_num_byte_min = (load_addr & _param->_mask_address_lsb);
536//                                uint32_t load_num_byte_max = load_num_byte_min+load_nb_byte;
537
538//                                log_printf(TRACE,Load_store_unit,FUNCTION,"            * load_num_byte_min       : %d",load_num_byte_min);
539//                                log_printf(TRACE,Load_store_unit,FUNCTION,"            * load_num_byte_max       : %d",load_num_byte_max);
540
541//                                for (uint32_t num_load_byte=load_num_byte_min; num_load_byte<load_num_byte_max; num_load_byte ++)
542//                                  {
543//                                       // Make a mask
544//                                       uint32_t num_store_byte = num_load_byte;
545                                     
546
547
548                                  // The bypass is checked byte per byte
549                                  // Is same endianness : because to change endianness, we must write in special register. Also the pipeline is flushed.
550                                  for (uint32_t num_store_byte=store_num_byte_min; num_store_byte<store_num_byte_max; num_store_byte ++)
551                                    {
552                                      // Make a mask
553                                      uint32_t num_load_byte = num_store_byte;
554
555//                                       if (is_big_endian)
556//                                         {
557//                                           // sd 0 : 0 1 2 3 4 5 6 7
558//                                           // ld 0 : 0 1 2 3 4 5 6 7 >>  0
559//                                           // lw 0 :         0 1 2 3 >>  0 -4
560//                                           // lw 4 : 4 5 6 7         >> 32 +4
561//                                           // lh 0 :             0 1 >>  0 -6
562//                                           // lh 2 :         2 3     >> 16 -2
563//                                           // lh 4 :     4 5         >> 32 +2
564//                                           // lh 6 : 6 7             >> 48 +6
565//                                           // lb 0 :               0 >>  0 -7
566//                                           // lb 1 :             1   >>  8 -5
567//                                           // lb 2 :           2     >> 16 -3
568//                                           // lb 3 :         3       >> 24 -1
569//                                           // lb 4 :       4         >> 32 +1
570//                                           // lb 5 :     5           >> 40 +3
571//                                           // lb 6 :   6             >> 48 +5
572//                                           // lb 7 : 7               >> 56 +7
573
574//                                           // diff : (store_nb_byte + load_nb_byte) - 2*nb_load_byte*((num_store_byte+1)
575
576//                                           // store duplicate = all store access can be see as full size_data store
577// //                                           uint32_t load_nb_byte = (1<<memory_access(_load_queue [index_load_queue ]._operation));
578
579// //                                           int32_t diff = ((_param->_size_general_data>>3)+load_nb_byte-2*load_nb_byte*((num_store_byte/load_nb_byte)+1));
580
581// //                                           num_load_byte =num_store_byte+diff;
582
583// //                                           log_printf(TRACE,Load_store_unit,FUNCTION,"              * load_nb_byte   : %d",load_nb_byte);
584// //                                           log_printf(TRACE,Load_store_unit,FUNCTION,"              * diff           : %d",diff);
585
586
587//                                           num_load_byte = num_store_byte;
588//                                         }
589//                                       else
590//                                         {
591//                                           // sd 0 : 0 1 2 3 4 5 6 7
592//                                           // ld 0 : 0 1 2 3 4 5 6 7 >>  0
593//                                           // lw 0 :         4 5 6 7 >>  0
594//                                           // lw 4 : 0 1 2 3         >> 32
595//                                           // lh 0 :             6 7 >>  0
596//                                           // lh 2 :         4 5     >> 16
597//                                           // lh 4 :     2 3         >> 32
598//                                           // lh 6 : 0 1             >> 48
599//                                           // lb 0 :               7 >>  0
600//                                           // lb 1 :             6   >>  8
601//                                           // lb 2 :           5     >> 16
602//                                           // lb 3 :         4       >> 24
603//                                           // lb 4 :       3         >> 32
604//                                           // lb 5 :     2           >> 40
605//                                           // lb 6 :   1             >> 48
606//                                           // lb 7 : 0               >> 56
607                                         
608//                                           num_load_byte = num_store_byte;
609//                                         }
610
611                                      uint32_t mask  = 1<<num_load_byte;
612
613                                      log_printf(TRACE,Load_store_unit,FUNCTION,"              * num_store_byte : %d",num_store_byte);
614                                      log_printf(TRACE,Load_store_unit,FUNCTION,"              * num_load_byte  : %d",num_load_byte);
615                                      log_printf(TRACE,Load_store_unit,FUNCTION,"              * mask           : %d",mask);
616
617                                      // Accept the bypass if :
618                                      //   * they have not a previous bypass with an another store
619                                      //   * it's a valid request of load
620                                      if ((check_hit_byte&mask)==0)
621                                        {
622                                          // Note : Store is duplicate = all store access can be see as full size_data store
623
624                                          uint32_t num_store_bit_min = num_store_byte<<3; //*8
625//                                        uint32_t num_store_bit_max = num_store_bit_min+8-1;
626                                          uint32_t num_load_bit_min  = num_load_byte <<3; //*8
627                                          uint32_t num_load_bit_max  = num_load_bit_min+8-1;
628
629                                          log_printf(TRACE,Load_store_unit,FUNCTION,"              * bypass !!!");
630//                                        log_printf(TRACE,Load_store_unit,FUNCTION,"              * interval store : [%d:%d]",num_store_bit_max,num_store_bit_min);
631                                          log_printf(TRACE,Load_store_unit,FUNCTION,"              * interval store : [..:%d]",num_store_bit_min);
632                                          log_printf(TRACE,Load_store_unit,FUNCTION,"              * interval load  : [%d:%d]",num_load_bit_max,num_load_bit_min);
633                                          log_printf(TRACE,Load_store_unit,FUNCTION,"                * rdata_old : 0x%.8x", load_data);
634
635                                          load_data = ((((store_data>>num_store_bit_min) & 0xff) << num_load_bit_min) |
636                                                       mask_not<Tdcache_data_t>(load_data,num_load_bit_max,num_load_bit_min));
637
638                                          check_hit_byte |= mask;
639                                          check_hit       = 1;
640                                          change_state = true;
641
642                                          log_printf(TRACE,Load_store_unit,FUNCTION,"                * rdata_new : 0x%.8x", load_data);
643                                        }
644                                    }
645
646                                  if (is_big_endian)
647                                    {
648                                      // swap in little endian
649                                      load_data      = swapBytes<Tgeneral_data_t  >(load_data     , _param->_size_general_data>>3,load_size_access);
650                                      check_hit_byte = swapBits <Tdcache_address_t>(check_hit_byte, _param->_size_general_data>>3,load_size_access);
651                                     
652                                     
653                                      log_printf(TRACE,Load_store_unit,FUNCTION,"            * load_data      (swap 2) : 0x%.8x",load_data);
654                                      log_printf(TRACE,Load_store_unit,FUNCTION,"            * check_hit_byte (swap 2) : %x",check_hit_byte);
655                                    }
656
657                                  _load_queue[index_load_queue]._rdata          = load_data;
658                                  _load_queue[index_load_queue]._check_hit_byte = check_hit_byte;
659                                  _load_queue[index_load_queue]._check_hit      = check_hit;
660
661                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * load_data  (after) : 0x%.8x",load_data);
662
663                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * check_hit          : %x",check_hit);
664                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * check_hit_byte     : %x",check_hit_byte);
665
666                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * mask_end_check     : %x",(-1& _param->_mask_address_lsb));
667                                  log_printf(TRACE,Load_store_unit,FUNCTION,"            * mask_check_hit_byte: %x",_param->_mask_check_hit_byte);
668                                  // The check is finish if all bit is set
669                                  end_check = (_load_queue[index_load_queue]._check_hit_byte == _param->_mask_check_hit_byte);
670
671                                }
672                            }
673                         
674                          next = true;
675                          break;
676                        }
677                      case STORE_QUEUE_EMPTY :
678                      case STORE_QUEUE_NO_VALID_NO_SPECULATIVE :
679                        {
680                          log_printf(TRACE,Load_store_unit,FUNCTION,"      * store have an invalid entry");
681                          break;
682                        }
683                      }
684                  }
685
686                if (next)
687                  {
688                    log_printf(TRACE,Load_store_unit,FUNCTION,"              * next");
689                    log_printf(TRACE,Load_store_unit,FUNCTION,"                * new store_queue_ptr_write : %d",store_queue_ptr_write);
690
691                    log_printf(TRACE,Load_store_unit,FUNCTION,"              * update reg_STORE_QUEUE_NB_CHECK");
692#ifdef DEBUG
693                    if (reg_STORE_QUEUE_NB_CHECK [store_queue_ptr_write] == 0)
694                      throw ERRORMORPHEO(FUNCTION,_("reg_STORE_QUEUE_NB_CHECK must be > 0\n"));
695#endif
696
697                    reg_STORE_QUEUE_NB_CHECK [store_queue_ptr_write] --;
698
699                    log_printf(TRACE,Load_store_unit,FUNCTION,"              * reg_STORE_QUEUE_NB_CHECK 1 [%d] <- %d", store_queue_ptr_write,reg_STORE_QUEUE_NB_CHECK [store_queue_ptr_write]);
700
701                    if ((store_queue_ptr_write ==     store_queue_ptr_read) or
702                        (store_queue_ptr_write == reg_STORE_QUEUE_PTR_READ))
703                      {
704//                      store_queue_empty = true;
705                        end_check         = true;
706                        change_state      = true;
707                      }
708
709//                  if (_load_queue[index_load_queue]._store_queue_ptr_write == 0)
710//                    _load_queue[index_load_queue]._store_queue_ptr_write = _param->_size_store_queue-1;
711//                  else
712//                    _load_queue[index_load_queue]._store_queue_ptr_write --;
713                    _load_queue[index_load_queue]._store_queue_ptr_write = store_queue_ptr_write; // because the index store have be decrease
714                    _load_queue[index_load_queue]._store_queue_empty     = store_queue_empty; // because the index store have be decrease
715
716                    // 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 "store_queue_ptr_read"
717                  }
718
719                if (change_state)
720                  {
721                    log_printf(TRACE,Load_store_unit,FUNCTION,"              * change_state");
722                    log_printf(TRACE,Load_store_unit,FUNCTION,"              * end_check : %d",end_check);
723
724                    log_printf(TRACE,Load_store_unit,FUNCTION,"                * state old : %s",toString(_load_queue[index_load_queue]._state).c_str());
725
726                    switch (_load_queue[index_load_queue]._state)
727                      {
728                      case LOAD_QUEUE_WAIT_CHECK   : 
729                        {
730                          if (end_check)
731                            _load_queue[index_load_queue]._state = LOAD_QUEUE_WAIT  ; 
732                          break;
733                        }
734                      case LOAD_QUEUE_COMMIT_CHECK : 
735                        {
736                          if (end_check)
737                            _load_queue[index_load_queue]._state = LOAD_QUEUE_COMMIT; 
738                          else
739                            _load_queue[index_load_queue]._state = LOAD_QUEUE_CHECK; // No commit : check hit and no end
740                          break;
741                        }
742                      case LOAD_QUEUE_CHECK        : 
743                        {
744                          if (end_check)
745                            _load_queue[index_load_queue]._state     = LOAD_QUEUE_COMMIT;
746
747                          // check find a bypass. A speculative load have been committed : report a speculation miss.
748                          if ((_load_queue[index_load_queue]._check_hit != 0) and
749                              (_load_queue[index_load_queue]._write_rd  == 0) // is commit
750                              )
751                            {
752                              _load_queue[index_load_queue]._exception = EXCEPTION_MEMORY_MISS_SPECULATION;
753                              _load_queue[index_load_queue]._write_rd  = 1; // write the good result
754
755#ifdef STATISTICS
756                              if (usage_is_set(_usage,USE_STATISTICS))
757                                (*_stat_nb_inst_load_commit_miss) ++;
758#endif
759                            }
760                         
761                          break;
762                        }
763                      default : break;
764                      }
765                    log_printf(TRACE,Load_store_unit,FUNCTION,"                * state new : %s",toString(_load_queue[index_load_queue]._state).c_str());
766                    log_printf(TRACE,Load_store_unit,FUNCTION,"                * exception : %d",_load_queue[index_load_queue]._exception);
767
768                    if (end_check//  and not store_queue_empty
769                        )
770                      {
771                        log_printf(TRACE,Load_store_unit,FUNCTION,"                * end check, decrease all nb_check");
772                       
773                        uint32_t i=store_queue_ptr_write;
774                        while (i!=store_queue_ptr_read)
775                          {
776                            i=((i==0)?_param->_size_store_queue:i)-1;
777                           
778#ifdef DEBUG
779                            if (reg_STORE_QUEUE_NB_CHECK [i] == 0)
780                              throw ERRORMORPHEO(FUNCTION,_("reg_STORE_QUEUE_NB_CHECK must be > 0\n"));
781#endif
782                           
783                            reg_STORE_QUEUE_NB_CHECK [i] --;
784
785                            log_printf(TRACE,Load_store_unit,FUNCTION,"              * reg_STORE_QUEUE_NB_CHECK 2 [%d] <- %d", i,reg_STORE_QUEUE_NB_CHECK [i]);
786
787                            //i=(i+1)%_param->_size_store_queue;
788                          }
789                       
790                        _load_queue[index_load_queue]._store_queue_empty = true; // end of check
791                      }
792                  }
793              }
794            // else : don't use a port
795          }
796       
797        //================================================================
798        // Interface "MEMORY_IN"
799        //================================================================
800       
801        if ((PORT_READ(in_MEMORY_IN_VAL [internal_MEMORY_IN_PORT]) == 1) and
802            (    internal_MEMORY_IN_ACK  == 1))
803          {
804            log_printf(TRACE,Load_store_unit,FUNCTION,"  * MEMORY_IN [%d]",internal_MEMORY_IN_PORT);
805
806            // Test operation :
807            //~~~~~~~~~~~~~~~~~
808            //  store  in store_queue
809            //  load   in speculation_access_queue
810            //  others in speculation_access_queue
811
812#ifdef DEBUG_TEST
813            if (PORT_READ(in_MEMORY_IN_TYPE [internal_MEMORY_IN_PORT]) != TYPE_MEMORY)
814              throw ERRORMORPHEO(FUNCTION,"The type is different at 'TYPE_MEMORY'");
815#endif
816            Toperation_t    operation            = PORT_READ(in_MEMORY_IN_OPERATION[internal_MEMORY_IN_PORT]);
817            Tgeneral_data_t address              = (PORT_READ(in_MEMORY_IN_IMMEDIAT[internal_MEMORY_IN_PORT]) +
818                                                    PORT_READ(in_MEMORY_IN_DATA_RA [internal_MEMORY_IN_PORT]));
819            bool            exception_alignement = (mask_memory_access(operation) & address) != 0;
820                                                   
821            if (is_operation_memory_store(operation) == true)
822              {
823                // =======================
824                // ===== STORE_QUEUE =====
825                // =======================
826                // There a two store request type :
827                //   - first is operation with address and data
828                //   - second is the information of re order buffer : the store become not speculative and can access at the data cache
829
830                log_printf(TRACE,Load_store_unit,FUNCTION,"    * store_queue");
831                log_printf(TRACE,Load_store_unit,FUNCTION,"      * PUSH");
832               
833                // Write pointer is define in rename stage :
834                Tlsq_ptr_t           index         = PORT_READ(in_MEMORY_IN_STORE_QUEUE_PTR_WRITE[internal_MEMORY_IN_PORT]);
835                log_printf(TRACE,Load_store_unit,FUNCTION,"      * index         : %d",index);
836               
837                // Need read : state and exception.
838                Tstore_queue_state_t old_state     = _store_queue [index]._state;
839                Tstore_queue_state_t new_state     = old_state;
840                bool                 update_info   = false;
841
842                Texception_t         old_exception = _store_queue [index]._exception;
843                Texception_t         new_exception = old_exception;
844
845                // Compute next state
846                switch (old_state)
847                  {
848                  case STORE_QUEUE_EMPTY                   :
849                    {
850                      if (is_operation_memory_store_head(operation) == true)
851                        {
852                          new_state = STORE_QUEUE_NO_VALID_NO_SPECULATIVE;
853
854                          // test if is a speculation
855                          if (operation == OPERATION_MEMORY_STORE_HEAD_KO)
856                            new_exception = EXCEPTION_MEMORY_MISS_SPECULATION;
857                          else
858                            new_exception = EXCEPTION_MEMORY_NONE;
859                        }
860                      else
861                        {
862                          new_state = STORE_QUEUE_VALID_SPECULATIVE;
863
864                          // Test if have an exception
865                          if (exception_alignement == true)
866                            new_exception = EXCEPTION_MEMORY_ALIGNMENT;
867                          else
868                            new_exception = EXCEPTION_MEMORY_NONE;
869
870                          update_info = true;
871                        }
872                      break;
873                    }
874                  case STORE_QUEUE_NO_VALID_NO_SPECULATIVE :
875                    {
876#ifdef DEBUG_TEST
877                      if (is_operation_memory_store_head(operation) == true)
878                        throw ERRORMORPHEO(FUNCTION,_("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."));
879#endif
880                      // Test if have a new exception (priority : miss_speculation)
881                      if ((exception_alignement == true) and (old_exception == EXCEPTION_MEMORY_NONE))
882                        new_exception = EXCEPTION_MEMORY_ALIGNMENT;
883                     
884                      if (new_exception != EXCEPTION_MEMORY_NONE)
885                        new_state = STORE_QUEUE_COMMIT;
886                      else
887                        new_state = STORE_QUEUE_VALID_NO_SPECULATIVE;
888                     
889                      update_info = true;
890                      break;
891                    }
892                  case STORE_QUEUE_VALID_SPECULATIVE       :
893                    {
894#ifdef DEBUG_TEST
895                      if (is_operation_memory_store_head(operation) == false)
896                        throw ERRORMORPHEO(FUNCTION,_("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."));
897#endif
898                      if (operation == OPERATION_MEMORY_STORE_HEAD_KO)
899                        new_exception = EXCEPTION_MEMORY_MISS_SPECULATION; // great prioritary
900                     
901                      if (new_exception != EXCEPTION_MEMORY_NONE)
902                        new_state = STORE_QUEUE_COMMIT;
903                      else
904                        new_state = STORE_QUEUE_VALID_NO_SPECULATIVE;
905                     
906                      break;
907                    }
908                  case STORE_QUEUE_VALID_NO_SPECULATIVE    :
909                  case STORE_QUEUE_COMMIT                  :
910                    {
911                      throw ERRORMORPHEO(FUNCTION,"<Load_store_unit::function_speculative_load_commit_transition> Invalid state and operation");
912                    }
913                  }
914
915                _store_queue [index]._state     = new_state;
916                _store_queue [index]._exception = new_exception;
917               
918                if (update_info == true)
919                  {
920                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * Update information");
921
922                    _store_queue [index]._context_id           = (not _param->_have_port_context_id   )?0:PORT_READ(in_MEMORY_IN_CONTEXT_ID   [internal_MEMORY_IN_PORT]);
923                    _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]);
924                    _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]);
925                    _store_queue [index]._packet_id            = (not _param->_have_port_rob_ptr      )?0:PORT_READ(in_MEMORY_IN_PACKET_ID    [internal_MEMORY_IN_PORT]);
926                    _store_queue [index]._operation            = operation;
927                    _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]);
928                    _store_queue [index]._address              = address;
929                    _store_queue [index]._send_commit          = false;
930
931                    // reordering data
932                    _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); 
933//                  _store_queue [index]._num_reg_rd           = PORT_READ(in_MEMORY_IN_NUM_REG_RD  [internal_MEMORY_IN_PORT]);
934                  }
935              }
936            else
937              {
938                // ====================================
939                // ===== SPECULATIVE_ACCESS_QUEUE =====
940                // ====================================
941
942                // In speculative access queue, they are many type's request
943                log_printf(TRACE,Load_store_unit,FUNCTION,"    * speculative_access_queue");
944                log_printf(TRACE,Load_store_unit,FUNCTION,"      * PUSH");
945               
946                // Write in reservation station
947                uint32_t     index = _speculative_access_queue_control->push();
948
949                log_printf(TRACE,Load_store_unit,FUNCTION,"      * index : %d", index);
950
951                Texception_t exception;
952
953                if (exception_alignement == true)
954                  exception = EXCEPTION_MEMORY_ALIGNMENT;
955                else
956                  exception = EXCEPTION_MEMORY_NONE;
957                               
958                // if exception, don't access at the cache
959                // NOTE : type "other" (lock, invalidate, flush and sync) can't make an alignement exception (access is equivalent at a 8 bits)
960                _speculative_access_queue [index]._state                = (exception == EXCEPTION_MEMORY_NONE)?SPECULATIVE_ACCESS_QUEUE_WAIT_CACHE:SPECULATIVE_ACCESS_QUEUE_WAIT_LOAD_QUEUE;
961                _speculative_access_queue [index]._context_id           = (not _param->_have_port_context_id   )?0:PORT_READ(in_MEMORY_IN_CONTEXT_ID   [internal_MEMORY_IN_PORT]);
962                _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]);
963                _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]);
964                _speculative_access_queue [index]._packet_id            = (not _param->_have_port_rob_ptr      )?0:PORT_READ(in_MEMORY_IN_PACKET_ID    [internal_MEMORY_IN_PORT]);
965
966                _speculative_access_queue [index]._operation            = operation;
967                _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]);
968                _speculative_access_queue [index]._store_queue_ptr_write= PORT_READ(in_MEMORY_IN_STORE_QUEUE_PTR_WRITE[internal_MEMORY_IN_PORT]);
969                _speculative_access_queue [index]._store_queue_ptr_read = PORT_READ(in_MEMORY_IN_STORE_QUEUE_PTR_READ [internal_MEMORY_IN_PORT]);
970                _speculative_access_queue [index]._store_queue_empty    = PORT_READ(in_MEMORY_IN_STORE_QUEUE_EMPTY    [internal_MEMORY_IN_PORT]);
971                _speculative_access_queue [index]._address              = address;
972                // NOTE : is operation is a load, then they are a result and must write in the register file
973                _speculative_access_queue [index]._write_rd             = is_operation_memory_load(operation);
974                _speculative_access_queue [index]._num_reg_rd           = PORT_READ(in_MEMORY_IN_NUM_REG_RD  [internal_MEMORY_IN_PORT]);
975
976                _speculative_access_queue [index]._exception            = exception;
977              }
978          }
979
980        //================================================================
981        // Interface "DCACHE_REQ"
982        //================================================================
983        if ((    internal_DCACHE_REQ_VAL  == 1) and
984            (PORT_READ(in_DCACHE_REQ_ACK[0]) == 1))
985          {
986            log_printf(TRACE,Load_store_unit,FUNCTION,"  * DCACHE_REQ [0]");
987
988            switch (internal_DCACHE_REQ_SELECT_QUEUE)
989              {
990              case SELECT_STORE_QUEUE :
991                {
992                  // =======================
993                  // ===== STORE_QUEUE =====
994                  // =======================
995                 
996                  // Entry flush and increase the read pointer
997                 
998                  _store_queue [reg_STORE_QUEUE_PTR_READ]._state = STORE_QUEUE_COMMIT;
999
1000#if defined(DEBUG) and defined(DEBUG_Load_store_unit) and (DEBUG_Load_store_unit == true)
1001                    {
1002                      // log file
1003                      Tcontext_t num_thread    = get_num_thread(_store_queue [reg_STORE_QUEUE_PTR_READ]._context_id   , _param->_size_context_id   ,
1004                                                                _store_queue [reg_STORE_QUEUE_PTR_READ]._front_end_id , _param->_size_front_end_id ,
1005                                                                _store_queue [reg_STORE_QUEUE_PTR_READ]._ooo_engine_id, _param->_size_ooo_engine_id);
1006
1007                      memory_log_file [num_thread] 
1008                        << "[" << simulation_cycle() << "] "
1009                        << std::hex
1010                        << "@ 0x" << std::setfill('0') << std::setw(_param->_size_general_data/4) << _store_queue [reg_STORE_QUEUE_PTR_READ]._address << " -[ Write ]-> 0x" << std::setfill('0') << std::setw(_param->_size_general_data/4) << _store_queue [reg_STORE_QUEUE_PTR_READ]._wdata << " "
1011                        << std::dec
1012                        << "{" << toString(_store_queue [reg_STORE_QUEUE_PTR_READ]._operation) << "}";
1013                     
1014                      memory_log_file [num_thread] << std::endl;
1015                    }
1016#endif     
1017
1018
1019                  break;
1020                }
1021              case SELECT_LOAD_QUEUE_SPECULATIVE :
1022                {
1023                  // =========================================
1024                  // ===== SELECT_LOAD_QUEUE_SPECULATIVE =====
1025                  // =========================================
1026
1027                  load_queue_push = true;
1028                  break;
1029                }
1030              case SELECT_LOAD_QUEUE :
1031                {
1032                  throw ERRORMORPHEO(FUNCTION,_("Invalid selection"));
1033                  break;
1034                }
1035
1036                break;
1037              }
1038          }
1039
1040        if (load_queue_push)
1041          {
1042            log_printf(TRACE,Load_store_unit,FUNCTION,"  * load_queue_push");
1043
1044            Tlsq_ptr_t   ptr_write = _speculative_access_queue[internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._load_queue_ptr_write;
1045            Toperation_t operation = _speculative_access_queue[internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._operation;
1046            Texception_t exception = _speculative_access_queue[internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._exception;
1047            bool         have_exception = (exception != EXCEPTION_MEMORY_NONE);
1048            bool         need_check= false;
1049            Tlsq_ptr_t   store_queue_ptr_write = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._store_queue_ptr_write;
1050            Tlsq_ptr_t   store_queue_ptr_read  = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._store_queue_ptr_read ;
1051            Tcontrol_t   store_queue_empty     = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._store_queue_empty    ;
1052           
1053            if (have_exception)
1054              _load_queue [ptr_write]._state = LOAD_QUEUE_COMMIT;
1055            else
1056              {
1057                if (have_dcache_rsp(operation))
1058                  {
1059                    // load and synchronisation
1060                    if (must_check(operation) and not store_queue_empty)
1061                      {
1062                        // load
1063                        need_check = true;
1064                       
1065                        _load_queue [ptr_write]._state = LOAD_QUEUE_WAIT_CHECK;
1066                      }
1067                    else
1068                      {
1069                        // synchronisation
1070                        _load_queue [ptr_write]._state = LOAD_QUEUE_WAIT;
1071                      }
1072                  }
1073                else
1074                  {
1075                    // lock, prefecth, flush and invalidate
1076                    _load_queue [ptr_write]._state = LOAD_QUEUE_COMMIT;
1077                  }
1078              }
1079
1080            Tdcache_address_t address        = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._address;
1081            Tdcache_address_t address_lsb    = (address & _param->_mask_address_lsb);
1082            Tdcache_address_t check_hit_byte = gen_mask_not<Tdcache_address_t>(address_lsb+(memory_size(operation)>>3)-1,address_lsb) & _param->_mask_check_hit_byte;
1083
1084            log_printf(TRACE,Load_store_unit,FUNCTION,"    * address                 : 0x%.8x", address);
1085            log_printf(TRACE,Load_store_unit,FUNCTION,"    * address_lsb             : 0x%.8x", address_lsb);
1086            log_printf(TRACE,Load_store_unit,FUNCTION,"    * operation               : %d", operation);
1087            log_printf(TRACE,Load_store_unit,FUNCTION,"    * memory_size             : %d", memory_size(operation));
1088            log_printf(TRACE,Load_store_unit,FUNCTION,"    * check_hit_byte          : 0x%x", check_hit_byte);
1089
1090            _load_queue [ptr_write]._context_id            = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._context_id;
1091            _load_queue [ptr_write]._front_end_id          = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._front_end_id;
1092            _load_queue [ptr_write]._ooo_engine_id         = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._ooo_engine_id;
1093            _load_queue [ptr_write]._packet_id             = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._packet_id;
1094            _load_queue [ptr_write]._operation             = operation;
1095            _load_queue [ptr_write]._store_queue_ptr_write = store_queue_ptr_write;
1096            _load_queue [ptr_write]._store_queue_ptr_read  = store_queue_ptr_read ;
1097            _load_queue [ptr_write]._store_queue_empty     = store_queue_empty    ;
1098            _load_queue [ptr_write]._address               = address;
1099            _load_queue [ptr_write]._check_hit_byte        = check_hit_byte;
1100            _load_queue [ptr_write]._check_hit             = 0;
1101            _load_queue [ptr_write]._shift                 = address_lsb<<3;// *8
1102            _load_queue [ptr_write]._is_load_signed        = is_operation_memory_load_signed(operation);
1103            _load_queue [ptr_write]._access_size           = memory_size(operation);
1104            // NOTE : if have an exception, must write in register, because a depend instruction wait the load data.
1105            _load_queue [ptr_write]._write_rd              = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._write_rd             ;
1106            _load_queue [ptr_write]._num_reg_rd            = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._num_reg_rd           ;
1107            _load_queue [ptr_write]._exception             = exception;
1108            _load_queue [ptr_write]._rdata                 = address; // to the exception
1109           
1110            log_printf(TRACE,Load_store_unit,FUNCTION,"    * speculative_access_queue");
1111            log_printf(TRACE,Load_store_unit,FUNCTION,"      * POP[%d]",(*_speculative_access_queue_control)[0]);
1112           
1113            _speculative_access_queue [(*_speculative_access_queue_control)[0]]._state = SPECULATIVE_ACCESS_QUEUE_EMPTY;
1114           
1115            _speculative_access_queue_control->pop();
1116
1117#ifdef STATISTICS
1118            if (usage_is_set(_usage,USE_STATISTICS))
1119              (*_stat_nb_inst_load) ++;
1120#endif
1121
1122            // Only load need check
1123            if (need_check//  and not store_queue_empty
1124                )
1125//             if (is_operation_memory_load(_load_queue [ptr_write]._operation))
1126              {
1127                log_printf(TRACE,Load_store_unit,FUNCTION,"    * update nb_check");
1128                log_printf(TRACE,Load_store_unit,FUNCTION,"      *     store_queue_ptr_write : %d",store_queue_ptr_write);
1129                log_printf(TRACE,Load_store_unit,FUNCTION,"      *     store_queue_ptr_read  : %d",store_queue_ptr_read );
1130                log_printf(TRACE,Load_store_unit,FUNCTION,"      *     store_queue_empty     : %d",store_queue_empty    );
1131                log_printf(TRACE,Load_store_unit,FUNCTION,"      * reg_STORE_QUEUE_PTR_READ  : %d",reg_STORE_QUEUE_PTR_READ);
1132               
1133                uint32_t i=store_queue_ptr_write;
1134                while (i!=store_queue_ptr_read)
1135                  {
1136                    i=((i==0)?_param->_size_store_queue:i)-1;
1137                   
1138                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * i                         : %d",i);
1139                   
1140                    reg_STORE_QUEUE_NB_CHECK [i] ++;
1141
1142                    log_printf(TRACE,Load_store_unit,FUNCTION,"              * reg_STORE_QUEUE_NB_CHECK 3 [%d] <- %d", i,reg_STORE_QUEUE_NB_CHECK [i]);
1143                  }
1144              }
1145          }
1146
1147        //================================================================
1148        // Interface "DCACHE_RSP"
1149        //================================================================
1150        if ((PORT_READ(in_DCACHE_RSP_VAL[0])== 1) and
1151            (    internal_DCACHE_RSP_ACK == 1))
1152          {
1153            log_printf(TRACE,Load_store_unit,FUNCTION,"  * DCACHE_RSP [0]");
1154
1155            // don't use context_id : because there are one queue for all thread
1156            //Tcontext_t      context_id = PORT_READ(in_DCACHE_RSP_CONTEXT_ID[0]);
1157            Tpacket_t       packet_id  = PORT_READ(in_DCACHE_RSP_PACKET_ID [0]);
1158            Tdcache_data_t  rdata      = PORT_READ(in_DCACHE_RSP_RDATA     [0]);
1159            Tdcache_error_t error      = PORT_READ(in_DCACHE_RSP_ERROR     [0]);
1160
1161            log_printf(TRACE,Load_store_unit,FUNCTION,"    * original packet_id : %d"  , packet_id);
1162            log_printf(TRACE,Load_store_unit,FUNCTION,"    * packet_id          : %d"  , packet_id>>1);
1163            log_printf(TRACE,Load_store_unit,FUNCTION,"    * rdata              : %.8x", rdata);
1164            log_printf(TRACE,Load_store_unit,FUNCTION,"    * error              : %d"  , error);
1165           
1166            if (DCACHE_RSP_IS_LOAD(packet_id) == 1)
1167              {
1168                packet_id >>= 1;
1169
1170                log_printf(TRACE,Load_store_unit,FUNCTION,"    * packet is a LOAD");
1171 
1172#ifdef DEBUG_TEST
1173                if (not have_dcache_rsp(_load_queue [packet_id]._operation))
1174                  throw ERRORMORPHEO(FUNCTION,_("Receive of respons, but the corresponding operation don't wait a respons."));
1175#endif
1176
1177                Tdcache_data_t data = _load_queue [packet_id]._rdata;
1178
1179                log_printf(TRACE,Load_store_unit,FUNCTION,"    * data construction");
1180                log_printf(TRACE,Load_store_unit,FUNCTION,"      * data from cache     : 0x%.8x",rdata);
1181                log_printf(TRACE,Load_store_unit,FUNCTION,"      * data (before)       : 0x%.8x", data);
1182                log_printf(TRACE,Load_store_unit,FUNCTION,"      * check_hit_byte      : 0x%x"  ,_load_queue [packet_id]._check_hit_byte);
1183                for (uint32_t i=0;i<(_param->_size_general_data>>3)/*8*/; ++i)
1184                  // Test if this byte has been checked
1185                  if ((_load_queue [packet_id]._check_hit_byte & (1<<i)) == 0)
1186                    {
1187                      log_printf(TRACE,Load_store_unit,FUNCTION,"      * no previous check ]%d:%d]",(i+1)<<3,i<<3);
1188                      data = insert<Tdcache_data_t>(data,rdata,((i+1)<<3)-1,i<<3);
1189                    }
1190                log_printf(TRACE,Load_store_unit,FUNCTION,"      * data (after)        : 0x%.8x", data);
1191               
1192                _load_queue [packet_id]._rdata = data;
1193               
1194#if defined(DEBUG) and defined(DEBUG_Load_store_unit) and (DEBUG_Load_store_unit == true)
1195                {
1196                  // log file
1197                  Tcontext_t num_thread    = get_num_thread(_load_queue [packet_id]._context_id   , _param->_size_context_id   ,
1198                                                            _load_queue [packet_id]._front_end_id , _param->_size_front_end_id ,
1199                                                            _load_queue [packet_id]._ooo_engine_id, _param->_size_ooo_engine_id);
1200                 
1201                  memory_log_file [num_thread] 
1202                    << "[" << simulation_cycle() << "] "
1203                    << std::hex
1204                    << "@ 0x" << std::setfill('0') << std::setw(_param->_size_general_data/4) << _load_queue [packet_id]._address << " -[ Read  ]-> 0x" << std::setfill('0') << std::setw(_param->_size_general_data/4) << _load_queue [packet_id]._rdata << " "
1205                    << std::dec
1206                    << "{" << toString(_load_queue [packet_id]._operation) << "}";
1207                 
1208                  memory_log_file [num_thread] << std::endl;
1209                }
1210#endif     
1211
1212                if (error != DCACHE_ERROR_NONE)
1213                  {
1214                    log_printf(TRACE,Load_store_unit,FUNCTION,"    * have a bus error !!!");
1215
1216                    _load_queue [packet_id]._exception = EXCEPTION_MEMORY_BUS_ERROR;
1217                    _load_queue [packet_id]._state     = LOAD_QUEUE_COMMIT;
1218
1219                   
1220                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * store_queue_ptr_write : %d", _load_queue[packet_id]._store_queue_ptr_write);
1221                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * store_queue_ptr_read  : %d", _load_queue[packet_id]._store_queue_ptr_read );
1222                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * store_queue_empty     : %d", _load_queue[packet_id]._store_queue_empty    );
1223
1224                    if (not _load_queue[packet_id]._store_queue_empty)
1225                      {
1226                        uint32_t i=_load_queue[packet_id]._store_queue_ptr_write;
1227                       
1228                        while (i!=_load_queue[packet_id]._store_queue_ptr_read)
1229                          {
1230                            i=((i==0)?_param->_size_store_queue:i)-1;
1231                           
1232#ifdef DEBUG
1233                            if (reg_STORE_QUEUE_NB_CHECK [i] == 0)
1234                              throw ERRORMORPHEO(FUNCTION,_("reg_STORE_QUEUE_NB_CHECK must be > 0\n"));
1235#endif
1236                           
1237                            reg_STORE_QUEUE_NB_CHECK [i] --;
1238
1239                            log_printf(TRACE,Load_store_unit,FUNCTION,"              * reg_STORE_QUEUE_NB_CHECK 4 [%d] <- %d", i,reg_STORE_QUEUE_NB_CHECK [i]);
1240
1241                            //i=(i+1)%_param->_size_store_queue;
1242                          }
1243                        _load_queue[packet_id]._store_queue_empty = true; // end of check
1244
1245                      }
1246                  }
1247                else
1248                  {
1249                    log_printf(TRACE,Load_store_unit,FUNCTION,"    * have no bus error.");
1250                    log_printf(TRACE,Load_store_unit,FUNCTION,"      * previous state : %s",toString(_load_queue [packet_id]._state).c_str());
1251
1252                    // FIXME : convention : if bus error, the cache return the fautive address !
1253                    // But, the load's address is aligned !
1254
1255                    switch (_load_queue [packet_id]._state)
1256                      {
1257                      case LOAD_QUEUE_WAIT_CHECK : _load_queue [packet_id]._state = LOAD_QUEUE_COMMIT_CHECK; break;
1258                      case LOAD_QUEUE_WAIT       : _load_queue [packet_id]._state = LOAD_QUEUE_COMMIT      ; break;
1259                      default : throw ERRORMORPHEO(FUNCTION,_("Illegal state (dcache_rsp).")); break;
1260                      }
1261                  }
1262              }
1263            else
1264              {
1265                log_printf(TRACE,Load_store_unit,FUNCTION,"    * packet is a STORE");
1266               
1267                // TODO : les stores ne génére pas de réponse sauf quand c'est un bus error !!!
1268                throw ERRORMORPHEO(FUNCTION,_("dcache_rsp : no respons to a write. (TODO : manage bus error to the store operation.)"));
1269              }
1270           
1271          }
1272       
1273        // this register is to manage the priority of check -> Round robin
1274        reg_LOAD_QUEUE_CHECK_PRIORITY = (reg_LOAD_QUEUE_CHECK_PRIORITY+1)%_param->_size_load_queue;
1275       
1276       
1277#if defined(DEBUG) and (DEBUG>=DEBUG_TRACE)
1278        // ***** dump store queue
1279        log_printf(TRACE,Load_store_unit,FUNCTION,"  * Dump STORE_QUEUE");
1280        log_printf(TRACE,Load_store_unit,FUNCTION,"    * ptr_read : %d",reg_STORE_QUEUE_PTR_READ);
1281       
1282        for (uint32_t i=0; i<_param->_size_store_queue; i++)
1283          {
1284            uint32_t j = (reg_STORE_QUEUE_PTR_READ+i)%_param->_size_store_queue;
1285
1286            log_printf(TRACE,Load_store_unit,FUNCTION,"    [%.4d] %.4d %.4d %.4d, %.4d, %.4d, %.4d, %.8x %.8x, %.2d %.1d, %.2d %s",
1287                       j,
1288                       _store_queue[j]._context_id          ,
1289                       _store_queue[j]._front_end_id        ,
1290                       _store_queue[j]._ooo_engine_id       ,
1291                       _store_queue[j]._packet_id           ,
1292                       _store_queue[j]._operation           ,
1293                       _store_queue[j]._load_queue_ptr_write,
1294                       _store_queue[j]._address             ,
1295                       _store_queue[j]._wdata               ,
1296                     //_store_queue[j]._write_rd            ,
1297                     //_store_queue[j]._num_reg_rd          ,
1298                       _store_queue[j]._exception           ,
1299                       _store_queue[j]._send_commit         ,
1300                       reg_STORE_QUEUE_NB_CHECK  [j]        ,
1301                       toString(_store_queue[j]._state).c_str());
1302          }
1303
1304        // ***** dump speculative_access queue
1305        log_printf(TRACE,Load_store_unit,FUNCTION,"  * Dump SPECULATIVE_ACCESS_QUEUE");
1306       
1307        for (uint32_t i=0; i<_param->_size_speculative_access_queue; i++)
1308          {
1309            uint32_t j = (*_speculative_access_queue_control)[i];
1310
1311            log_printf(TRACE,Load_store_unit,FUNCTION,"    [%.4d] %.4d %.4d %.4d, %.4d, %.4d, %.4d %.4d %.4d %.1d, %.8x, %.1d %.4d, %.2d, %s",
1312                       j,
1313                       _speculative_access_queue[j]._context_id          ,
1314                       _speculative_access_queue[j]._front_end_id        ,
1315                       _speculative_access_queue[j]._ooo_engine_id       ,
1316                       _speculative_access_queue[j]._packet_id           ,
1317                       _speculative_access_queue[j]._operation           ,
1318                       _speculative_access_queue[j]._load_queue_ptr_write,
1319                       _speculative_access_queue[j]._store_queue_ptr_write,
1320                       _speculative_access_queue[j]._store_queue_ptr_read ,
1321                       _speculative_access_queue[j]._store_queue_empty    ,
1322                       _speculative_access_queue[j]._address             ,
1323                       _speculative_access_queue[j]._write_rd            ,
1324                       _speculative_access_queue[j]._num_reg_rd          ,
1325                       _speculative_access_queue[j]._exception           ,
1326                       toString(_speculative_access_queue[j]._state).c_str());
1327          }
1328
1329        // ***** dump load queue
1330        log_printf(TRACE,Load_store_unit,FUNCTION,"  * Dump LOAD_QUEUE");
1331        log_printf(TRACE,Load_store_unit,FUNCTION,"    * ptr_read_check_priority : %d",reg_LOAD_QUEUE_CHECK_PRIORITY);
1332       
1333        for (uint32_t i=0; i<_param->_size_load_queue; i++)
1334          {
1335            uint32_t j = i;
1336
1337            log_printf(TRACE,Load_store_unit,FUNCTION,"    [%.4d] %.4d %.4d %.4d, %.4d, %.4d, %.4d %.4d %.1d, %.8x %.1x %.1d %.2d %.1d %.2d, %.8x, %.1d %.4d, %.2d, %s",
1338                       j,
1339                       _load_queue[j]._context_id          ,
1340                       _load_queue[j]._front_end_id        ,
1341                       _load_queue[j]._ooo_engine_id       ,
1342                       _load_queue[j]._packet_id           ,
1343                       _load_queue[j]._operation           ,
1344                       _load_queue[j]._store_queue_ptr_write,
1345                       _load_queue[j]._store_queue_ptr_read ,
1346                       _load_queue[j]._store_queue_empty    ,
1347                       _load_queue[j]._address             ,
1348                       _load_queue[j]._check_hit_byte      , 
1349                       _load_queue[j]._check_hit           ,
1350                       _load_queue[j]._shift               ,
1351                       _load_queue[j]._is_load_signed      ,
1352                       _load_queue[j]._access_size         ,
1353                       _load_queue[j]._rdata               ,
1354                       _load_queue[j]._write_rd            ,
1355                       _load_queue[j]._num_reg_rd          ,
1356                       _load_queue[j]._exception           ,
1357                       toString(_load_queue[j]._state).c_str());
1358          }
1359#endif
1360       
1361#ifdef STATISTICS
1362        if (usage_is_set(_usage,USE_STATISTICS))
1363          {
1364            for (uint32_t i=0; i<_param->_size_store_queue; i++)
1365              if (_store_queue[i]._state != STORE_QUEUE_EMPTY)
1366                (*_stat_use_store_queue) ++;
1367            for (uint32_t i=0; i<_param->_size_speculative_access_queue; i++)
1368              if (_speculative_access_queue[i]._state != SPECULATIVE_ACCESS_QUEUE_EMPTY)
1369                (*_stat_use_speculative_access_queue) ++;
1370            for (uint32_t i=0; i<_param->_size_load_queue; i++)
1371              if (_load_queue[i]._state != LOAD_QUEUE_EMPTY)
1372                (*_stat_use_load_queue) ++;
1373          }
1374#endif
1375      }
1376
1377    log_end(Load_store_unit,FUNCTION);
1378  };
1379
1380}; // end namespace load_store_unit
1381}; // end namespace execute_unit
1382}; // end namespace multi_execute_unit
1383}; // end namespace execute_loop
1384}; // end namespace multi_execute_loop
1385}; // end namespace core
1386
1387}; // end namespace behavioural
1388}; // end namespace morpheo             
1389#endif
Note: See TracBrowser for help on using the repository browser.