Changeset 71 for 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
- Timestamp:
- Jan 19, 2008, 12:09:01 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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
r62 r71 1 1 #ifdef SYSTEMC 2 //#if defined(STATISTICS) or defined(VHDL_TESTBENCH)3 2 /* 4 3 * $Id$ … … 30 29 // Reset : clear all queue 31 30 _speculative_access_queue_control->clear(); 32 internal_MEMORY_STORE_QUEUE_PTR_READ = 0; 33 internal_MEMORY_LOAD_QUEUE_PTR_READ = 0; 31 32 reg_STORE_QUEUE_PTR_READ = 0; 33 reg_LOAD_QUEUE_CHECK_PRIORITY = 0; 34 34 35 35 for (uint32_t i=0; i< _param->_size_store_queue ; i++) … … 44 44 else 45 45 { 46 //================================================================ 47 // Interface "PORT_CHECK" 48 //================================================================ 49 50 // Plusieurs moyens de faire la verification de dépendance entre les loads et les stores. 51 // 1) un load ne peut vérifier qu'un store par cycle. Dans ce cas port_check <= size_load_queue 52 // 2) un load tente de vérifier le maximum de store par cycle. Dans ce cas ce n'est pas du pointeur d'écriture qu'il lui faut mais un vecteur de bit indiquant quel store à déjà été testé. De plus il faut un bit indiquant qu'il y a un match mais que ce n'est pas forcément le premier. 53 54 // solution 1) 55 log_printf(TRACE,Load_store_unit,FUNCTION,"CHECK"); 56 for (uint32_t i=0, nb_check=0; (nb_check<_param->_nb_port_check) and (i<_param->_size_load_queue); i++) 57 { 58 uint32_t index_load = (i + reg_LOAD_QUEUE_CHECK_PRIORITY)%_param->_size_load_queue; 59 60 if (((_load_queue[index_load]._state == LOAD_QUEUE_WAIT_CHECK) or 61 (_load_queue[index_load]._state == LOAD_QUEUE_COMMIT_CHECK) or 62 (_load_queue[index_load]._state == LOAD_QUEUE_CHECK)) and 63 is_operation_memory_load(_load_queue[index_load]._operation)) 64 { 65 log_printf(TRACE,Load_store_unit,FUNCTION," * Find a load : %d",index_load); 66 67 nb_check++; // use one port 68 69 // find a entry that it need a check 70 71 Tlsq_ptr_t index_store = _load_queue[index_load]._store_queue_ptr_write; 72 bool end_check = false; 73 bool change_state = false; 74 bool next = false; 75 76 // At the first store queue empty, stop check. 77 // Explication : 78 // * rename logic keep a empty case in the store queue (also size_store_queue > 1) 79 // * when a store is out of store queue, also it was in head of re order buffer. Also, they are none previous load. 80 81 log_printf(TRACE,Load_store_unit,FUNCTION," * index_store : %d",index_store); 82 if (index_store == reg_STORE_QUEUE_PTR_READ) 83 { 84 log_printf(TRACE,Load_store_unit,FUNCTION," * index_store == reg_STORE_QUEUE_PTR_READ"); 85 end_check = true; 86 change_state = true; 87 } 88 else 89 { 90 log_printf(TRACE,Load_store_unit,FUNCTION," * index_store != reg_STORE_QUEUE_PTR_READ"); 91 92 index_store = (index_store-1)%(_param->_size_store_queue); // store_queue_ptr_write target the next slot to write, also the slot is not significatif when the load is renaming 93 94 log_printf(TRACE,Load_store_unit,FUNCTION," * index_store : %d",index_store); 95 96 switch (_store_queue[index_store]._state) 97 { 98 case STORE_QUEUE_VALID_NO_SPECULATIVE : 99 case STORE_QUEUE_COMMIT : 100 case STORE_QUEUE_VALID_SPECULATIVE : 101 { 102 103 log_printf(TRACE,Load_store_unit,FUNCTION," * store have a valid entry"); 104 105 // TODO : MMU - nous considérons que les adresses sont physique 106 bool test_thread_id = true; 107 108 // Test thread id. 109 if (_param->_have_port_context_id) 110 test_thread_id &= (_load_queue[index_load]._context_id == _store_queue[index_store]._context_id); 111 if (_param->_have_port_front_end_id) 112 test_thread_id &= (_load_queue[index_load]._front_end_id == _store_queue[index_store]._front_end_id); 113 if (_param->_have_port_ooo_engine_id) 114 test_thread_id &= (_load_queue[index_load]._ooo_engine_id == _store_queue[index_store]._ooo_engine_id); 115 116 if (test_thread_id) 117 { 118 log_printf(TRACE,Load_store_unit,FUNCTION," * load and store is the same thread."); 119 // the load and store are in the same thread. Now, we must test address. 120 Tdcache_address_t load_addr = _load_queue [index_load ]._address; 121 Tdcache_address_t store_addr = _store_queue[index_store]._address; 122 123 log_printf(TRACE,Load_store_unit,FUNCTION," * load_addr : %.8x.",load_addr ); 124 log_printf(TRACE,Load_store_unit,FUNCTION," * store_addr : %.8x.",store_addr); 125 log_printf(TRACE,Load_store_unit,FUNCTION," * load_addr & mask_address_msb : %.8x.",load_addr & _param->_mask_address_msb); 126 log_printf(TRACE,Load_store_unit,FUNCTION," * store_addr & mask_address_msb : %.8x.",store_addr & _param->_mask_address_msb); 127 // Test if the both address target the same word 128 if ((load_addr & _param->_mask_address_msb) == 129 (store_addr & _param->_mask_address_msb)) 130 { 131 log_printf(TRACE,Load_store_unit,FUNCTION," * address_msb is the same."); 132 // all case - [] : store, () : load 133 // (1) store_max >= load_max and store_min <= load_min ...[...(...)...]... Ok - inclusion in store 134 // (2) store_min > load_max ...[...]...(...)... Ok - no conflit 135 // (3) store_max < load_min ...(...)...[...]... Ok - no conflit 136 // (4) store_max < load_max and store_min > load_min ...(...[...]...)... Ko - inclusion in load 137 // (5) store_max >= load_max and store_min > load_min ...[...(...]...)... Ko - conflit 138 // (6) store_max < load_max and store_min <= load_min ...(...[...)...]... Ko - conflit 139 // but : 140 // load in the cache is a word ! 141 // the mask can be make when the load is commited. Also, the rdata content a full word. 142 // the only case is (4) 143 144 Tgeneral_data_t load_data = _load_queue [index_load ]._rdata ; 145 Tgeneral_data_t store_data = _store_queue[index_store]._wdata ; 146 147 log_printf(TRACE,Load_store_unit,FUNCTION," * load_data (init) : %.8x",load_data); 148 log_printf(TRACE,Load_store_unit,FUNCTION," * store_data (init) : %.8x",store_data); 149 uint32_t store_num_byte_min = (store_addr & _param->_mask_address_lsb); 150 uint32_t store_num_byte_max = store_num_byte_min+(1<<memory_access(_store_queue[index_store]._operation)); 151 log_printf(TRACE,Load_store_unit,FUNCTION," * store_num_byte_min : %d",store_num_byte_min); 152 log_printf(TRACE,Load_store_unit,FUNCTION," * store_num_byte_max : %d",store_num_byte_max); 153 log_printf(TRACE,Load_store_unit,FUNCTION," * check_hit : %x",_load_queue[index_load]._check_hit); 154 log_printf(TRACE,Load_store_unit,FUNCTION," * check_hit_byte : %x",_load_queue[index_load]._check_hit_byte); 155 // The bypass is checked byte per byte 156 for (uint32_t byte=store_num_byte_min; byte<store_num_byte_max; byte ++) 157 { 158 uint32_t mask = 1<<byte; 159 uint32_t index = byte<<3; 160 log_printf(TRACE,Load_store_unit,FUNCTION," * byte : %d",byte); 161 log_printf(TRACE,Load_store_unit,FUNCTION," * mask : %d",mask); 162 log_printf(TRACE,Load_store_unit,FUNCTION," * index : %d",index); 163 // Accept the bypass if they had not a previous bypass with an another store 164 if ((_load_queue[index_load]._check_hit_byte&mask)==0) 165 { 166 log_printf(TRACE,Load_store_unit,FUNCTION," * bypass !!!"); 167 log_printf(TRACE,Load_store_unit,FUNCTION," * rdata_old : %.8x", load_data); 168 load_data = insert<Tdcache_data_t>(load_data, store_data, index+8-1, index); 169 _load_queue[index_load]._check_hit_byte |= mask; 170 _load_queue[index_load]._check_hit = 1; 171 change_state = true; 172 173 log_printf(TRACE,Load_store_unit,FUNCTION," * rdata_new : %.8x", load_data); 174 } 175 } 176 177 _load_queue[index_load]._rdata = load_data; 178 179 log_printf(TRACE,Load_store_unit,FUNCTION," * check_hit : %x",_load_queue[index_load]._check_hit); 180 log_printf(TRACE,Load_store_unit,FUNCTION," * check_hit_byte : %x",_load_queue[index_load]._check_hit_byte); 181 182 log_printf(TRACE,Load_store_unit,FUNCTION," * mask_end_check : %x",(-1& _param->_mask_address_lsb)); 183 // The check is finish if all bit is set 184 end_check = (_load_queue[index_load]._check_hit_byte == MASK_CHECK_BYTE_HIT); 185 } 186 } 187 188 next = true; 189 break; 190 } 191 case STORE_QUEUE_EMPTY : 192 case STORE_QUEUE_NO_VALID_NO_SPECULATIVE : 193 { 194 log_printf(TRACE,Load_store_unit,FUNCTION," * store have an invalid entry"); 195 break; 196 } 197 } 198 } 199 200 if (next) 201 { 202 log_printf(TRACE,Load_store_unit,FUNCTION," * next"); 203 // if (_load_queue[index_load]._store_queue_ptr_write == 0) 204 // _load_queue[index_load]._store_queue_ptr_write = _param->_size_store_queue-1; 205 // else 206 // _load_queue[index_load]._store_queue_ptr_write --; 207 _load_queue[index_load]._store_queue_ptr_write = index_store; // because the index store have be decrease 208 209 // FIXME : peut n'est pas obliger de faire cette comparaison. Au prochain cycle on le détectera que les pointeur sont égaux. Ceci évitera d'avoir deux comparateurs avec le registre "reg_STORE_QUEUE_PTR_READ" 210 if (index_store == reg_STORE_QUEUE_PTR_READ) 211 { 212 end_check = true; 213 change_state = true; 214 } 215 } 216 217 if (change_state) 218 { 219 log_printf(TRACE,Load_store_unit,FUNCTION," * change_state"); 220 221 switch (_load_queue[index_load]._state) 222 { 223 case LOAD_QUEUE_WAIT_CHECK : _load_queue[index_load]._state = LOAD_QUEUE_WAIT ; break; 224 case LOAD_QUEUE_COMMIT_CHECK : 225 { 226 if (end_check) 227 _load_queue[index_load]._state = LOAD_QUEUE_COMMIT; 228 else 229 _load_queue[index_load]._state = LOAD_QUEUE_CHECK; 230 break; 231 } 232 case LOAD_QUEUE_CHECK : 233 { 234 if (end_check) 235 _load_queue[index_load]._state = LOAD_QUEUE_COMMIT; 236 // check find a bypass. A speculative load have been committed : report a speculation miss. 237 if (_load_queue[index_load]._check_hit != 0) 238 { 239 _load_queue[index_load]._exception = EXCEPTION_MEMORY_MISS_SPECULATION; 240 _load_queue[index_load]._write_rd = 1; // write the good result 241 } 242 243 break; 244 } 245 default : break; 246 } 247 log_printf(TRACE,Load_store_unit,FUNCTION," * new state : %d",_load_queue[index_load]._state); 248 log_printf(TRACE,Load_store_unit,FUNCTION," * exception : %d",_load_queue[index_load]._exception); 249 } 250 } 251 // else : don't use a port 252 } 253 46 254 //================================================================ 47 255 // Interface "MEMORY_IN" … … 117 325 case STORE_QUEUE_NO_VALID_NO_SPECULATIVE : 118 326 { 119 // if (is_operation_memory_store_head(operation) == false) 120 // { 121 new_state = STORE_QUEUE_VALID_NO_SPECULATIVE; 122 123 // Test if have a new exception (priority : miss_speculation) 124 if ((old_exception == EXCEPTION_MEMORY_NONE) and 125 (exception_alignement == true)) 126 new_exception = EXCEPTION_MEMORY_ALIGNMENT; 127 128 update_info = true; 129 break; 130 // } 327 #ifdef DEBUG_TEST 328 if (is_operation_memory_store_head(operation) == true) 329 throw ErrorMorpheo(_("Transaction in memory_in's interface, actual state of store_queue is \"STORE_QUEUE_NO_VALID_NO_SPECULATIVE\", also a previous store_head have been receiveid. But this operation is a store_head.")); 330 #endif 331 // Test if have a new exception (priority : miss_speculation) 332 if ((exception_alignement == true) and (old_exception == EXCEPTION_MEMORY_NONE)) 333 new_exception = EXCEPTION_MEMORY_ALIGNMENT; 334 335 if (new_exception != EXCEPTION_MEMORY_NONE) 336 new_state = STORE_QUEUE_COMMIT; 337 else 338 new_state = STORE_QUEUE_VALID_NO_SPECULATIVE; 339 340 update_info = true; 341 break; 131 342 } 132 343 case STORE_QUEUE_VALID_SPECULATIVE : 133 344 { 134 // if (is_operation_memory_store_head(operation) == true) 135 // { 136 new_state = STORE_QUEUE_VALID_NO_SPECULATIVE; 137 138 if (operation == OPERATION_MEMORY_STORE_HEAD_KO) 139 new_exception = EXCEPTION_MEMORY_MISS_SPECULATION; 140 141 break; 142 // } 345 #ifdef DEBUG_TEST 346 if (is_operation_memory_store_head(operation) == false) 347 throw ErrorMorpheo(_("Transaction in memory_in's interface, actual state of store_queue is \"STORE_QUEUE_VALID_SPECULATIVE\", also a previous access with register and address have been receiveid. But this operation is a not store_head.")); 348 #endif 349 if (operation == OPERATION_MEMORY_STORE_HEAD_KO) 350 new_exception = EXCEPTION_MEMORY_MISS_SPECULATION; // great prioritary 351 352 if (new_exception != EXCEPTION_MEMORY_NONE) 353 new_state = STORE_QUEUE_COMMIT; 354 else 355 new_state = STORE_QUEUE_VALID_NO_SPECULATIVE; 356 357 break; 143 358 } 144 359 case STORE_QUEUE_VALID_NO_SPECULATIVE : 145 360 case STORE_QUEUE_COMMIT : 146 361 { 147 ErrorMorpheo("<Load_store_unit::function_speculative_load_commit_transition> Invalid state and operation");362 throw ErrorMorpheo("<Load_store_unit::function_speculative_load_commit_transition> Invalid state and operation"); 148 363 } 149 364 } … … 156 371 log_printf(TRACE,Load_store_unit,FUNCTION," * Update information"); 157 372 158 _store_queue [index]._context_id = PORT_READ(in_MEMORY_IN_CONTEXT_ID ); 159 _store_queue [index]._packet_id = PORT_READ(in_MEMORY_IN_PACKET_ID ); 160 _store_queue [index]._dcache_type = operation_to_dcache_type(operation); 161 _store_queue [index]._uncached = 0; // is the MMU that have this info 373 _store_queue [index]._context_id = (not _param->_have_port_context_id )?0:PORT_READ(in_MEMORY_IN_CONTEXT_ID); 374 _store_queue [index]._front_end_id = (not _param->_have_port_front_end_id )?0:PORT_READ(in_MEMORY_IN_FRONT_END_ID); 375 _store_queue [index]._ooo_engine_id = (not _param->_have_port_ooo_engine_id)?0:PORT_READ(in_MEMORY_IN_OOO_ENGINE_ID); 376 _store_queue [index]._packet_id = (not _param->_have_port_packet_id )?0:PORT_READ(in_MEMORY_IN_PACKET_ID ); 377 _store_queue [index]._operation = operation; 162 378 _store_queue [index]._load_queue_ptr_write = PORT_READ(in_MEMORY_IN_LOAD_QUEUE_PTR_WRITE); 163 379 _store_queue [index]._address = address; 164 _store_queue [index]._wdata = PORT_READ(in_MEMORY_IN_DATA_RB ); 165 // _store_queue [index]._write_rd = PORT_READ(in_MEMORY_IN_WRITE_RD ); 380 381 // reordering data 382 _store_queue [index]._wdata = duplicate<Tgeneral_data_t>(_param->_size_general_data,PORT_READ(in_MEMORY_IN_DATA_RB), memory_size(operation), 0); 166 383 // _store_queue [index]._num_reg_rd = PORT_READ(in_MEMORY_IN_NUM_REG_RD ); 167 384 } … … 169 386 else 170 387 { 171 // // ==================================== 172 // // ===== SPECULATIVE_ACCESS_QUEUE ===== 173 // // ==================================== 174 175 // // In speculative access queue, they are many type's request 176 // log_printf(TRACE,Load_store_unit,FUNCTION,"speculative_access_queue"); 177 // log_printf(TRACE,Load_store_unit,FUNCTION," * PUSH"); 178 179 // // Write in reservation station 180 // uint32_t index = _speculative_access_queue_control->push(); 181 182 // log_printf(TRACE,Load_store_unit,FUNCTION," * index : %d",index); 388 // ==================================== 389 // ===== SPECULATIVE_ACCESS_QUEUE ===== 390 // ==================================== 391 392 // In speculative access queue, they are many type's request 393 log_printf(TRACE,Load_store_unit,FUNCTION,"speculative_access_queue"); 394 log_printf(TRACE,Load_store_unit,FUNCTION," * PUSH"); 395 396 // Write in reservation station 397 uint32_t index = _speculative_access_queue_control->push(); 398 399 log_printf(TRACE,Load_store_unit,FUNCTION," * index : %d", index); 400 401 Texception_t exception; 402 403 if (exception_alignement == true) 404 exception = EXCEPTION_MEMORY_ALIGNMENT; 405 else 406 exception = EXCEPTION_MEMORY_NONE; 407 408 // if exception, don't access at the cache 409 // NOTE : type "other" (lock, invalidate, flush and sync) can't make an alignement exception (access is equivalent at a 8 bits) 410 _speculative_access_queue [index]._state = (exception == EXCEPTION_MEMORY_NONE)?SPECULATIVE_ACCESS_QUEUE_WAIT_CACHE:SPECULATIVE_ACCESS_QUEUE_WAIT_LOAD_QUEUE; 411 _speculative_access_queue [index]._context_id = (not _param->_have_port_context_id )?0:PORT_READ(in_MEMORY_IN_CONTEXT_ID); 412 _speculative_access_queue [index]._front_end_id = (not _param->_have_port_front_end_id )?0:PORT_READ(in_MEMORY_IN_FRONT_END_ID); 413 _speculative_access_queue [index]._ooo_engine_id = (not _param->_have_port_ooo_engine_id)?0:PORT_READ(in_MEMORY_IN_OOO_ENGINE_ID); 414 _speculative_access_queue [index]._packet_id = (not _param->_have_port_packet_id )?0:PORT_READ(in_MEMORY_IN_PACKET_ID); 415 416 _speculative_access_queue [index]._operation = operation; 417 _speculative_access_queue [index]._load_queue_ptr_write = PORT_READ(in_MEMORY_IN_LOAD_QUEUE_PTR_WRITE); 418 _speculative_access_queue [index]._store_queue_ptr_write= PORT_READ(in_MEMORY_IN_STORE_QUEUE_PTR_WRITE); 419 _speculative_access_queue [index]._address = address; 420 // NOTE : is operation is a load, then they are a result and must write in the register file 421 _speculative_access_queue [index]._write_rd = is_operation_memory_load(operation); 422 _speculative_access_queue [index]._num_reg_rd = PORT_READ(in_MEMORY_IN_NUM_REG_RD ); 423 424 _speculative_access_queue [index]._exception = exception; 425 426 log_printf(TRACE,Load_store_unit,FUNCTION," * index : %d",index); 183 427 } 184 428 } … … 191 435 (PORT_READ(in_MEMORY_OUT_ACK) == 1)) 192 436 { 437 log_printf(TRACE,Load_store_unit,FUNCTION,"MEMORY_OUT transaction"); 438 193 439 switch (internal_MEMORY_OUT_SELECT_QUEUE) 194 440 { … … 199 445 // ======================= 200 446 447 log_printf(TRACE,Load_store_unit,FUNCTION," * store_queue [%d]",reg_STORE_QUEUE_PTR_READ); 448 201 449 // Entry flush and increase the read pointer 202 203 _store_queue [internal_MEMORY_STORE_QUEUE_PTR_READ]._state = STORE_QUEUE_EMPTY; 204 205 internal_MEMORY_STORE_QUEUE_PTR_READ = (internal_MEMORY_STORE_QUEUE_PTR_READ+1)%_param->_size_store_queue; 450 _store_queue [reg_STORE_QUEUE_PTR_READ]._state = STORE_QUEUE_EMPTY; 451 452 reg_STORE_QUEUE_PTR_READ = (reg_STORE_QUEUE_PTR_READ+1)%_param->_size_store_queue; 206 453 207 454 break; 208 455 } 209 456 case SELECT_LOAD_QUEUE : 457 { 458 // ====================== 459 // ===== LOAD_QUEUE ===== 460 // ====================== 461 462 log_printf(TRACE,Load_store_unit,FUNCTION," * load_queue [%d]",internal_MEMORY_OUT_PTR); 463 464 // Entry flush and increase the read pointer 465 466 _load_queue [internal_MEMORY_OUT_PTR]._state = LOAD_QUEUE_EMPTY; 467 468 // reg_LOAD_QUEUE_PTR_READ = (reg_LOAD_QUEUE_PTR_READ+1)%_param->_size_load_queue; 469 470 break; 471 } 210 472 case SELECT_LOAD_QUEUE_SPECULATIVE : 473 { 474 log_printf(TRACE,Load_store_unit,FUNCTION," * load_queue [%d] (speculative)",internal_MEMORY_OUT_PTR); 475 476 _load_queue [internal_MEMORY_OUT_PTR]._state = LOAD_QUEUE_CHECK; 477 // NOTE : a speculative load write in the register file. 478 // if the speculation is a miss, write_rd is re set at 1. 479 _load_queue [internal_MEMORY_OUT_PTR]._write_rd = 0; 480 break; 481 } 482 211 483 break; 212 484 } … … 216 488 // Interface "DCACHE_REQ" 217 489 //================================================================ 490 bool load_queue_push = (_speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._state == SPECULATIVE_ACCESS_QUEUE_WAIT_LOAD_QUEUE); 491 218 492 if (( internal_DCACHE_REQ_VAL == 1) and 219 493 (PORT_READ(in_DCACHE_REQ_ACK) == 1)) 220 494 { 495 log_printf(TRACE,Load_store_unit,FUNCTION,"DCACHE_REQ"); 496 221 497 switch (internal_DCACHE_REQ_SELECT_QUEUE) 222 498 { … … 229 505 // Entry flush and increase the read pointer 230 506 231 _store_queue [internal_MEMORY_STORE_QUEUE_PTR_READ]._state = STORE_QUEUE_COMMIT; 232 507 _store_queue [reg_STORE_QUEUE_PTR_READ]._state = STORE_QUEUE_COMMIT; 508 509 break; 510 } 511 case SELECT_LOAD_QUEUE_SPECULATIVE : 512 { 513 // ========================================= 514 // ===== SELECT_LOAD_QUEUE_SPECULATIVE ===== 515 // ========================================= 516 517 load_queue_push = true; 233 518 break; 234 519 } 235 520 case SELECT_LOAD_QUEUE : 236 case SELECT_LOAD_QUEUE_SPECULATIVE : 521 { 522 throw ErrorMorpheo(_("Invalid selection")); 523 break; 524 } 525 237 526 break; 238 527 } 239 528 } 240 529 530 if (load_queue_push) 531 { 532 Tlsq_ptr_t ptr_write = _speculative_access_queue[internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._load_queue_ptr_write; 533 Toperation_t operation = _speculative_access_queue[internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._operation; 534 Texception_t exception = _speculative_access_queue[internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._exception; 535 bool have_exception = (exception != EXCEPTION_MEMORY_NONE); 536 537 538 if (have_exception) 539 _load_queue [ptr_write]._state = LOAD_QUEUE_COMMIT; 540 else 541 { 542 if (have_dcache_rsp(operation)) 543 { 544 // load and synchronisation 545 if (must_check(operation)) 546 { 547 // load 548 _load_queue [ptr_write]._state = LOAD_QUEUE_WAIT_CHECK; 549 } 550 else 551 { 552 // synchronisation 553 _load_queue [ptr_write]._state = LOAD_QUEUE_WAIT; 554 } 555 } 556 else 557 { 558 // lock, prefecth, flush and invalidate 559 _load_queue [ptr_write]._state = LOAD_QUEUE_COMMIT; 560 } 561 } 562 563 Tdcache_address_t address = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._address; 564 Tdcache_address_t address_lsb = (address & _param->_mask_address_lsb); 565 Tdcache_address_t check_hit_byte = gen_mask_not<Tdcache_address_t>(address_lsb+memory_access(operation)+1,address_lsb); 566 _load_queue [ptr_write]._context_id = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._context_id ; 567 _load_queue [ptr_write]._front_end_id = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._front_end_id ; 568 _load_queue [ptr_write]._ooo_engine_id = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._ooo_engine_id ; 569 _load_queue [ptr_write]._packet_id = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._packet_id ; 570 _load_queue [ptr_write]._operation = operation; 571 _load_queue [ptr_write]._store_queue_ptr_write = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._store_queue_ptr_write; 572 _load_queue [ptr_write]._address = address; 573 _load_queue [ptr_write]._check_hit_byte = check_hit_byte; 574 _load_queue [ptr_write]._check_hit = 0; 575 _load_queue [ptr_write]._shift = address<<3; 576 _load_queue [ptr_write]._is_load_signed = is_operation_memory_load_signed(operation); 577 _load_queue [ptr_write]._access_size = memory_size(operation); 578 // NOTE : if have an exception, must write in register, because a depend instruction wait the load data. 579 _load_queue [ptr_write]._write_rd = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._write_rd ; 580 581 _load_queue [ptr_write]._num_reg_rd = _speculative_access_queue [internal_SPECULATIVE_ACCESS_QUEUE_PTR_READ]._num_reg_rd ; 582 _load_queue [ptr_write]._exception = exception; 583 _load_queue [ptr_write]._rdata = address; // to the exception 584 585 log_printf(TRACE,Load_store_unit,FUNCTION," * speculative_access_queue"); 586 log_printf(TRACE,Load_store_unit,FUNCTION," * POP[%d]",(*_speculative_access_queue_control)[0]); 587 588 _speculative_access_queue [(*_speculative_access_queue_control)[0]]._state = SPECULATIVE_ACCESS_QUEUE_EMPTY; 589 590 _speculative_access_queue_control->pop(); 591 } 592 593 //================================================================ 594 // Interface "DCACHE_RSP" 595 //================================================================ 596 if ((PORT_READ(in_DCACHE_RSP_VAL)== 1) and 597 ( internal_DCACHE_RSP_ACK == 1)) 598 { 599 log_printf(TRACE,Load_store_unit,FUNCTION,"DCACHE_RSP"); 600 601 // don't use context_id : because there are one queue for all thread 602 //Tcontext_t context_id = PORT_READ(in_DCACHE_RSP_CONTEXT_ID); 603 Tpacket_t packet_id = PORT_READ(in_DCACHE_RSP_PACKET_ID ); 604 Tdcache_data_t rdata = PORT_READ(in_DCACHE_RSP_RDATA ); 605 Tdcache_error_t error = PORT_READ(in_DCACHE_RSP_ERROR ); 606 607 log_printf(TRACE,Load_store_unit,FUNCTION," * original packet_id : %d", packet_id); 608 609 if (DCACHE_RSP_IS_LOAD(packet_id) == 1) 610 { 611 packet_id >>= 1; 612 613 log_printf(TRACE,Load_store_unit,FUNCTION," * packet is a LOAD : %d", packet_id); 614 615 616 #ifdef DEBUG_TEST 617 if (not have_dcache_rsp(_load_queue [packet_id]._operation)) 618 throw ErrorMorpheo(_("Receive of respons, but the corresponding operation don't wait a respons.")); 619 #endif 620 621 622 if (error != 0) 623 { 624 log_printf(TRACE,Load_store_unit,FUNCTION," * have a bus error !!!"); 625 626 _load_queue [packet_id]._exception = EXCEPTION_MEMORY_BUS_ERROR; 627 _load_queue [packet_id]._state = LOAD_QUEUE_COMMIT; 628 } 629 else 630 { 631 log_printf(TRACE,Load_store_unit,FUNCTION," * have no bus error."); 632 log_printf(TRACE,Load_store_unit,FUNCTION," * previous state : %d.",_load_queue [packet_id]._state); 633 634 // FIXME : convention : if bus error, the cache return the fautive address ! 635 // But, the load's address is aligned ! 636 _load_queue [packet_id]._rdata = rdata; 637 638 switch (_load_queue [packet_id]._state) 639 { 640 case LOAD_QUEUE_WAIT_CHECK : _load_queue [packet_id]._state = LOAD_QUEUE_COMMIT_CHECK; break; 641 case LOAD_QUEUE_WAIT : _load_queue [packet_id]._state = LOAD_QUEUE_COMMIT ; break; 642 default : throw ErrorMorpheo(_("Illegal state (dcache_rsp).")); break; 643 } 644 } 645 } 646 else 647 { 648 log_printf(TRACE,Load_store_unit,FUNCTION," * packet is a STORE"); 649 650 // TODO : les stores ne génére pas de réponse sauf quand c'est un bus error !!! 651 throw ERRORMORPHEO(FUNCTION,_("dcache_rsp : no respons to a write. (TODO : manage bus error to the store operation.)")); 652 } 653 654 } 655 656 // this register is to manage the priority of check -> Round robin 657 reg_LOAD_QUEUE_CHECK_PRIORITY = (reg_LOAD_QUEUE_CHECK_PRIORITY+1)%_param->_size_load_queue; 658 659 241 660 #if DEBUG>=DEBUG_TRACE 242 661 // ***** dump store queue 243 cout << "Dump store queue" << endl244 << "ptr_read : " << toString(static_cast<uint32_t>( internal_MEMORY_STORE_QUEUE_PTR_READ)) << endl;662 cout << "Dump STORE_QUEUE :" << endl 663 << "ptr_read : " << toString(static_cast<uint32_t>(reg_STORE_QUEUE_PTR_READ)) << endl; 245 664 246 665 for (uint32_t i=0; i<_param->_size_store_queue; i++) 247 666 { 248 uint32_t j = ( internal_MEMORY_STORE_QUEUE_PTR_READ+i)%_param->_size_store_queue;667 uint32_t j = (reg_STORE_QUEUE_PTR_READ+i)%_param->_size_store_queue; 249 668 cout << "{" << j << "}" << endl 250 669 << _store_queue[j] << endl; 251 670 } 671 672 // ***** dump speculative_access queue 673 cout << "Dump SPECULATIVE_ACCESS_QUEUE :" << endl; 674 675 for (uint32_t i=0; i<_param->_size_speculative_access_queue; i++) 676 { 677 uint32_t j = (*_speculative_access_queue_control)[i]; 678 cout << "{" << j << "}" << endl 679 << _speculative_access_queue[j] << endl; 680 } 681 682 // ***** dump load queue 683 cout << "Dump LOAD_QUEUE :" << endl 684 << "ptr_read_check_priority : " << toString(static_cast<uint32_t>(reg_LOAD_QUEUE_CHECK_PRIORITY)) << endl; 685 686 for (uint32_t i=0; i<_param->_size_load_queue; i++) 687 { 688 uint32_t j = i; 689 cout << "{" << j << "}" << endl 690 << _load_queue[j] << endl; 691 } 692 693 #endif 694 695 #ifdef STATISTICS 696 for (uint32_t i=0; i<_param->_size_store_queue; i++) 697 if (_store_queue[i]._state != STORE_QUEUE_EMPTY) 698 (*_stat_use_store_queue) ++; 699 for (uint32_t i=0; i<_param->_size_speculative_access_queue; i++) 700 if (_speculative_access_queue[i]._state != SPECULATIVE_ACCESS_QUEUE_EMPTY) 701 (*_stat_use_speculative_access_queue) ++; 702 for (uint32_t i=0; i<_param->_size_load_queue; i++) 703 if (_load_queue[i]._state != LOAD_QUEUE_EMPTY) 704 (*_stat_use_load_queue) ++; 252 705 #endif 253 706 } … … 266 719 }; // end namespace morpheo 267 720 #endif 268 //#endif
Note: See TracChangeset
for help on using the changeset viewer.