Changeset 227 for trunk/modules/vci_cc_vcache_wrapper_v4/caba/source
- Timestamp:
- Apr 12, 2012, 6:24:18 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/modules/vci_cc_vcache_wrapper_v4/caba/source/src/vci_cc_vcache_wrapper_v4.cpp
r225 r227 1422 1422 if ( not cache_hit ) // cache miss 1423 1423 { 1424 // in case of icache miss we send a request to CMD FSM, but we are1425 // blocked in IDLE state if the previous cleanup is not completed1426 if ( not r_icache_cleanup_req.read() )1427 {1428 1424 1429 1425 #ifdef INSTRUMENTATION 1430 1426 m_cpt_icache_miss++; 1431 1427 #endif 1432 r_icache_fsm = ICACHE_MISS_VICTIM; 1433 r_icache_miss_req = true; 1434 } 1435 break; 1428 r_icache_fsm = ICACHE_MISS_VICTIM; 1429 r_icache_miss_req = true; 1436 1430 } 1437 1431 else // cache hit … … 1632 1626 // when the selected slot is not empty 1633 1627 { 1634 if ( m_ireq.valid ) m_cost_ins_miss_frz++; 1635 1636 bool valid; 1637 size_t way; 1638 size_t set; 1639 paddr_t victim; 1640 1641 valid = r_icache.victim_select(r_icache_vci_paddr.read(), 1642 &victim, 1643 &way, 1644 &set); 1645 r_icache_miss_way = way; 1646 r_icache_miss_set = set; 1647 1648 if ( valid ) 1649 { 1650 r_icache_cleanup_req = true; 1651 r_icache_cleanup_line = victim; 1652 r_icache_fsm = ICACHE_MISS_INVAL; 1653 } 1654 else 1655 { 1656 r_icache_fsm = ICACHE_MISS_WAIT; 1628 m_cost_ins_miss_frz++; 1629 1630 size_t index; // unused 1631 bool hit = r_cleanup_buffer.hit( r_icache_vci_paddr.read()>>(uint32_log2(m_icache_words)+2), &index ); 1632 if ( not hit and not r_icache_cleanup_req.read() ) 1633 { 1634 bool valid; 1635 size_t way; 1636 size_t set; 1637 paddr_t victim; 1638 1639 valid = r_icache.victim_select(r_icache_vci_paddr.read(), 1640 &victim, 1641 &way, 1642 &set); 1643 r_icache_miss_way = way; 1644 r_icache_miss_set = set; 1645 1646 if ( valid ) 1647 { 1648 r_icache_cleanup_req = true; 1649 r_icache_cleanup_line = victim; 1650 r_icache_fsm = ICACHE_MISS_INVAL; 1651 } 1652 else 1653 { 1654 r_icache_fsm = ICACHE_MISS_WAIT; 1655 } 1657 1656 } 1658 1657 break; … … 2017 2016 tlb_inval_required = true; 2018 2017 r_dcache_tlb_inval_count = 0; 2019 r_dcache_tlb_inval_line = r_dcache_p1_paddr.read()>>(uint32_log2(m_dcache_words<<2)); 2018 r_dcache_tlb_inval_line = r_dcache_p1_paddr.read()>> 2019 (uint32_log2(m_dcache_words<<2)); 2020 2020 r_dcache_in_tlb[way*m_dcache_sets+set] = false; 2021 2021 } … … 2143 2143 // coherence transaction. 2144 2144 2145 // TLB inval required 2145 // TLB inval required after a write hit 2146 2146 if ( tlb_inval_required ) 2147 2147 { … … 2544 2544 m_cpt_dcache_spec_miss++; 2545 2545 #endif 2546 #if DEBUG_DCACHE 2547 if ( m_debug_dcache_fsm ) 2548 { 2549 std::cout << " <PROC.DCACHE_IDLE> Speculative access miss" << std::endl; 2550 } 2551 #endif 2546 2552 } 2547 2553 // if cache miss, try to get the missing line … … 2551 2557 m_cpt_dcache_miss++; 2552 2558 #endif 2553 // blocked in IDLE state if previous cleanup not completed 2554 if ( not r_dcache_cleanup_req.read() ) 2555 { 2556 r_dcache_vci_paddr = paddr; 2557 r_dcache_vci_miss_req = true; 2558 r_dcache_miss_type = PROC_MISS; 2559 r_dcache_fsm = DCACHE_MISS_VICTIM; 2560 } 2559 r_dcache_vci_paddr = paddr; 2560 r_dcache_vci_miss_req = true; 2561 r_dcache_miss_type = PROC_MISS; 2562 r_dcache_fsm = DCACHE_MISS_VICTIM; 2561 2563 } 2562 2564 // if cache hit return the data … … 3387 3389 // A cleanup request is generated for each valid line 3388 3390 // and we are blocked until the previous cleanup is completed 3389 // Finally, both the itlb and dtlb are reset, because3390 // all TLB entries (including global entries) must be invalidated.3391 // Finally, both the itlb and dtlb are flushed 3392 // (including global entries) 3391 3393 { 3392 3394 if ( not r_dcache_cleanup_req ) … … 3405 3407 } 3406 3408 3409 r_dcache_in_tlb[m_dcache_sets*way+set] = false; 3410 r_dcache_contains_ptd[m_dcache_sets*way+set] = false; 3411 3407 3412 r_dcache_flush_count = r_dcache_flush_count.read() + 1; 3408 3413 3409 if ( r_dcache_flush_count.read() == (m_dcache_sets*m_dcache_ways - 1) ) // last slot3414 if ( r_dcache_flush_count.read() == (m_dcache_sets*m_dcache_ways - 1) ) // last 3410 3415 { 3411 3416 r_dtlb.reset(); 3412 3417 r_itlb.reset(); 3413 for (size_t line = 0; line < m_dcache_ways*m_dcache_sets; line++)3414 {3415 r_dcache_in_tlb[line] = false;3416 r_dcache_contains_ptd[line] = false;3417 }3418 3418 r_dcache_fsm = DCACHE_IDLE; 3419 3419 m_drsp.valid = true; … … 3582 3582 } 3583 3583 //////////////////////// 3584 case DCACHE_MISS_VICTIM: // Selects a victim line 3585 // Set the r_dcache_cleanup_req flip-flop 3586 // when the selected slot is not empty 3587 { 3588 bool valid; 3589 size_t way; 3590 size_t set; 3591 paddr_t victim; 3592 3593 valid = r_dcache.victim_select( r_dcache_vci_paddr.read(), 3594 &victim, 3595 &way, 3596 &set ); 3597 r_dcache_miss_way = way; 3598 r_dcache_miss_set = set; 3599 3600 if ( valid ) 3601 { 3602 r_dcache_cleanup_req = true; 3603 r_dcache_cleanup_line = victim; 3604 r_dcache_fsm = DCACHE_MISS_INVAL; 3605 } 3606 else 3607 { 3608 r_dcache_fsm = DCACHE_MISS_WAIT; 3609 } 3584 case DCACHE_MISS_VICTIM: // Selects a victim line if there is no pending cleanup 3585 // on the missing line, and if a new cleanup can be posted. 3586 // Set the r_dcache_cleanup_req flip-flop if required 3587 { 3588 size_t index; // unused 3589 bool hit = r_cleanup_buffer.hit( r_dcache_vci_paddr.read()>>(uint32_log2(m_dcache_words)+2), &index ); 3590 if ( not hit and not r_dcache_cleanup_req.read() ) 3591 { 3592 bool valid; 3593 size_t way; 3594 size_t set; 3595 paddr_t victim; 3596 3597 valid = r_dcache.victim_select( r_dcache_vci_paddr.read(), 3598 &victim, 3599 &way, 3600 &set ); 3601 r_dcache_miss_way = way; 3602 r_dcache_miss_set = set; 3603 3604 if ( valid ) 3605 { 3606 r_dcache_cleanup_req = true; 3607 r_dcache_cleanup_line = victim; 3608 r_dcache_fsm = DCACHE_MISS_INVAL; 3609 } 3610 else 3611 { 3612 r_dcache_fsm = DCACHE_MISS_WAIT; 3613 } 3610 3614 3611 3615 #if DEBUG_DCACHE … … 3613 3617 { 3614 3618 std::cout << " <PROC.DCACHE_MISS_VICTIM> Select a slot:" << std::dec 3615 << " / way= " << way3616 << " / set= " << set3617 << " / valid= " << valid3618 << " / line= " << std::hex << victim << std::endl;3619 << " / WAY = " << way 3620 << " / SET = " << set 3621 << " / VALID = " << valid 3622 << " / LINE = " << std::hex << victim << std::endl; 3619 3623 } 3620 3624 #endif 3625 } 3621 3626 break; 3622 3627 } … … 3951 3956 ////////////////////////// 3952 3957 case DCACHE_DIRTY_SC_WAIT: // wait completion of SC for PTE Dirty bit 3953 // If thePTE update is a success, return to IDLE state.3954 // If the PTE update is a failure, invalidate the cache line3958 // If PTE update is a success, return to IDLE state. 3959 // If PTE update is a failure, invalidate cache line 3955 3960 // in DCACHE and invalidate the matching TLB entries. 3956 3961 { … … 3984 3989 #endif 3985 3990 } 3986 else // invalidate the cache line and TLBs 3987 { 3991 else // invalidate the cache line TLBs 3992 { 3993 3994 #if DEBUG_DCACHE 3995 if ( m_debug_dcache_fsm ) 3996 { 3997 std::cout << " <PROC.DCACHE_DIRTY_SC_WAIT> PTE modified : Inval cache line & TLBs" 3998 << std::endl; 3999 } 4000 #endif 3988 4001 paddr_t nline; 3989 4002 size_t way = r_dcache_dirty_way.read(); … … 3991 4004 bool hit; 3992 4005 3993 hit = r_dcache.inval( r_dcache_dirty_way.read(), 3994 r_dcache_dirty_set.read(), 3995 &nline ); 4006 hit = r_dcache.inval( way, 4007 set, 4008 &nline ); 4009 3996 4010 assert(hit && "PTE should still be in dcache"); 4011 3997 4012 // request cleanup 3998 4013 r_dcache_cleanup_req = true; … … 4007 4022 r_dcache_in_tlb[way*m_dcache_sets+set] = false; 4008 4023 } 4009 if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )// contains PTD4024 else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) // contains PTD 4010 4025 { 4011 4026 r_itlb.reset(); … … 4014 4029 r_dcache_fsm = DCACHE_IDLE; 4015 4030 } 4016 #if DEBUG_DCACHE 4017 if ( m_debug_dcache_fsm ) 4018 { 4019 std::cout << " <PROC.DCACHE_DIRTY_SC_WAIT> PTE modified : Inval cache line & TLBs" 4020 << std::endl; 4021 } 4022 #endif 4031 else 4032 { 4033 r_dcache_fsm = DCACHE_IDLE; 4034 } 4023 4035 } 4024 4036 } … … 4261 4273 4262 4274 // return to the calling state when TLB inval completed 4263 if ( r_dcache_tlb_inval_count.read() == ( m_dtlb_sets*m_dtlb_ways-1) )4275 if ( r_dcache_tlb_inval_count.read() == ((m_dtlb_sets*m_dtlb_ways)-1) ) 4264 4276 { 4265 4277 r_dcache_fsm = r_dcache_fsm_scan_save.read(); 4266 4278 } 4267 4279 r_dcache_tlb_inval_count = r_dcache_tlb_inval_count.read() + 1; 4280 break; 4268 4281 } 4269 4282 } // end switch r_dcache_fsm … … 4638 4651 } // end switch r_vci_rsp_fsm 4639 4652 4640 //////////////////////////////////////////////////////////////////////////////// 4641 // The CLEANUP FSM send the cleanup commands on the coherence network, 4642 // and supports simultaneous cleanup transactions, but two simultaneous 4643 // transactions mut address different cache lines. 4644 // Therefore, the line number is registered in an associative 4645 // registration buffer (Content Adressable Memory) by the CLEANUP FSM, 4646 // and the corresponding slot (identified by the VCI TRDID field) is cleared 4647 // when the cleanup transaction response is received. 4648 // It handles cleanup requests from both the DCACHE FSM & ICACHE FSM 4649 // with a round robin priority, and can support up to 4 simultaneous 4650 // cleanup transactions (4 slots in the registration buffer). 4651 // The r_dcache_cleanup_req (or r_icache_cleanup_req) flip-flops are reset 4652 // when the command has been sent. 4653 ///////////////////////////////////////////////////////////////////////////////////// 4654 // The CLEANUP FSM is in charge to send the cleanup commands on the coherence 4655 // network. It has two clients (DCACHE FSM and ICACHE FSM) that are served 4656 // with a round-robin priority. All cleanup commands are registered in the 4657 // r_cleanup_buffer, because we must avoid to send a Read Miss command 4658 // for line (X) if there is a pending cleanup for line (X): the r_cleanup_buffer 4659 // is tested by the ICACHE FSM and DCACHE FSM before posting a miss request. 4660 // The CLEANUP FSM resets the r_*cache_cleanup request flip-flops as soon as 4661 // the request has been sent and registered in the buffer. 4662 // The buffer itself is cleared when the cleanup response is received. 4663 // We use an assocative registration buffer (CAM) in order to support several 4664 // simultaneous cleanup transactions (up to 4 simultaneous clenups). 4653 4665 // The VCI TRDID field is used to distinguish data/instruction cleanups: 4654 4666 // - if data cleanup : TRDID = 2*index + 0 4655 4667 // - if instruction cleanup : TRDID = 2*index + 1 4656 //////////////////////////////////////////////////////////////////////////// 4668 ///////////////////////////////////////////////////////////////////////////////////// 4657 4669 4658 4670 switch ( r_cleanup_fsm.read() ) … … 4665 4677 if ( r_dcache_cleanup_req.read() ) // dcache request 4666 4678 { 4667 ok = r_cleanup_buffer. register_value( r_dcache_cleanup_line.read(),4668 4679 ok = r_cleanup_buffer.write( r_dcache_cleanup_line.read(), 4680 &index ); 4669 4681 if ( ok ) // successful registration 4670 4682 { 4683 r_dcache_cleanup_req = false; 4671 4684 r_cleanup_fsm = CLEANUP_DATA_GO; 4672 4685 r_cleanup_trdid = index<<1; … … 4675 4688 else if ( r_icache_cleanup_req.read() ) // icache request 4676 4689 { 4677 ok = r_cleanup_buffer. register_value( r_icache_cleanup_line.read(),4678 4690 ok = r_cleanup_buffer.write( r_icache_cleanup_line.read(), 4691 &index ); 4679 4692 if ( ok ) // successful registration 4680 4693 { 4694 r_icache_cleanup_req = false; 4681 4695 r_cleanup_fsm = CLEANUP_INS_GO; 4682 4696 r_cleanup_trdid = (index<<1) + 1; … … 4692 4706 if ( r_icache_cleanup_req.read() ) // icache request 4693 4707 { 4694 ok = r_cleanup_buffer. register_value( r_icache_cleanup_line.read(),4695 4708 ok = r_cleanup_buffer.write( r_icache_cleanup_line.read(), 4709 &index ); 4696 4710 if ( ok ) // successful registration 4697 4711 { 4712 r_icache_cleanup_req = false; 4698 4713 r_cleanup_fsm = CLEANUP_INS_GO; 4699 4714 r_cleanup_trdid = (index<<1) + 1; … … 4702 4717 else if ( r_dcache_cleanup_req.read() ) // dcache request 4703 4718 { 4704 ok = r_cleanup_buffer. register_value( r_dcache_cleanup_line.read(),4705 4719 ok = r_cleanup_buffer.write( r_dcache_cleanup_line.read(), 4720 &index ); 4706 4721 if ( ok ) // successful registration 4707 4722 { 4723 r_dcache_cleanup_req = false; 4708 4724 r_cleanup_fsm = CLEANUP_DATA_GO; 4709 4725 r_cleanup_trdid = index<<1; … … 4717 4733 if ( p_vci_ini_c.cmdack.read() ) 4718 4734 { 4719 r_dcache_cleanup_req = false;4720 4735 r_cleanup_fsm = CLEANUP_INS_IDLE; 4721 4736 … … 4731 4746 break; 4732 4747 } 4733 //////////////////// ////4748 //////////////////// 4734 4749 case CLEANUP_INS_GO: 4735 4750 { 4736 4751 if ( p_vci_ini_c.cmdack.read() ) 4737 4752 { 4738 r_icache_cleanup_req = false;4739 4753 r_cleanup_fsm = CLEANUP_DATA_IDLE; 4740 4754 … … 4753 4767 4754 4768 //////////////// Handling cleanup responses ////////////////// 4755 if ( p_vci_ini_c.rspval.read() ) // valid response4756 { 4757 r_cleanup_buffer. cancel_index( p_vci_ini_c.rtrdid.read() >> 1);4769 if ( p_vci_ini_c.rspval.read() ) 4770 { 4771 r_cleanup_buffer.inval( p_vci_ini_c.rtrdid.read() >> 1); 4758 4772 } 4759 4773
Note: See TracChangeset
for help on using the changeset viewer.