Ignore:
Timestamp:
Apr 12, 2012, 6:24:18 PM (13 years ago)
Author:
alain
Message:

Fixinng a bug in the handling of the generic_cam
to support pipelined cleanups.

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  
    14221422                if ( not cache_hit )    // cache miss
    14231423                {
    1424                     // in case of icache miss we send a request to CMD FSM, but we are
    1425                     // blocked in IDLE state if the previous cleanup is not completed
    1426                     if ( not r_icache_cleanup_req.read() )
    1427                     {
    14281424
    14291425#ifdef INSTRUMENTATION
    14301426m_cpt_icache_miss++;
    14311427#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;
    14361430                }
    14371431                else                    // cache hit
     
    16321626                                           // when the selected slot is not empty
    16331627    {
    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            }
    16571656        }
    16581657        break;
     
    20172016                tlb_inval_required       = true;
    20182017                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));
    20202020                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
    20212021            }
     
    21432143        //    coherence transaction.   
    21442144
    2145         // TLB inval required
     2145        // TLB inval required after a write hit
    21462146        if ( tlb_inval_required )
    21472147        {
     
    25442544m_cpt_dcache_spec_miss++;
    25452545#endif
     2546#if DEBUG_DCACHE
     2547if ( m_debug_dcache_fsm )
     2548{
     2549    std::cout << "  <PROC.DCACHE_IDLE> Speculative access miss" << std::endl;
     2550}
     2551#endif
    25462552                            }
    25472553                            // if cache miss, try to get the missing line
     
    25512557m_cpt_dcache_miss++;
    25522558#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;
    25612563                            }
    25622564                            // if cache hit return the data
     
    33873389                                // A cleanup request is generated for each valid line
    33883390                                // and we are blocked until the previous cleanup is completed
    3389                                 // Finally, both the itlb and dtlb are reset, because
    3390                                 // all TLB entries (including global entries) must be invalidated.
     3391                                // Finally, both the itlb and dtlb are flushed
     3392                                // (including global entries)
    33913393    {
    33923394        if ( not r_dcache_cleanup_req )
     
    34053407            }
    34063408
     3409            r_dcache_in_tlb[m_dcache_sets*way+set]       = false;
     3410            r_dcache_contains_ptd[m_dcache_sets*way+set] = false;
     3411
    34073412            r_dcache_flush_count = r_dcache_flush_count.read() + 1;
    34083413
    3409             if ( r_dcache_flush_count.read() == (m_dcache_sets*m_dcache_ways - 1) )     // last slot
     3414            if ( r_dcache_flush_count.read() == (m_dcache_sets*m_dcache_ways - 1) ) // last
    34103415            {
    34113416                r_dtlb.reset();   
    34123417                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                 }
    34183418                r_dcache_fsm = DCACHE_IDLE;
    34193419                m_drsp.valid = true;
     
    35823582    }
    35833583    ////////////////////////
    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            }
    36103614
    36113615#if DEBUG_DCACHE
     
    36133617{
    36143618    std::cout << "  <PROC.DCACHE_MISS_VICTIM> Select a slot:" << std::dec
    3615               << " / way = "   << way
    3616               << " / set = "   << set
    3617               << " / valid = "  << valid
    3618               << " / line = " << std::hex << victim << std::endl;
     3619              << " / WAY = "   << way
     3620              << " / SET = "   << set
     3621              << " / VALID = "  << valid
     3622              << " / LINE = " << std::hex << victim << std::endl;
    36193623}
    36203624#endif
     3625        }
    36213626        break;
    36223627    }
     
    39513956    //////////////////////////
    39523957    case DCACHE_DIRTY_SC_WAIT:          // wait completion of SC for PTE Dirty bit
    3953                                         // If the PTE update is a success, return to IDLE state.
    3954                                         // If the PTE update is a failure, invalidate the cache line
     3958                                        // If PTE update is a success, return to IDLE state.
     3959                                        // If PTE update is a failure, invalidate cache line
    39553960                                        // in DCACHE and invalidate the matching TLB entries.
    39563961    {
     
    39843989#endif
    39853990            }
    3986             else                                        // invalidate the cache line and TLBs
    3987             {
     3991            else                                        // invalidate the cache line TLBs
     3992            {
     3993
     3994#if DEBUG_DCACHE
     3995if ( 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
    39884001                paddr_t nline;
    39894002                size_t  way = r_dcache_dirty_way.read();
     
    39914004                bool hit;
    39924005
    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
    39964010                assert(hit && "PTE should still be in dcache");
     4011
    39974012                // request cleanup
    39984013                r_dcache_cleanup_req  = true;
     
    40074022                    r_dcache_in_tlb[way*m_dcache_sets+set] = false;
    40084023                } 
    4009                 if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )     // contains PTD
     4024                else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) // contains PTD
    40104025                {
    40114026                    r_itlb.reset();
     
    40144029                    r_dcache_fsm = DCACHE_IDLE;
    40154030                }
    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                }
    40234035            }
    40244036        }
     
    42614273
    42624274        // 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) )
    42644276        {
    42654277            r_dcache_fsm = r_dcache_fsm_scan_save.read();
    42664278        }
    42674279        r_dcache_tlb_inval_count = r_dcache_tlb_inval_count.read() + 1;
     4280        break;
    42684281    }   
    42694282    } // end switch r_dcache_fsm
     
    46384651    } // end switch r_vci_rsp_fsm
    46394652
    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).
    46534665    // The VCI TRDID field is used to distinguish data/instruction cleanups:
    46544666    // - if data cleanup        : TRDID = 2*index + 0
    46554667    // - if instruction cleanup : TRDID = 2*index + 1
    4656     ////////////////////////////////////////////////////////////////////////////
     4668    /////////////////////////////////////////////////////////////////////////////////////
    46574669
    46584670    switch ( r_cleanup_fsm.read() )
     
    46654677            if ( r_dcache_cleanup_req.read() )      // dcache request
    46664678            {
    4667                 ok = r_cleanup_buffer.register_value( r_dcache_cleanup_line.read(),
    4668                                                       &index );   
     4679                ok = r_cleanup_buffer.write( r_dcache_cleanup_line.read(),
     4680                                             &index );   
    46694681                if ( ok )   // successful registration
    46704682                {
     4683                    r_dcache_cleanup_req = false;
    46714684                    r_cleanup_fsm   = CLEANUP_DATA_GO;
    46724685                    r_cleanup_trdid = index<<1;
     
    46754688            else if ( r_icache_cleanup_req.read() ) // icache request
    46764689            {
    4677                 ok = r_cleanup_buffer.register_value( r_icache_cleanup_line.read(),
    4678                                                       &index );   
     4690                ok = r_cleanup_buffer.write( r_icache_cleanup_line.read(),
     4691                                             &index );   
    46794692                if ( ok )   // successful registration
    46804693                {
     4694                    r_icache_cleanup_req = false;
    46814695                    r_cleanup_fsm   = CLEANUP_INS_GO;
    46824696                    r_cleanup_trdid = (index<<1) + 1;
     
    46924706            if ( r_icache_cleanup_req.read() )      // icache request
    46934707            {
    4694                 ok = r_cleanup_buffer.register_value( r_icache_cleanup_line.read(),
    4695                                                       &index );   
     4708                ok = r_cleanup_buffer.write( r_icache_cleanup_line.read(),
     4709                                             &index );   
    46964710                if ( ok )   // successful registration
    46974711                {
     4712                    r_icache_cleanup_req = false;
    46984713                    r_cleanup_fsm   = CLEANUP_INS_GO;
    46994714                    r_cleanup_trdid = (index<<1) + 1;
     
    47024717            else if ( r_dcache_cleanup_req.read() ) // dcache request
    47034718            {
    4704                 ok = r_cleanup_buffer.register_value( r_dcache_cleanup_line.read(),
    4705                                                       &index );   
     4719                ok = r_cleanup_buffer.write( r_dcache_cleanup_line.read(),
     4720                                             &index );   
    47064721                if ( ok )   // successful registration
    47074722                {
     4723                    r_dcache_cleanup_req = false;
    47084724                    r_cleanup_fsm   = CLEANUP_DATA_GO;
    47094725                    r_cleanup_trdid = index<<1;
     
    47174733            if ( p_vci_ini_c.cmdack.read() )
    47184734            {
    4719                 r_dcache_cleanup_req = false;
    47204735                r_cleanup_fsm        = CLEANUP_INS_IDLE;
    47214736
     
    47314746            break;
    47324747        }
    4733         ////////////////////////
     4748        ////////////////////
    47344749        case CLEANUP_INS_GO:
    47354750        {
    47364751            if ( p_vci_ini_c.cmdack.read() )
    47374752            {
    4738                 r_icache_cleanup_req = false;
    47394753                r_cleanup_fsm        = CLEANUP_DATA_IDLE;
    47404754
     
    47534767
    47544768    //////////////// Handling  cleanup responses //////////////////
    4755     if ( p_vci_ini_c.rspval.read() )    // valid response
    4756     {
    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);
    47584772    }
    47594773
Note: See TracChangeset for help on using the changeset viewer.