source: trunk/IPs/systemC/processor/Morpheo/Behavioural/Core/Multi_Front_end/Front_end/Prediction_unit/Update_Prediction_Table/src/Update_Prediction_Table_transition.cpp @ 122

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

Modif for performance :
1) Load Store Unit : store send request to valid exeception
2) Commit_unit : retire can bypass store
3) Commit_unit : add stat to manage store instruction
4) Load Store Unit and Load Store Pointer Manager : add store_queue_ptr_read
5) Fix lot of bug

  • Property svn:keywords set to Id
File size: 68.2 KB
Line 
1#ifdef SYSTEMC
2/*
3 * $Id: Update_Prediction_Table_transition.cpp 122 2009-06-03 08:15:51Z rosiere $
4 *
5 * [ Description ]
6 *
7 */
8
9#include "Behavioural/Core/Multi_Front_end/Front_end/Prediction_unit/Update_Prediction_Table/include/Update_Prediction_Table.h"
10
11namespace morpheo                    {
12namespace behavioural {
13namespace core {
14namespace multi_front_end {
15namespace front_end {
16namespace prediction_unit {
17namespace update_prediction_table {
18
19#undef  FUNCTION
20#define FUNCTION "Update_Prediction_Table::transition"
21  void Update_Prediction_Table::transition (void)
22  {
23    log_begin(Update_Prediction_Table,FUNCTION);
24    log_function(Update_Prediction_Table,FUNCTION,_name.c_str());
25
26    if (PORT_READ(in_NRESET) == 0)
27      {
28        // Initialisation
29
30        reg_UPDATE_PRIORITY = 0;
31
32        // All pointer is set at 0
33        for (uint32_t i=0; i<_param->_nb_context; i++)
34          {
35            for (uint32_t j=0; j<_param->_size_ufpt_queue[i]; ++j)
36              reg_UPDATE_FETCH_PREDICTION_TABLE [i][j]._state = UPDATE_FETCH_PREDICTION_STATE_EMPTY;
37            reg_UFPT_BOTTOM          [i] = 0;
38            reg_UFPT_TOP             [i] = 0;
39            reg_UFPT_UPDATE          [i] = 0;
40            reg_UFPT_NB_NEED_UPDATE  [i] = 0;
41            reg_UFPT_NB_UPDATE       [i] = 0;
42                                                               
43            for (uint32_t j=0; j<_param->_size_upt_queue[i]; ++j)
44              reg_UPDATE_PREDICTION_TABLE [i][j]._state = UPDATE_PREDICTION_STATE_EMPTY;
45            reg_UPT_BOTTOM           [i] = 0;
46            reg_UPT_TOP              [i] = 0;
47            reg_UPT_TOP_EVENT        [i] = 0;
48            reg_UPT_UPDATE           [i] = 0;
49            reg_UPT_EMPTY            [i] = true;
50                                                                                   
51            reg_IS_ACCURATE          [i] = true;
52           
53            reg_UFPT_EVENT_STATE     [i] = UFPT_EVENT_STATE_OK;
54            reg_UPT_EVENT_STATE      [i] = UPT_EVENT_STATE_OK;
55
56//             reg_EVENT_VAL            [i] = false;
57//             reg_EVENT_STATE          [i] = EVENT_STATE_OK;
58//             reg_EVENT_IS_BRANCH      [i] = true;
59          }
60      }
61    else
62      {
63        bool flush_UFPT    [_param->_nb_context];
64        for (uint32_t i=0; i<_param->_nb_context; i++)
65          {
66            flush_UFPT    [i] = false;
67          }
68
69        // ===================================================================
70        // =====[ GARBAGE COLLECTOR ]=========================================
71        // ===================================================================
72
73        // Each cycle, if the most lastest branch have update all prediction struction (state = end), free this slot
74        //   * Update state -> new status is "empty"
75        //   * Update pointer (bottom and accurate)
76        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"  * GARBAGE COLLECTOR (BEGIN)");
77        for (uint32_t i=0; i<_param->_nb_context; i++)
78          {
79            // -----------------------------
80            // UPDATE_FETCH_PREDICTION_TABLE
81            // -----------------------------
82            {
83              uint32_t bottom = reg_UFPT_BOTTOM [i];
84              bool     end    = (reg_UPDATE_FETCH_PREDICTION_TABLE [i][bottom]._state == UPDATE_FETCH_PREDICTION_STATE_END);
85
86              // Test if bottom slot can be remove
87              if (end)
88                {
89                  log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UFPT [%d][%d]",i,bottom);
90                  log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UFPT [%d][%d].state =  UPDATE_FETCH_PREDICTION_STATE_EMPTY",i,bottom);
91                 
92                  // Free slot
93                  reg_UPDATE_FETCH_PREDICTION_TABLE [i][bottom]._state = UPDATE_FETCH_PREDICTION_STATE_EMPTY;
94                  // Update pointer
95                  bottom = (bottom+1)%_param->_size_ufpt_queue[i];
96
97                  reg_UFPT_BOTTOM [i] = bottom;
98                }
99            }
100
101            // -----------------------
102            // UPDATE_PREDICTION_TABLE
103            // -----------------------
104            {
105              uint32_t bottom = reg_UPT_BOTTOM [i];
106
107//               if (reg_UPT_EVENT_STATE [i] == UPT_EVENT_STATE_OK)
108                {
109                  bool     end    = (reg_UPDATE_PREDICTION_TABLE [i][bottom]._state == UPDATE_PREDICTION_STATE_END);
110                 
111                  log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * reg_UPT_BOTTOM (before) : %d",bottom);
112                  log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * state is STATE_END      : %d",end);
113                 
114                  if (end)
115                    {
116#if defined(DEBUG) and defined(DEBUG_Update_Prediction_Table) and (DEBUG_Update_Prediction_Table == true)
117                      if (reg_UPDATE_PREDICTION_TABLE [i][bottom]._retire_ok)
118                        {
119                          uint32_t num_thread = _param->_translate_num_context_to_num_thread [i];
120                          branchement_log_file [num_thread] 
121                            << std::hex
122                            << "0x" << reg_UPDATE_PREDICTION_TABLE [i][bottom]._address_src       << " "
123                            << "0x" << reg_UPDATE_PREDICTION_TABLE [i][bottom]._address_dest      << " "
124                            << std::dec
125                            <<         reg_UPDATE_PREDICTION_TABLE [i][bottom]._good_take         << " - "
126                            << "["  << simulation_cycle() << "] " << " "
127                            <<         reg_UPDATE_PREDICTION_TABLE [i][bottom]._miss_prediction   << " "
128                            <<         reg_UPDATE_PREDICTION_TABLE [i][bottom]._ifetch_prediction << " "
129                            << "("  << (uint32_t)reg_UPDATE_PREDICTION_TABLE [i][bottom]._condition         << ")"
130                            << std::endl;
131                        }
132#endif
133                     
134                      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UPT [%d][%d]",i,bottom);
135                      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UPT [%d][%d]._state =  UPDATE_PREDICTION_STATE_EMPTY",i,bottom);
136                      // Free slot
137                      reg_UPDATE_PREDICTION_TABLE [i][bottom]._state = UPDATE_PREDICTION_STATE_EMPTY;
138                     
139                      // Update pointer
140                      reg_UPT_BOTTOM [i] = (bottom+1)%_param->_size_upt_queue[i];
141                     
142                      // Free a slot, test if bottom pointer overtake the top pointer
143                      if (reg_UPT_BOTTOM [i] == reg_UPT_TOP [i])
144                        reg_UPT_EMPTY [i] = true; // free a slot
145                     
146                      reg_EVENT_UPT_FULL [i] = false;
147                    }
148                 
149                  log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * reg_UPT_BOTTOM (after ) : %d",reg_UPT_BOTTOM         [i]);
150                }
151            }
152          }
153
154        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"  * GARBAGE COLLECTOR (END)");
155
156        // ===================================================================
157        // =====[ PREDICT ]===================================================
158        // ===================================================================
159       
160        // An ifetch_unit compute next cycle and have an branch : predict_val is set
161        //   * Alloc new entry -> new status is "wait decod"
162        //   * Save input (to restore in miss or error)
163        //   * Update pointer
164
165        for (uint32_t i=0; i<_param->_nb_inst_predict; i++)
166          // Test if have a transaction
167          if (PORT_READ(in_PREDICT_VAL[i]) and internal_PREDICT_ACK [i])
168            {
169              // get transaction information
170              Tcontext_t          context     = (_param->_have_port_context_id)?PORT_READ(in_PREDICT_CONTEXT_ID [i]):0;
171              uint32_t            top         = internal_PREDICT_UPDATE_PREDICTION_ID [i];
172              Tbranch_condition_t condition   = PORT_READ(in_PREDICT_BTB_CONDITION [i]);
173              bool                is_accurate = (_param->_always_accurate_predict or
174                                                 (_param->_can_accurate_predict and PORT_READ(in_PREDICT_BTB_IS_ACCURATE [i])));
175
176
177              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"  * PREDICT[%d] - Accepted",i);
178              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * context     : %d",context);
179              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * top         : %d",top);
180              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * condition   : %d",condition);
181              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * is_accurate : %d",is_accurate);
182
183#ifdef DEBUG_TEST
184              if (reg_UPDATE_FETCH_PREDICTION_TABLE [context][top]._state != UPDATE_FETCH_PREDICTION_STATE_EMPTY)
185                throw ERRORMORPHEO(FUNCTION,_("Predict : invalid state."));
186#endif
187
188              // Ifetch unit have fetch an instruction bundle with a branchement.
189              // Insert in UFPT
190              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UFPT [%d][%d].state <- UPDATE_FETCH_PREDICTION_STATE_WAIT_DECOD (predict)",context,top);
191              reg_UPDATE_FETCH_PREDICTION_TABLE [context][top]._state        = UPDATE_FETCH_PREDICTION_STATE_WAIT_DECOD;
192
193              // Write information
194              reg_UPDATE_FETCH_PREDICTION_TABLE [context][top]._condition    = condition;
195              reg_UPDATE_FETCH_PREDICTION_TABLE [context][top]._address_src  = PORT_READ(in_PREDICT_BTB_ADDRESS_SRC  [i]);
196              reg_UPDATE_FETCH_PREDICTION_TABLE [context][top]._address_dest = PORT_READ(in_PREDICT_BTB_ADDRESS_DEST [i]);
197              reg_UPDATE_FETCH_PREDICTION_TABLE [context][top]._last_take    = PORT_READ(in_PREDICT_BTB_LAST_TAKE    [i]);
198              reg_UPDATE_FETCH_PREDICTION_TABLE [context][top]._is_accurate  = is_accurate;
199              reg_UPDATE_FETCH_PREDICTION_TABLE [context][top]._history      = (_param->_have_port_history)?PORT_READ(in_PREDICT_DIR_HISTORY [i]):0;
200              reg_UPDATE_FETCH_PREDICTION_TABLE [context][top]._address_ras  = PORT_READ(in_PREDICT_RAS_ADDRESS      [i]);
201              reg_UPDATE_FETCH_PREDICTION_TABLE [context][top]._index_ras    = PORT_READ(in_PREDICT_RAS_INDEX        [i]);
202
203              // Update pointer
204              reg_UFPT_TOP     [context] = (top+1)%_param->_size_ufpt_queue [context];
205
206              // Test if this branchement need update
207              if (need_update(condition))
208                {
209                  reg_UFPT_NB_NEED_UPDATE [context] ++;
210                  log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UFPT_NB_NEED_UPDATE (after) : %d",reg_UFPT_NB_NEED_UPDATE [context]);
211                }
212            }
213
214        // ===================================================================
215        // =====[ DECOD ]=====================================================
216        // ===================================================================
217
218
219        // An decod is detected by decod stage
220        //   1) Hit prediction : The instruction bundle have a branch predicted in ifetch stage and it is this branch
221        //      * Update state, wait_decod -> wait_end
222        //      * Pop ufpt -> push upt
223        //      * Update accurate register : if the predict stage have tagged this branch as not accurate, stop decod
224        //   2) Miss           : The instruction bundle have a branch but it is not predicted
225        //      * Flush ufpt
226        //      * decod information is write in upt
227
228        for (uint32_t i=0; i<_param->_nb_inst_decod; i++)
229          // Test if have a decod transaction
230          if (PORT_READ(in_DECOD_VAL[i]) and internal_DECOD_ACK [i])
231            {
232              // Read information
233              Tcontext_t          context       = (_param->_have_port_context_id)?PORT_READ(in_DECOD_CONTEXT_ID [i]):0;
234              Tcontrol_t          miss_ifetch   = PORT_READ(in_DECOD_MISS_IFETCH [i]);
235              Tcontrol_t          miss_decod    = PORT_READ(in_DECOD_MISS_DECOD  [i]);
236              uint32_t            upt_ptr_write = internal_DECOD_UPT_PTR_WRITE [i];
237              uint32_t            top_next      = (upt_ptr_write+1)%_param->_size_upt_queue [context];
238              Tbranch_condition_t condition  ;
239              Tcontrol_t          is_accurate;
240              Taddress_t          address_src   = PORT_READ(in_DECOD_BTB_ADDRESS_SRC  [i]);
241              Taddress_t          address_dest  = PORT_READ(in_DECOD_BTB_ADDRESS_DEST [i]);
242              Tcontrol_t          direction     = PORT_READ(in_DECOD_BTB_LAST_TAKE    [i]);
243
244              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"  * DECOD[%d] - Accepted",i);
245              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * context       : %d",context);
246              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * miss_ifetch   : %d",miss_ifetch);
247              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * miss_decod    : %d",miss_decod);
248              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * upt_ptr_write : %d",upt_ptr_write);
249
250              // In decod step, two miss type :
251              // miss_ifetch = branch is previously predict (predict interface), but it's not the good
252              // miss_decod  = branch was not detected
253              if (not (miss_ifetch or miss_decod))
254                {
255                  // Normal case : branch is previous predicted, change state of branch
256
257                  // Read ufpt_ptr (send in predic step)
258                  uint32_t ufpt_ptr_read = (_param->_have_port_depth)?PORT_READ(in_DECOD_UPDATE_PREDICTION_ID [i]):0;
259
260                  log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * ufpt_ptr_read : %d",ufpt_ptr_read);
261
262#ifdef DEBUG_TEST
263                  if (reg_UPDATE_FETCH_PREDICTION_TABLE [context][ufpt_ptr_read]._state != UPDATE_FETCH_PREDICTION_STATE_WAIT_DECOD)
264                    throw ERRORMORPHEO(FUNCTION,_("Decod : invalid ufpt state."));
265#endif
266                  // Change state
267                  log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UFPT [%d][%d].state <- UPDATE_FETCH_PREDICTION_STATE_END (decod - hit)",context,ufpt_ptr_read);
268                  reg_UPDATE_FETCH_PREDICTION_TABLE [context][ufpt_ptr_read]._state = UPDATE_FETCH_PREDICTION_STATE_END;
269
270                  // Push upt (from Pop ufpt)
271                  condition   = reg_UPDATE_FETCH_PREDICTION_TABLE [context][ufpt_ptr_read]._condition;
272                  is_accurate = reg_UPDATE_FETCH_PREDICTION_TABLE [context][ufpt_ptr_read]._is_accurate;
273
274                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._condition         = condition;
275                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._address_src       = reg_UPDATE_FETCH_PREDICTION_TABLE [context][ufpt_ptr_read]._address_src ;
276                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._address_dest      = reg_UPDATE_FETCH_PREDICTION_TABLE [context][ufpt_ptr_read]._address_dest;
277                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._last_take         = reg_UPDATE_FETCH_PREDICTION_TABLE [context][ufpt_ptr_read]._last_take   ;
278//                reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._good_take;
279                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._is_accurate       = is_accurate;
280                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._history           = reg_UPDATE_FETCH_PREDICTION_TABLE [context][ufpt_ptr_read]._history     ;
281                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._address_ras       = reg_UPDATE_FETCH_PREDICTION_TABLE [context][ufpt_ptr_read]._address_ras ;
282                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._index_ras         = reg_UPDATE_FETCH_PREDICTION_TABLE [context][ufpt_ptr_read]._index_ras   ;
283                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._ifetch_prediction = true ; // prediction from ifetch
284
285                  // Update pointer (now, this instruction is not in ufpt)
286                  if (need_update(condition))
287                    {
288                      reg_UFPT_NB_NEED_UPDATE [context] --;
289                      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UFPT_NB_NEED_UPDATE (after) : %d",reg_UFPT_NB_NEED_UPDATE [context]);
290                    }
291                }
292              else
293                {
294                  // Have a miss !!!
295                  log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * miss !!!");
296
297                  condition   = PORT_READ(in_DECOD_BTB_CONDITION [i]);
298                  is_accurate = (_param->_always_accurate_decod or
299                                 (_param->_can_accurate_decod and PORT_READ(in_DECOD_IS_ACCURATE [i])));
300
301                  // if can_continue, don't wait the end of all instruction
302                  // (can_continue = not miss_commit and the destination is accurate (know))
303                  Tcontrol_t can_continue = is_accurate;
304
305#ifdef DEBUG_TEST
306                  if (reg_UPT_EVENT_STATE [context] != UPT_EVENT_STATE_OK)
307                    throw ERRORMORPHEO(FUNCTION,_("Decod : invalid upt event state."));
308                  if (reg_UFPT_EVENT_STATE [context] != UFPT_EVENT_STATE_OK)
309                    throw ERRORMORPHEO(FUNCTION,_("Decod : invalid ufpt event state."));
310#endif
311
312                  // miss_ifetch -> need flush ufpt
313                  // miss_decod  -> not necessary
314                  // if can_continue (destination is know) and direction is not take (instruction in ifetch_queue can be valid)
315                  bool flush_ufpt = (not (can_continue and not direction and not miss_ifetch));
316
317                  log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * can_continue: %d",can_continue);
318                  log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * direction   : %d",direction   );
319                  log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * miss_ifetch : %d",miss_ifetch );
320                  log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * flush_ufpt: %d",flush_ufpt  );
321
322                  // Test if can continue without flushing the ufpt (and ifetch_queue)
323                  if (flush_ufpt)
324                    {
325//                       // Optimisation : Test if ufpt have entry that need update prediction struction (as Return Address Stack)
326//                       if (reg_UFPT_NB_NEED_UPDATE [context] == 0)
327//                         {
328//                           // Change state
329//                           log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UPT_EVENT [%d] <- UPT_EVENT_STATE_KO_COMMIT_UPDATE_CONTEXT (decod - miss - no flush ufpt)",context);
330//                           reg_UPT_EVENT_STATE [context] = UPT_EVENT_STATE_KO_COMMIT_UPDATE_CONTEXT;
331
332//                           // @@@
333// //                           // Have an actual event ?
334// //                           if (not reg_EVENT_VAL [context])
335// //                             reg_EVENT_UPT_PTR  [context] = upt_ptr_write;
336//                         }
337//                       else
338//                         {
339//                           log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * EVENT [%d] <- UPT_EVENT_STATE_KO_MISS_WAIT_UFPT (decod - miss - flush ufpt)",context);
340//                           // just wait ufpt, don't flush upt
341//                           reg_UPT_EVENT_STATE [context] = UPT_EVENT_STATE_KO_MISS_WAIT_UFPT;
342//                         }
343
344                      reg_UPT_EVENT_STATE [context] = UPT_EVENT_STATE_KO_DECODE_UPDATE_CONTEXT;
345                      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UPT_EVENT_STATE [%d] <- %s (decod, miss)",context,toString(reg_UPT_EVENT_STATE [context]).c_str());
346
347                      // Need Flush UPFT
348                      flush_UFPT [context] = true;
349
350                      // Write information
351//                       reg_EVENT_IS_BRANCH       [context] = true;
352                      reg_EVENT_DEPTH           [context] = upt_ptr_write;
353                      reg_EVENT_ADDRESS_SRC     [context] = address_src; // delay_slot is compute in Context_State
354                      reg_EVENT_ADDRESS_DEST_VAL[context] = direction;
355                      reg_EVENT_ADDRESS_DEST    [context] = address_dest;
356                      reg_EVENT_CAN_CONTINUE    [context] = can_continue;
357                    }
358                  // else can continue
359
360                  // Push upt (from decod interface)
361                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._condition         = condition;
362                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._address_src       = address_src ;
363                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._address_dest      = address_dest;
364                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._last_take         = direction   ;
365//                reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._good_take;
366                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._is_accurate       = is_accurate;
367//                reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._history           = ; // static prediction
368                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._address_ras       = PORT_READ(in_DECOD_RAS_ADDRESS [i]);
369                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._index_ras         = PORT_READ(in_DECOD_RAS_INDEX   [i]);
370                  reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._ifetch_prediction = false; // static prediction
371                }
372
373              // In all case !!!
374#ifdef DEBUG_TEST
375              if (reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._state != UPDATE_PREDICTION_STATE_EMPTY)
376                throw ERRORMORPHEO(FUNCTION,_("Decod : invalid upt state."));
377#endif
378             
379              // Change state
380              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UPT  [%d][%d].state <- UPDATE_PREDICTION_STATE_WAIT_END (decod - hit)",context,upt_ptr_write);
381              reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._state       = UPDATE_PREDICTION_STATE_WAIT_END;
382              reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._retire_ok   = false;
383              reg_UPDATE_PREDICTION_TABLE [context][upt_ptr_write]._miss_commit = false;
384
385              // Write new accurate
386#ifdef DEBUG_TEST
387              if (not reg_IS_ACCURATE [context]  and not is_accurate)
388                throw ERRORMORPHEO(FUNCTION,_("Decod : invalid accurate flag."));
389#endif
390
391              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * is_accurate : %d",is_accurate);
392
393              reg_IS_ACCURATE [context] = is_accurate;
394             
395              // Update pointer
396              reg_UPT_TOP     [context] = top_next;
397              reg_UPT_EMPTY   [context] = false; // new instruction
398            }
399
400        // ===================================================================
401        // =====[ UPDATE ]====================================================
402        // ===================================================================
403        {
404          bool can_continue [_param->_nb_context];
405          for (uint32_t i=0; i<_param->_nb_context; ++i)
406            can_continue [i] = true;
407
408          // For each updated instruction
409          for (uint32_t i=0; i<_param->_nb_inst_update; i++)
410            {
411              Tcontext_t context   = internal_UPDATE_CONTEXT_ID [i];
412
413              // Test if transaction
414              // (an val_with_out is an update and don't need update prediction structure
415              if ((internal_UPDATE_VAL[i] and PORT_READ(in_UPDATE_ACK [i])) or
416                  (internal_UPDATE_VAL_WITHOUT_ACK [i] and can_continue [context]))
417                {
418                  Tdepth_t   depth     = internal_UPDATE_DEPTH [i];
419                 
420                  log_printf(TRACE,Update_Prediction_Table,FUNCTION,"  * UPDATE[%d] - Accepted",i);
421                  log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * context : %d",context);
422                  log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * depth   : %d",depth);
423                 
424                  upt_event_state_t upt_event_state = reg_UPT_EVENT_STATE [context];
425
426                  // One interface to two source :
427                  //   * from ufpt -> newest prediction
428                  //   * from upt  -> oldest prediction
429                  if (internal_UPDATE_FROM_UFPT [i])
430                    {
431                      // if free a slot, also all queue is updated
432                      // Last slot ?
433                      if ((--reg_UFPT_NB_UPDATE [context])==0)
434                        {
435                          log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UFPT_EVENT [%d] <- UFPT_EVENT_STATE_OK (update - end flush ufpt)",context);
436                          reg_UFPT_EVENT_STATE    [context] = UFPT_EVENT_STATE_OK;
437                          reg_UFPT_NB_NEED_UPDATE [context] = 0;
438
439//                           // Test upt event to change state
440//                           // test if upt wait ufpt
441//                           switch (upt_event_state)
442//                             {
443//                               // this case when don't need flush upt (miss decod and can continue)
444//                             case UPT_EVENT_STATE_KO_MISS_WAIT_UFPT  : upt_event_state = UPT_EVENT_STATE_KO_COMMIT_UPDATE_CONTEXT; break;
445//                             case UPT_EVENT_STATE_KO_EVENT_WAIT_UFPT : upt_event_state = UPT_EVENT_STATE_OK               ; break;
446//                             default : break;
447//                             }
448
449//                           reg_UPT_EVENT_STATE [context] = upt_event_state;
450                        }
451                     
452                      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * Update Fetch Prediction Table");
453                     
454                      // Change state
455#ifdef DEBUG_TEST
456                      if (reg_UPDATE_FETCH_PREDICTION_TABLE [context][depth]._state != UPDATE_FETCH_PREDICTION_STATE_EVENT)
457                        throw ERRORMORPHEO(FUNCTION,_("Update : invalid ufpt state."));
458#endif
459                     
460                      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UFPT [%d][%d].state <- UPDATE_FETCH_PREDICTION_STATE_END (update)",context,depth);
461                     
462                      reg_UPDATE_FETCH_PREDICTION_TABLE [context][depth]._state = UPDATE_FETCH_PREDICTION_STATE_END;
463                                           
464                      // Update pointer
465                      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UFPT_UPDATE (before) : %d",reg_UFPT_UPDATE [context]);
466                      reg_UFPT_UPDATE [context] = ((depth==0)?_param->_size_ufpt_queue[context]:depth)-1;
467                      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UFPT_UPDATE (after ) : %d",reg_UFPT_UPDATE [context]);
468                    }
469                  else
470                    {
471                      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * Update Prediction Table");
472                      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * reg_UPT_UPDATE (before) : %d",reg_UPT_UPDATE [context]);
473                      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * reg_UPT_EVENT_STATE     : %s",toString(upt_event_state).c_str());
474 
475                      // Change state
476#ifdef DEBUG_TEST
477                      if (internal_UPDATE_RAS [i])
478                        {
479                          if ((reg_UPDATE_PREDICTION_TABLE [context][depth]._state != UPDATE_PREDICTION_STATE_EVENT) and
480                              (reg_UPDATE_PREDICTION_TABLE [context][depth]._state != UPDATE_PREDICTION_STATE_KO   ) )
481                            throw ERRORMORPHEO(FUNCTION,_("Update : invalid upt state."));
482                        }
483                      else
484                        {
485                          if (reg_UPDATE_PREDICTION_TABLE [context][depth]._state != UPDATE_PREDICTION_STATE_OK   )
486                            throw ERRORMORPHEO(FUNCTION,_("Update : invalid upt state."));
487                        }
488#endif
489
490#ifdef STATISTICS
491                      Tbranch_condition_t condition = reg_UPDATE_PREDICTION_TABLE [context][depth]._condition;
492#endif
493                      bool ok = (reg_UPDATE_PREDICTION_TABLE [context][depth]._state == UPDATE_PREDICTION_STATE_OK);
494                      bool ko = (reg_UPDATE_PREDICTION_TABLE [context][depth]._state == UPDATE_PREDICTION_STATE_KO);
495
496                      // Test if branch is valid (prediction can be incorrect)
497                      if (ok or ko)
498                        {
499                          reg_UPDATE_PREDICTION_TABLE [context][depth]._retire_ok       = true;
500                          reg_UPDATE_PREDICTION_TABLE [context][depth]._miss_prediction = ko;
501
502#ifdef STATISTICS
503                          if (usage_is_set(_usage,USE_STATISTICS))
504                            {
505                              if (reg_UPDATE_PREDICTION_TABLE [context][depth]._ifetch_prediction)
506                                (*_stat_nb_branch_ifetch_prediction [context])++;
507                              if (reg_UPDATE_PREDICTION_TABLE [context][depth]._is_accurate)
508                                (*_stat_nb_branch_accurate          [context])++;
509                            }
510#endif
511                        }
512
513                      // Have an update, test the state to transiste to the good state
514                      if (ko)
515                        {
516                          // Ko
517                          log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UPT  [%d][%d].state <- UPDATE_PREDICTION_STATE_END_KO (update)",context,depth);
518                         
519                          // Wait update of context_state
520                          reg_UPDATE_PREDICTION_TABLE [context][depth]._state = UPDATE_PREDICTION_STATE_END_KO;
521
522                          reg_EVENT_UPT_PTR  [context] = depth;
523
524#ifdef STATISTICS
525                          if (usage_is_set(_usage,USE_STATISTICS))
526                            (*_stat_nb_branch_miss [context][condition])++;
527#endif
528                        }
529                      else
530                        {
531                          // ok or event
532
533                          log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UPT  [%d][%d].state <- UPDATE_PREDICTION_STATE_END (update)",context,depth);
534                          reg_UPDATE_PREDICTION_TABLE [context][depth]._state = UPDATE_PREDICTION_STATE_END;
535
536#ifdef STATISTICS
537                          if (usage_is_set(_usage,USE_STATISTICS))
538                            {
539                              if (ok)
540                                (*_stat_nb_branch_hit    [context][condition]) ++;
541                              else
542                                (*_stat_nb_branch_unused [context]) ++;
543                            }
544#endif
545                        }
546                     
547                      // Update pointer
548                      //  * if update RAS : update pointer is decreaste until it equal at top pointer
549                      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * internal_UPDATE_RAS [%d] : %d",i,internal_UPDATE_RAS [i]);
550                     
551                      if (internal_UPDATE_RAS [i])
552                        {
553                          // if end_event, restart too bottom, else decrease pointer
554                          bool end_event  = (reg_UPT_UPDATE [context] == reg_UPT_TOP [context]);
555
556                          log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * end_event               : %d",end_event);
557                          log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * bottom                  : %d",reg_UPT_BOTTOM[context]);
558                         
559                          if (end_event)
560                            {
561                              reg_UPT_UPDATE [context] = (end_event)?reg_UPT_BOTTOM[context]:(((depth==0)?_param->_size_upt_queue[context]:depth)-1);
562//                            reg_UPT_UPDATE [context] = reg_UPT_BOTTOM[context];
563
564                              switch (upt_event_state)
565                                {
566                                  // this case when don't need flush upt (miss decod and can continue)
567                                case UPT_EVENT_STATE_KO_MISS_FLUSH_UPT  : upt_event_state = UPT_EVENT_STATE_KO_COMMIT_UPDATE_CONTEXT; break;
568                                case UPT_EVENT_STATE_KO_EVENT_FLUSH_UPT : 
569                                  {
570                                    upt_event_state = UPT_EVENT_STATE_OK;
571                                    reg_UPT_TOP    [context] = reg_UPT_TOP_EVENT [context];
572                                    reg_UPT_UPDATE [context] = reg_UPT_TOP_EVENT [context];
573
574                                    break;
575                                  }
576                                default : break;
577                                }
578                             
579                              reg_UPT_EVENT_STATE [context] = upt_event_state;
580                            }
581                          else
582                            {
583                              // else, decrease update pointer
584                              reg_UPT_UPDATE [context] = (((depth==0)?_param->_size_upt_queue[context]:depth)-1);
585                            }
586                        }
587                      else
588                        {
589                          log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * next update");
590                         
591                          // increase pointer
592                          reg_UPT_UPDATE [context] = (depth+1)%_param->_size_upt_queue[context];
593                        }
594                     
595                      // Test if freeing the branch with no accurate ?
596                      if ((reg_UPDATE_PREDICTION_TABLE [context][depth]._is_accurate == false) and not ko)
597                        reg_IS_ACCURATE [context] = true;
598
599                      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * reg_UPT_UPDATE (after ) : %d",reg_UPT_UPDATE[context]);
600                      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * reg_UPT_EVENT_STATE     : %s",toString(reg_UPT_EVENT_STATE [context]).c_str());
601                    }
602                }
603              else
604                can_continue [context] = false;
605            }
606       
607          // Round robin
608          reg_UPDATE_PRIORITY = (reg_UPDATE_PRIORITY+1)%_param->_nb_context;
609        }
610
611        // ===================================================================
612        // =====[ BRANCH_COMPLETE ]===========================================
613        // ===================================================================
614       
615        // The branch is complete
616        //   * Hit  prediction :
617        //     * update status
618        //   * Miss prediction :
619        {
620          bool branch_complete_miss [_param->_nb_context];
621          for (uint32_t i=0; i<_param->_nb_context; ++i)
622            branch_complete_miss [i] = false;
623
624          for (uint32_t i=0; i<_param->_nb_inst_branch_complete; i++)
625            if (PORT_READ(in_BRANCH_COMPLETE_VAL[i]) and internal_BRANCH_COMPLETE_ACK [i])
626              {
627                // Read information
628                Tcontext_t context   = (_param->_have_port_context_id)?PORT_READ(in_BRANCH_COMPLETE_CONTEXT_ID [i]):0;
629                Tdepth_t   depth     = (_param->_have_port_depth     )?PORT_READ(in_BRANCH_COMPLETE_DEPTH      [i]):0;
630                Tcontrol_t miss      = internal_BRANCH_COMPLETE_MISS_PREDICTION [i];
631                Tcontrol_t good_take = internal_BRANCH_COMPLETE_TAKE            [i];
632                Taddress_t good_addr = internal_BRANCH_COMPLETE_ADDRESS_DEST    [i];
633               
634                upt_event_state_t upt_event_state  = reg_UPT_EVENT_STATE [context];
635               
636                log_printf(TRACE,Update_Prediction_Table,FUNCTION,"  * BRANCH_COMPLETE[%d] - Accepted",i);
637                log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * context             : %d",context);
638                log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * depth               : %d",depth);
639                log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * miss                : %d",miss);
640                log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UPT_EVENT_STATE : %s",toString(upt_event_state).c_str());
641               
642                // Test if the completed branch is a speculation miss
643                if (miss)
644                  {
645                    // special case : two branch complete on the same context.
646                    // when the re order keep the order, the branch complete j is most speculative that the branch comple i if i < j
647                    if (not branch_complete_miss [context])
648                      {
649                        branch_complete_miss [context] = true;
650                        // Flush UPT
651                        // get information
652                        uint32_t          top                 = reg_UPT_TOP [context];
653                        uint32_t          new_update          = ((top==0)?_param->_size_upt_queue[context]:top)-1; 
654                       
655                        Taddress_t        address_src         = reg_UPDATE_PREDICTION_TABLE [context][depth]._address_src;
656                        upt_state_t       event_top           = reg_UPDATE_PREDICTION_TABLE [context][top]._state;
657                       
658                        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * upt_event_state     : %s",toString(upt_event_state).c_str());
659                        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * event_top           : %s",toString(event_top).c_str());
660                       
661                        bool              previous_ufpt_event = (reg_UFPT_EVENT_STATE [i] == UFPT_EVENT_STATE_KO_FLUSH);
662                       
663                       
664                        bool              previous_upt_event  = (false
665                                                                 or (upt_event_state == UPT_EVENT_STATE_KO_MISS_WAIT_UFPT )
666                                                                 or (upt_event_state == UPT_EVENT_STATE_KO_MISS_FLUSH_UPT )
667                                                                 or (upt_event_state == UPT_EVENT_STATE_KO_EVENT_WAIT_UFPT)
668                                                                 or (upt_event_state == UPT_EVENT_STATE_KO_EVENT_FLUSH_UPT)
669                                                                 or (event_top       == UPDATE_PREDICTION_STATE_END_KO    )
670                                                                 or (event_top       == UPDATE_PREDICTION_STATE_KO        )
671                                                                 );
672                       
673                        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * top                 : %d",top);
674                        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * new_update          : %d",new_update);
675                        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * previous_upt_event  : %d",previous_upt_event);
676                        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * previous_ufpt_event : %d",previous_ufpt_event);
677                        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UPT_UPDATE      : %d",reg_UPT_UPDATE [context]);
678                       
679                        // Have a miss !!!
680                        // Flush UPFT
681                        flush_UFPT [context] |= not previous_ufpt_event;
682                       
683                        // Test if the entry wait the branchment (else, they have a previous event)
684                        if (reg_UPDATE_PREDICTION_TABLE [context][depth]._state == UPDATE_PREDICTION_STATE_WAIT_END)
685                          {
686                            // All instruction between the instruction and the top is disable
687                            for (uint32_t j=(depth+1)%_param->_size_upt_queue[context];
688                                 j!=top; 
689                                 j=(j+1)%_param->_size_upt_queue[context])
690                              {
691                                reg_UPDATE_PREDICTION_TABLE [context][j]._state     = UPDATE_PREDICTION_STATE_EVENT;
692                                reg_UPDATE_PREDICTION_TABLE [context][j]._retire_ok = false; // event
693                              }
694                           
695                            // New top
696                            reg_UPT_TOP       [context] = depth;
697                           
698                            if (not previous_upt_event)
699                              {
700                                reg_UPT_TOP_EVENT [context] = top;
701                                reg_UPT_UPDATE    [context] = new_update;
702                              }
703                            else
704                              {
705                                // Have event. Top index this slot
706                                reg_UPDATE_PREDICTION_TABLE [context][top]._retire_ok = false;
707                               
708                                switch (event_top)
709                                  {
710                                  case UPDATE_PREDICTION_STATE_END_KO : 
711                                    {
712                                      // Have already update predictor
713                                      reg_UPDATE_PREDICTION_TABLE [context][top]._state = UPDATE_PREDICTION_STATE_END;
714                                      reg_UPT_UPDATE              [context] = new_update;
715                                      break;
716                                    }
717                                  case UPDATE_PREDICTION_STATE_KO :
718                                    {
719                                      // Doesn't have update predictor
720                                      reg_UPDATE_PREDICTION_TABLE [context][top]._state = UPDATE_PREDICTION_STATE_EVENT;
721                                      break;
722                                    }
723                                  default :
724                                    {
725                                      //                                 reg_UPDATE_PREDICTION_TABLE [context][top]._state = UPDATE_PREDICTION_STATE_EVENT;
726//                                 break;
727                                     
728#ifdef DEBUG_TEST
729                                      throw ERRORMORPHEO(FUNCTION,_("Branch complete : invalid upt state."));
730#endif
731                                    }
732                                  }
733                              }
734                           
735                            if (reg_UPT_BOTTOM [context] == reg_UPT_TOP [context])
736                              reg_UPT_EMPTY [context] = true;
737                           
738                            log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UPT  [%d][%d].state <- UPDATE_PREDICTION_STATE_KO (branch_complete, ifetch hit)",context,depth);
739                            reg_UPDATE_PREDICTION_TABLE [context][depth]._state = UPDATE_PREDICTION_STATE_KO;
740                           
741                            log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UFPT_NB_NEED_UPDATE [%d] : %d",context,reg_UFPT_NB_NEED_UPDATE [context]);
742                           
743//                       if ( (reg_UFPT_NB_NEED_UPDATE [context] > 0) or
744//                            (reg_UFPT_NB_UPDATE      [context] > 0))
745//                         {
746//                           log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * EVENT [%d] <- EVENT_STATE_MISS_FLUSH_UFPT_AND_UPT (branch_complete - miss)",context);
747//                           reg_EVENT_STATE [context] = EVENT_STATE_MISS_FLUSH_UFPT_AND_UPT;
748//                         }
749//                       else
750//                         {
751// //                        if (not previous_update_ras)
752//                           {
753//                             // have ras prediction ?
754//                             log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * EVENT [%d] <- EVENT_STATE_MISS_FLUSH_UPT (branch_complete - miss)",context);
755                           
756//                             reg_EVENT_STATE [context] = EVENT_STATE_MISS_FLUSH_UPT;
757                           
758//                           }
759//                         }
760
761                            reg_UPT_EVENT_STATE [context] = UPT_EVENT_STATE_KO_MISS_FLUSH_UPT;
762                            log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UPT_EVENT_STATE [%d] <- %s (branch_complete, ifetch hit)",context,toString(reg_UPT_EVENT_STATE [context]).c_str());
763                           
764                            //                       reg_EVENT_SOURCE          [context] = EVENT_SOURCE_UPT;
765                           
766                            // else no update
767                           
768                            //                       reg_EVENT_IS_BRANCH       [context] = true;
769                            reg_EVENT_DEPTH           [context] = depth;
770                            reg_EVENT_ADDRESS_SRC     [context] = address_src; // delay_slot is compute in Context_State
771                            reg_EVENT_ADDRESS_DEST_VAL[context] = good_take;
772                            reg_EVENT_ADDRESS_DEST    [context] = good_addr;
773                            reg_EVENT_CAN_CONTINUE    [context] = false;
774                           
775                          }
776                       
777                        reg_UPDATE_PREDICTION_TABLE [context][depth]._miss_commit = true;
778                      }
779                  }
780                else
781                  {
782                  // Hit case
783
784// #ifdef DEBUG_TEST
785//                   if (reg_UPDATE_PREDICTION_TABLE [context][depth]._state != UPDATE_PREDICTION_STATE_WAIT_END)
786//                     throw ERRORMORPHEO(FUNCTION,_("Branch complete : invalid upt state."));
787// #endif
788
789                  // In same cycle, can have a previous branch_complete
790                    if (reg_UPDATE_PREDICTION_TABLE [context][depth]._state == UPDATE_PREDICTION_STATE_WAIT_END)
791                      {
792                        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UPT  [%d][%d].state <- UPDATE_PREDICTION_STATE_OK (branch_complete, ifetch hit)",context,depth);
793                        reg_UPDATE_PREDICTION_TABLE [context][depth]._state = UPDATE_PREDICTION_STATE_OK;
794                      }
795                  }
796               
797                log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UPT_EVENT_STATE : %s",toString(reg_UPT_EVENT_STATE [context]).c_str());
798               
799                // In all case : update good_take
800                reg_UPDATE_PREDICTION_TABLE [context][depth]._good_take    = good_take;
801               
802                // Write address_dest if need read register
803                Tbranch_condition_t condition = reg_UPDATE_PREDICTION_TABLE [context][depth]._condition;
804               
805                if ((condition == BRANCH_CONDITION_READ_REGISTER_WITHOUT_WRITE_STACK) or
806                    (condition == BRANCH_CONDITION_READ_REGISTER_WITH_WRITE_STACK   ) or
807                    (condition == BRANCH_CONDITION_READ_STACK                       ) )
808                  reg_UPDATE_PREDICTION_TABLE [context][depth]._address_dest = good_addr;
809              }
810        }
811
812        // ===================================================================
813        // =====[ BRANCH_EVENT ]==============================================
814        // ===================================================================
815        for (uint32_t i=0; i<_param->_nb_context; i++)
816          if (internal_BRANCH_EVENT_VAL [i] and PORT_READ(in_BRANCH_EVENT_ACK [i]))
817            {
818              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"  * BRANCH_EVENT [%d] - Accepted",i);
819
820              upt_event_state_t upt_event_state  = reg_UPT_EVENT_STATE [i];
821             
822              switch (upt_event_state)
823                {
824                case UPT_EVENT_STATE_KO_DECODE_UPDATE_CONTEXT : upt_event_state = UPT_EVENT_STATE_KO_DECODE_WAIT_END_EVENT; break;
825                case UPT_EVENT_STATE_KO_COMMIT_UPDATE_CONTEXT : upt_event_state = UPT_EVENT_STATE_KO_COMMIT_WAIT_END_EVENT; break;
826                default : break; // an other branch is occured
827                }
828
829              reg_UPT_EVENT_STATE [i] = upt_event_state;
830              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UPT_EVENT_STATE : %s (branch_event)",toString(upt_event_state).c_str());
831            }
832
833        // ===================================================================
834        // =====[ EVENT ]=====================================================
835        // ===================================================================
836        for (uint32_t i=0; i<_param->_nb_context; ++i)
837          if (PORT_READ(in_EVENT_VAL [i]) and internal_EVENT_ACK [i])
838            {
839              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"  * EVENT");
840
841              //----------------------------------------------------------------
842              // Cases
843              //----------------------------------------------------------------
844              //   * EVENT_TYPE_NONE               - nothing
845              //   * EVENT_TYPE_MISS_SPECULATION   - Change state, reset pointer
846              //   * EVENT_TYPE_EXCEPTION          - Flush upft and upt, Change state, reset pointer
847              //   * EVENT_TYPE_BRANCH_NO_ACCURATE - nothing : manage in decod and update
848              //   * EVENT_TYPE_SPR_ACCESS         - nothing
849              //   * EVENT_TYPE_MSYNC              - nothing
850              //   * EVENT_TYPE_PSYNC              - nothing
851              //   * EVENT_TYPE_CSYNC              - nothing
852             
853              Tevent_type_t     event_type      = PORT_READ(in_EVENT_TYPE  [i]);
854              upt_event_state_t upt_event_state = reg_UPT_EVENT_STATE [i];
855
856              // Test if end of miss -> all previous branch is complete
857              //                     -> all next     branch is finish
858
859              switch (event_type)
860                {
861                case EVENT_TYPE_BRANCH_MISS_SPECULATION :
862                  {
863                    log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * type  : EVENT_TYPE_BRANCH_MISS_SPECULATION");
864
865                    switch (upt_event_state)
866                      {
867                      case UPT_EVENT_STATE_KO_COMMIT_WAIT_END_EVENT :
868                        {
869                          Tdepth_t depth = reg_EVENT_UPT_PTR [i];
870                         
871                          log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * depth : %d",depth);
872                         
873                          if (reg_UPDATE_PREDICTION_TABLE [i][depth]._state == UPDATE_PREDICTION_STATE_END_KO)
874                            {
875                              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UPT  [%d][%d].state <- UPDATE_PREDICTION_STATE_END (event)",i,depth);
876                             
877                              reg_UPDATE_PREDICTION_TABLE [i][depth]._state = UPDATE_PREDICTION_STATE_END;
878                            }
879
880                            reg_UPT_TOP    [i] = reg_UPT_TOP_EVENT [i];
881                            reg_UPT_UPDATE [i] = reg_UPT_TOP_EVENT [i];
882
883                          // break; continue
884                        }
885                      case UPT_EVENT_STATE_KO_DECODE_WAIT_END_EVENT :
886                        {
887                          // Change state
888                          log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * EVENT [%d] <- EVENT_STATE_OK (event)",i);
889                         
890                          upt_event_state = UPT_EVENT_STATE_OK;
891                          reg_IS_ACCURATE [i] = true;
892
893                          break;
894                        }
895                      default : break; // an other branch is occured
896                      }
897
898                    break;
899                  }
900                case EVENT_TYPE_LOAD_MISS_SPECULATION :
901                case EVENT_TYPE_EXCEPTION             :
902                  {
903                    log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * type  : EVENT_TYPE_LOAD_MISS_SPECULATION");
904
905                    // Have a miss !!!
906                    // Flush UPFT
907                    flush_UFPT [i] = true;
908                   
909                    // Flush UPT
910                    uint32_t bottom = reg_UPT_BOTTOM [i];
911
912                    log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * bottom     : %d",bottom);
913
914//                     event_state_t event_state         = reg_EVENT_STATE [i];
915//                     bool          previous_update_ras = ((event_state == EVENT_STATE_MISS_FLUSH_UFPT_AND_UPT ) or
916//                                                          (event_state == EVENT_STATE_MISS_FLUSH_UPT          ) or
917//                                                          (event_state == EVENT_STATE_EVENT_FLUSH_UFPT_AND_UPT) or
918//                                                          (event_state == EVENT_STATE_EVENT_FLUSH_UPT));
919
920                    bool     find     = false; // have slot to update ???
921                    bool     find_top = false;
922                    Tdepth_t top      = bottom;
923                    Tdepth_t update   = bottom;
924                    bool     empty    = reg_UPT_EMPTY [i];
925
926                    // flush all slot, because this event is in head of rob
927                    for (uint32_t j=0; j<_param->_size_upt_queue[i]; ++j)
928                      {
929                        Tdepth_t x = (bottom+j)%_param->_size_upt_queue[i];
930
931                        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * UPT [%d] : %s",x,toString(reg_UPDATE_PREDICTION_TABLE [i][x]._state).c_str());
932                       
933                        if ((reg_UPDATE_PREDICTION_TABLE [i][x]._state != UPDATE_PREDICTION_STATE_END) and
934                            (reg_UPDATE_PREDICTION_TABLE [i][x]._state != UPDATE_PREDICTION_STATE_EMPTY))
935                          {
936                            log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * find at UPT[%d]",x);
937
938                            find = true; // find a not empty slot
939                            reg_UPDATE_PREDICTION_TABLE [i][x]._state     = UPDATE_PREDICTION_STATE_EVENT;
940                            reg_UPDATE_PREDICTION_TABLE [i][x]._retire_ok = false;
941                            update = x;
942                          }
943
944                        if (reg_UPDATE_PREDICTION_TABLE [i][x]._state != UPDATE_PREDICTION_STATE_EMPTY)
945                          if (not find_top)
946                            {
947                              top = x;
948                              find_top = true;
949                            }
950                      }
951
952                    log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * find       : %d",find);
953                    log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * top        : %d",top);
954                    log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * update     : %d",update);
955                   
956                    // Test if have update slot
957                    reg_UPT_TOP_EVENT [i] = reg_UPT_TOP[i];
958                    if (find)
959                      {
960                        // TODO : special case : event is an exception on branch, also depth is not valid
961                        reg_UPT_TOP       [i] = top; // depth is again valid
962                       
963                        if (bottom == reg_UPT_TOP [i])
964                          reg_UPT_EMPTY [i] = true;
965
966                        reg_UPT_UPDATE [i]  = update;
967                      }
968             
969                    // new state :
970                    //   * test if ufpt is empty
971                    //     * ok : flush upft and upt
972                    //     * ko : test if have previous flush upt
973                    //            * ok : nothing
974                    //            * ko : flush upt
975//                     reg_EVENT_VAL             [i] = find;
976//                     reg_EVENT_IS_BRANCH       [i] = false;
977//                     reg_EVENT_UPT_PTR         [i] = ((top==0)?_param->_size_upt_queue[i]:top)-1; ///// ZE MODIF
978                    reg_EVENT_UPT_PTR         [i] = top;
979                    reg_EVENT_UPT_FULL        [i] = (not empty and (bottom == reg_UPT_TOP [i]));
980                    reg_EVENT_DEPTH           [i] = top;
981//                  reg_EVENT_ADDRESS_SRC     [i] = address_src; // delay_slot is compute in I_State
982//                  reg_EVENT_ADDRESS_DEST_VAL[i] = good_take;
983//                  reg_EVENT_ADDRESS_DEST    [i] = good_addr;
984
985                    log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UPT_BOTTOM                   : %d",reg_UPT_BOTTOM          [i]);
986                    log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UPT_TOP                      : %d",reg_UPT_TOP             [i]);
987                    log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UPT_EMPTY                    : %d",reg_UPT_EMPTY           [i]);
988
989//                     log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_EVENT_VAL                    : %d",reg_EVENT_VAL           [i]);
990                    log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_EVENT_UPT_PTR                : %d",reg_EVENT_UPT_PTR       [i]);
991                    log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_EVENT_UPT_FULL               : %d",reg_EVENT_UPT_FULL      [i]);
992                    log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UFPT_NB_NEED_UPDATE          : %d",reg_UFPT_NB_NEED_UPDATE [i]);
993                    log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UFPT_NB_UPDATE               : %d",reg_UFPT_NB_UPDATE      [i]);
994
995                    if (find)
996                      {
997                        // have ras prediction ?
998                        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UPT_EVENT [%d] <- UPT_EVENT_STATE_KO_EVENT_FLUSH_UPT (event - find)",i);
999                       
1000                        upt_event_state = UPT_EVENT_STATE_KO_EVENT_FLUSH_UPT;
1001                      }
1002                    else
1003                      {
1004                        // special case : nothing
1005                        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * UPT_EVENT [%d] <- UPT_EVENT_STATE_KO_EVENT_WAIT_UFPT (event - not find)",i);
1006                       
1007//                      reg_EVENT_VAL     [i] = false;
1008                       
1009                        upt_event_state = UPT_EVENT_STATE_KO_EVENT_WAIT_UFPT;
1010                      }
1011
1012                    break;
1013                  }
1014                default :
1015                  {
1016                    // nothing
1017                    break;
1018                  }
1019                }
1020
1021              reg_UPT_EVENT_STATE [i] = upt_event_state;
1022              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UPT_EVENT_STATE : %s (branch_event)",toString(upt_event_state).c_str());
1023            }
1024
1025        // ===================================================================
1026        // =====[ FLUSH ]=====================================================
1027        // ===================================================================
1028
1029        for (uint32_t i=0; i<_param->_nb_context; ++i)
1030          {
1031            if (flush_UFPT [i])
1032              {
1033                log_printf(TRACE,Update_Prediction_Table,FUNCTION,"  * Flush Update Fetch Prediction Table");
1034                log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * context                          : %d",i);
1035                log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UFPT_NB_NEED_UPDATE          : %d",reg_UFPT_NB_NEED_UPDATE [i]);
1036
1037              // It's to accelerate miss speculation -> associative access
1038              if (reg_UFPT_NB_NEED_UPDATE [i] == 0)
1039                {
1040                  // No entry need prediction, flush all entry -> Reset
1041                  for (uint32_t j=0; j<_param->_size_ufpt_queue[i]; ++j)
1042                    reg_UPDATE_FETCH_PREDICTION_TABLE [i][j]._state = UPDATE_FETCH_PREDICTION_STATE_EMPTY;
1043                  reg_UFPT_BOTTOM [i] = 0;
1044                  reg_UFPT_TOP    [i] = 0;
1045                }
1046              else
1047                {
1048                  uint32_t bottom = reg_UFPT_BOTTOM [i];
1049                  for (uint32_t j=0; j<_param->_size_ufpt_queue[i]; ++j)
1050                    {
1051                      uint32_t index = (bottom+j)%_param->_size_ufpt_queue[i];
1052                      // EMPTY : no event
1053                      // END   : already update
1054                      // EVENT : previous event
1055                      if (reg_UPDATE_FETCH_PREDICTION_TABLE [i][index]._state == UPDATE_FETCH_PREDICTION_STATE_WAIT_DECOD)
1056                        {
1057                          reg_UFPT_UPDATE    [i] = index;
1058                          reg_UFPT_NB_UPDATE [i] ++;
1059                          reg_UPDATE_FETCH_PREDICTION_TABLE [i][index]._state = UPDATE_FETCH_PREDICTION_STATE_EVENT;
1060                        }
1061                    }
1062
1063                  // Change state
1064                  reg_UFPT_EVENT_STATE [i] = UFPT_EVENT_STATE_KO_FLUSH;
1065                }
1066
1067              log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UFPT_UPDATE         (after ) : %d",reg_UFPT_UPDATE [i]);
1068
1069              }
1070
1071            // Change state on UPT
1072            {
1073              upt_event_state_t  upt_event_state  = reg_UPT_EVENT_STATE  [i];
1074              ufpt_event_state_t ufpt_event_state = reg_UFPT_EVENT_STATE [i];
1075             
1076              // Test upt event to change state
1077              // test if upt wait ufpt
1078              if (ufpt_event_state == UFPT_EVENT_STATE_OK)
1079                switch (upt_event_state)
1080                  {
1081                    // this case when don't need flush upt (miss decod and can continue)
1082                  case UPT_EVENT_STATE_KO_MISS_WAIT_UFPT  : upt_event_state = UPT_EVENT_STATE_KO_COMMIT_UPDATE_CONTEXT; break;
1083                  case UPT_EVENT_STATE_KO_EVENT_WAIT_UFPT : upt_event_state = UPT_EVENT_STATE_OK               ; break;
1084                  default : break;
1085                  }
1086             
1087              reg_UPT_EVENT_STATE [i] = upt_event_state;
1088            }
1089          }
1090
1091#ifdef STATISTICS
1092        if (usage_is_set(_usage,USE_STATISTICS))
1093          for (uint32_t i=0; i<_param->_nb_context; i++)
1094            {
1095              for (uint32_t j=0; j<_param->_size_ufpt_queue[i]; j++)
1096                if (reg_UPDATE_FETCH_PREDICTION_TABLE [i][j]._state != UPDATE_FETCH_PREDICTION_STATE_EMPTY)
1097                  (*_stat_ufpt_queue_nb_elt [i]) ++;
1098              for (uint32_t j=0; j<_param->_size_upt_queue[i]; j++)
1099                if (reg_UPDATE_PREDICTION_TABLE [i][j]._state != UPDATE_PREDICTION_STATE_EMPTY)
1100                  (*_stat_upt_queue_nb_elt [i]) ++;
1101            }
1102#endif
1103       
1104        // ===================================================================
1105        // =====[ PRINT ]=====================================================
1106        // ===================================================================
1107
1108#if (DEBUG >= DEBUG_TRACE)
1109    log_printf(TRACE,Update_Prediction_Table,FUNCTION,"  * Dump Update_Prediction_Table");
1110    log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_UPDATE_PRIORITY       : %d",reg_UPDATE_PRIORITY);
1111    for (uint32_t i=0; i<_param->_nb_context; i++)
1112      {
1113        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_IS_ACCURATE           : %d",reg_IS_ACCURATE        [i]);
1114        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_EVENT_UFPT_STATE      : %s"  ,toString(reg_UFPT_EVENT_STATE [i]).c_str());
1115        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_EVENT_UPT_STATE       : %s"  ,toString(reg_UPT_EVENT_STATE [i]).c_str());
1116//         log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_EVENT_VAL             : %d"  ,reg_EVENT_VAL             [i]);
1117        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_EVENT_UPT_PTR         : %d"  ,reg_EVENT_UPT_PTR         [i]);
1118        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_EVENT_UPT_FULL        : %d"  ,reg_EVENT_UPT_FULL        [i]);
1119//         log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_EVENT_IS_BRANCH       : %d"  ,reg_EVENT_IS_BRANCH       [i]);
1120        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_EVENT_DEPTH           : %d"  ,reg_EVENT_DEPTH           [i]);
1121        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_EVENT_ADDRESS_SRC     : %.8x (%.8x)",reg_EVENT_ADDRESS_SRC     [i],reg_EVENT_ADDRESS_SRC     [i]<<2);
1122        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_EVENT_ADDRESS_DEST_VAL: %d"  ,reg_EVENT_ADDRESS_DEST_VAL[i]);
1123        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_EVENT_ADDRESS_DEST    : %.8x (%.8x)",reg_EVENT_ADDRESS_DEST    [i],reg_EVENT_ADDRESS_DEST    [i]<<2);
1124        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * reg_EVENT_CAN_CONTINUE    : %d"  ,reg_EVENT_CAN_CONTINUE    [i]);
1125
1126        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * Dump UFPT [%d] (Update_Fetch_Prediction_Table)",i);
1127        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * reg_UFPT_BOTTOM         : %d",reg_UFPT_BOTTOM         [i]);
1128        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * reg_UFPT_TOP            : %d",reg_UFPT_TOP            [i]);
1129        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * reg_UFPT_UPDATE         : %d",reg_UFPT_UPDATE         [i]);
1130        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * reg_UFPT_NB_NEED_UPDATE : %d",reg_UFPT_NB_NEED_UPDATE [i]);
1131        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * reg_UFPT_NB_UPDATE      : %d",reg_UFPT_NB_UPDATE      [i]);
1132        for (uint32_t j=0; j<_param->_size_ufpt_queue[i]; j++)
1133          log_printf(TRACE,Update_Prediction_Table,FUNCTION,"        [%d] %.4d, %.8x (%.8x) %.8x (%.8x), %.1d   %.1d, %.8d %.8x (%.8x) %.4d - %s",
1134                     j,
1135                     reg_UPDATE_FETCH_PREDICTION_TABLE [i][j]._condition,
1136                     reg_UPDATE_FETCH_PREDICTION_TABLE [i][j]._address_src,
1137                     reg_UPDATE_FETCH_PREDICTION_TABLE [i][j]._address_src<<2,
1138                     reg_UPDATE_FETCH_PREDICTION_TABLE [i][j]._address_dest,
1139                     reg_UPDATE_FETCH_PREDICTION_TABLE [i][j]._address_dest<<2,
1140                     reg_UPDATE_FETCH_PREDICTION_TABLE [i][j]._last_take,
1141                     reg_UPDATE_FETCH_PREDICTION_TABLE [i][j]._is_accurate,
1142                     reg_UPDATE_FETCH_PREDICTION_TABLE [i][j]._history,
1143                     reg_UPDATE_FETCH_PREDICTION_TABLE [i][j]._address_ras,
1144                     reg_UPDATE_FETCH_PREDICTION_TABLE [i][j]._address_ras<<2,
1145                     reg_UPDATE_FETCH_PREDICTION_TABLE [i][j]._index_ras,
1146                     toString(reg_UPDATE_FETCH_PREDICTION_TABLE [i][j]._state).c_str()
1147                     );
1148
1149        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * Dump UPT [%d] (Update_Prediction_Table)",i);
1150        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * reg_UPT_BOTTOM          : %d",reg_UPT_BOTTOM         [i]);
1151        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * reg_UPT_TOP             : %d",reg_UPT_TOP            [i]);
1152        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * reg_UPT_TOP_EVENT       : %d",reg_UPT_TOP_EVENT      [i]);
1153        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * reg_UPT_UPDATE          : %d",reg_UPT_UPDATE         [i]);
1154        log_printf(TRACE,Update_Prediction_Table,FUNCTION,"      * reg_UPT_EMPTY           : %d",reg_UPT_EMPTY          [i]);
1155        for (uint32_t j=0; j<_param->_size_upt_queue[i]; j++)
1156          log_printf(TRACE,Update_Prediction_Table,FUNCTION,"        [%d] %.4d, %.8x (%.8x) %.8x (%.8x), %.1d %.1d %.1d, %.8d %.8x (%.8x) %.4d - %s",
1157                     j,
1158                     reg_UPDATE_PREDICTION_TABLE [i][j]._condition,
1159                     reg_UPDATE_PREDICTION_TABLE [i][j]._address_src,
1160                     reg_UPDATE_PREDICTION_TABLE [i][j]._address_src<<2,
1161                     reg_UPDATE_PREDICTION_TABLE [i][j]._address_dest,
1162                     reg_UPDATE_PREDICTION_TABLE [i][j]._address_dest<<2,
1163                     reg_UPDATE_PREDICTION_TABLE [i][j]._last_take,
1164                     reg_UPDATE_PREDICTION_TABLE [i][j]._good_take,
1165                     reg_UPDATE_PREDICTION_TABLE [i][j]._is_accurate,
1166                     reg_UPDATE_PREDICTION_TABLE [i][j]._history,
1167                     reg_UPDATE_PREDICTION_TABLE [i][j]._address_ras,
1168                     reg_UPDATE_PREDICTION_TABLE [i][j]._address_ras<<2,
1169                     reg_UPDATE_PREDICTION_TABLE [i][j]._index_ras,
1170                     toString(reg_UPDATE_PREDICTION_TABLE [i][j]._state).c_str()
1171                     );
1172      }
1173#endif
1174
1175#ifdef DEBUG_TEST
1176    for (uint32_t i=0; i<_param->_nb_context; i++)
1177      {
1178        if (reg_UFPT_NB_NEED_UPDATE [i] > _param->_size_ufpt_queue[i])
1179          throw ERRORMORPHEO(FUNCTION,toString(_("reg_UFPT_NB_NEED_UPDATE [%d] (%d) is > at size_ufpt_queue (%d).\n"),i,reg_UFPT_NB_NEED_UPDATE [i],_param->_size_ufpt_queue[i]));
1180        if (reg_UFPT_NB_UPDATE [i] > _param->_size_ufpt_queue[i])
1181          throw ERRORMORPHEO(FUNCTION,toString(_("reg_UFPT_NB_UPDATE [%d] (%d) is > at size_ufpt_queue (%d).\n"),i,reg_UFPT_NB_UPDATE [i],_param->_size_ufpt_queue[i]));
1182      }
1183#endif
1184
1185      }
1186
1187
1188#if defined(STATISTICS) or defined(VHDL_TESTBENCH)
1189    end_cycle ();
1190#endif
1191   
1192    log_end(Update_Prediction_Table,FUNCTION);
1193  };
1194
1195}; // end namespace update_prediction_table
1196}; // end namespace prediction_unit
1197}; // end namespace front_end
1198}; // end namespace multi_front_end
1199}; // end namespace core
1200
1201}; // end namespace behavioural
1202}; // end namespace morpheo             
1203#endif
Note: See TracBrowser for help on using the repository browser.