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

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

1) Add test and configuration
2) Fix Bug
3) Add log file in load store unit
4) Fix Bug in environment

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