Changeset 204 for trunk/modules/vci_cc_vcache_wrapper_v4
- Timestamp:
- Mar 8, 2012, 8:48:53 AM (13 years ago)
- Location:
- trunk/modules/vci_cc_vcache_wrapper_v4/caba/source
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/modules/vci_cc_vcache_wrapper_v4/caba/source/include/vci_cc_vcache_wrapper_v4.h
r203 r204 35 35 #include "generic_fifo.h" 36 36 #include "generic_tlb.h" 37 #include "generic_cache.h" 37 38 #include "generic_cam.h" 38 #include "generic_cache.h"39 39 #include "vci_initiator.h" 40 40 #include "vci_target.h" … … 113 113 DCACHE_XTN_DC_INVAL_VA, 114 114 DCACHE_XTN_DC_INVAL_PA, 115 DCACHE_XTN_DC_INVAL_ WAIT,115 DCACHE_XTN_DC_INVAL_END, 116 116 DCACHE_XTN_DC_INVAL_GO, 117 117 DCACHE_XTN_DT_INVAL, … … 121 121 DCACHE_WRITE_SC_WAIT, 122 122 DCACHE_WRITE_UNC_WAIT, 123 // handling processor miss requests123 // handling processor miss requests 124 124 DCACHE_MISS_VICTIM, 125 125 DCACHE_MISS_INVAL, … … 133 133 DCACHE_CC_INVAL, 134 134 DCACHE_CC_UPDT, 135 DCACHE_CC_WAIT, 135 // handling TLB inval (after a coherence or XTN request) 136 DCACHE_INVAL_TLB_SCAN, 136 137 }; 137 138 … … 173 174 TGT_RSP_ICACHE, 174 175 TGT_RSP_DCACHE, 175 };176 177 enum inval_itlb_fsm_state_e {178 INVAL_ITLB_IDLE,179 INVAL_ITLB_SCAN,180 };181 182 enum inval_dtlb_fsm_state_e {183 INVAL_DTLB_IDLE,184 INVAL_DTLB_SCAN,185 176 }; 186 177 … … 386 377 sc_signal<size_t> r_dcache_p1_tlb_set; // selected set (from dtlb) 387 378 sc_signal<paddr_t> r_dcache_p1_tlb_nline; // nline value (from dtlb) 388 // registers written in P2 stage (used in P3 stage) 379 sc_signal<bool> r_dcache_p1_tlb_big; // big page bit (from dtlb) 380 // registers written in P2 stage (used in long write) 389 381 sc_signal<uint32_t> r_dcache_p2_vaddr; // virtual address (from proc) 390 382 sc_signal<size_t> r_dcache_p2_tlb_way; // selected way in dtlb … … 395 387 sc_signal<size_t> r_dcache_p2_pte_set; // selected set in dcache 396 388 sc_signal<size_t> r_dcache_p2_pte_word; // selected word in dcache 397 sc_signal<size_t> r_dcache_p2_pte _flags;// pte value read in dcache389 sc_signal<size_t> r_dcache_p2_pte; // pte value read in dcache 398 390 399 391 // communication between DCACHE FSM and VCI_CMD FSM … … 445 437 sc_signal<paddr_t> r_dcache_ll_vaddr; // LL reserved address 446 438 447 // communication between DCACHE FSM and INVAL_ITLB/INVAL_DTLB FSMs448 sc_signal<bool> r_dcache_itlb_inval_req; // inval request of one or several TLB entries449 sc_signal<bool> r_dcache_dtlb_inval_req; // inval request of one or several TLB entries;439 // ITLB and DTLB invalidation 440 sc_signal<bool> r_dcache_itlb_inval_req; // inval request for itlb 441 sc_signal<bool> r_dcache_dtlb_inval_req; // inval request for dtlb 450 442 sc_signal<paddr_t> r_dcache_tlb_inval_line; // line index 443 sc_signal<size_t> r_dcache_tlb_inval_count; // tlb entry counter 451 444 452 445 // communication between DCACHE FSM and ICACHE FSM … … 510 503 uint32_t *r_tgt_buf; // cache line word buffer 511 504 vci_be_t *r_tgt_be; // cache line be buffer 512 513 ///////////////////////////////////514 // INVAL_ITLB FSM REGISTERS515 ///////////////////////////////////516 sc_signal<int> r_inval_itlb_fsm; // state register517 sc_signal<size_t> r_inval_itlb_count; // counter to scan all itlb entries518 519 ///////////////////////////////////520 // INVAL_DTLB FSM REGISTERS521 ///////////////////////////////////522 sc_signal<int> r_inval_dtlb_fsm; //state register523 sc_signal<size_t> r_inval_dtlb_count; // counter to scan all dtlb entries524 505 525 506 ////////////////////////////////////////////////////////////////// -
trunk/modules/vci_cc_vcache_wrapper_v4/caba/source/src/vci_cc_vcache_wrapper_v4.cpp
r203 r204 32 32 #define DEBUG_ICACHE 1 33 33 #define DEBUG_CLEANUP 0 34 #define DEBUG_INVAL_ITLB 135 #define DEBUG_INVAL_DTLB 136 34 37 35 namespace soclib { … … 86 84 "DCACHE_XTN_DC_INVAL_VA", 87 85 "DCACHE_XTN_DC_INVAL_PA", 88 "DCACHE_XTN_DC_INVAL_ WAIT",86 "DCACHE_XTN_DC_INVAL_END", 89 87 "DCACHE_XTN_DC_INVAL_GO", 90 88 "DCACHE_XTN_DT_INVAL", … … 106 104 "DCACHE_CC_INVAL", 107 105 "DCACHE_CC_UPDT", 108 "DCACHE_CC_WAIT", 106 107 "DCACHE_INVAL_TLB_SCAN", 109 108 }; 110 109 const char *cmd_fsm_state_str[] = { … … 142 141 "TGT_RSP_DCACHE", 143 142 }; 144 const char *inval_itlb_fsm_state_str[] = {145 "INVAL_ITLB_IDLE",146 "INVAL_ITLB_SCAN",147 };148 const char *inval_dtlb_fsm_state_str[] = {149 "INVAL_DTLB_IDLE",150 "INVAL_DTLB_SCAN",151 };152 143 } 153 144 … … 280 271 r_dcache_p1_tlb_set("r_dcache_p1_tlb_set"), 281 272 r_dcache_p1_tlb_nline("r_dcache_p1_tlb_nline"), 273 r_dcache_p1_tlb_big("r_dcache_p1_tlb_big"), 282 274 283 275 r_dcache_p2_vaddr("r_dcache_p2_vaddr"), … … 289 281 r_dcache_p2_pte_set("r_dcache_p2_pte_set"), 290 282 r_dcache_p2_pte_word("r_dcache_p2_pte_word"), 291 r_dcache_p2_pte _flags("r_dcache_p2_pte_flags"),283 r_dcache_p2_pte("r_dcache_p2_pte"), 292 284 293 285 r_dcache_vci_paddr("r_dcache_vci_paddr"), … … 333 325 r_dcache_dtlb_inval_req("r_dcache_dtlb_inval_req"), 334 326 r_dcache_tlb_inval_line("r_dcache_tlb_inval_line"), 327 r_dcache_tlb_inval_count("r_dcache_tlb_inval_count"), 335 328 336 329 r_dcache_xtn_req("r_dcache_xtn_req"), … … 373 366 r_tgt_dcache_rsp("r_tgt_dcache_rsp"), 374 367 375 r_inval_itlb_fsm("r_inval_itlb_fsm"),376 r_inval_itlb_count("r_inval_itlb_count"),377 378 r_inval_dtlb_fsm("r_inval_dtlb_fsm"),379 r_inval_dtlb_count("r_inval_dtlb_count"),380 381 368 r_iss(this->name(), proc_id), 382 369 r_wbuf("wbuf", wbuf_nwords, wbuf_nlines, dcache_words ), … … 394 381 assert( (icache_words == dcache_words) and 395 382 "icache_words and dcache_words parameters must be equal"); 383 384 assert( (itlb_sets == dtlb_sets) and 385 "itlb_sets and dtlb_sets parameters must be etqual"); 386 387 assert( (itlb_ways == dtlb_ways) and 388 "itlb_ways and dtlb_ways parameters must be etqual"); 396 389 397 390 r_mmu_params = (uint32_log2(m_dtlb_ways) << 29) | (uint32_log2(m_dtlb_sets) << 25) | … … 489 482 << " | " << cmd_fsm_state_str[r_vci_cmd_fsm.read()] 490 483 << " | " << rsp_fsm_state_str[r_vci_rsp_fsm.read()] 491 << " | " << tgt_fsm_state_str[r_tgt_fsm.read()] << std::endl; 492 std::cout << " " << cleanup_fsm_state_str[r_cleanup_fsm.read()] 493 << " | " << inval_itlb_fsm_state_str[r_inval_itlb_fsm] 494 << " | " << inval_dtlb_fsm_state_str[r_inval_dtlb_fsm]; 484 << " | " << tgt_fsm_state_str[r_tgt_fsm.read()] 485 << " | " << cleanup_fsm_state_str[r_cleanup_fsm.read()]; 495 486 if (r_dcache_p0_valid.read() ) std::cout << " | P1_WRITE"; 496 487 if (r_dcache_p1_valid.read() ) std::cout << " | P2_WRITE"; … … 702 693 r_vci_rsp_fsm = RSP_IDLE; 703 694 r_tgt_fsm = TGT_IDLE; 704 r_inval_itlb_fsm = INVAL_ITLB_IDLE;705 r_inval_dtlb_fsm = INVAL_DTLB_IDLE;706 695 r_cleanup_fsm = CLEANUP_DATA_IDLE; 707 696 … … 743 732 r_dcache_ll_valid = false; 744 733 745 // No request from DCACHE FSM to INVAL TLB FSMs734 // No TLB inval requestis 746 735 r_dcache_itlb_inval_req = false; 747 736 r_dcache_dtlb_inval_req = false; … … 770 759 m_debug_icache_fsm = false; 771 760 m_debug_cleanup_fsm = false; 772 m_debug_inval_itlb_fsm = false;773 m_debug_inval_dtlb_fsm = false;774 761 775 762 /* … … 906 893 m_debug_icache_fsm = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok; 907 894 m_debug_dcache_fsm = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok; 908 m_debug_inval_itlb_fsm = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok;909 m_debug_inval_dtlb_fsm = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok;910 895 911 896 ///////////////////////////////////////////////////////////////////// … … 1911 1896 m_irsp_instruction = irsp.instruction; 1912 1897 m_irsp_error = irsp.error; 1913 1914 ////////////////////////////////////////////////////////////////////////////////////1915 // INVAL ITLB FSM1916 // This FSM works in parallel with the ICACHE FSM.1917 // When the r_dcache_itlb_inval_req flip-flop is activated by the DCACHE FSM1918 // it scans sequencially all entries in the ITLB, and invalidates the1919 // entries matching the evicted line.1920 // It signals the completion of invalidation by reseting r_dcache_itlb_inval_req.1921 ////////////////////////////////////////////////////////////////////////////////////1922 1923 switch(r_inval_itlb_fsm)1924 {1925 /////////////////////1926 case INVAL_ITLB_IDLE:1927 {1928 if ( r_dcache_itlb_inval_req.read() )1929 {1930 r_itlb.reset_bypass(r_dcache_tlb_inval_line.read());1931 r_inval_itlb_count = 0;1932 r_inval_itlb_fsm = INVAL_ITLB_SCAN;1933 1934 #if DEBUG_INVAL_ITLB1935 if ( m_debug_inval_itlb_fsm )1936 {1937 std::cout << " <PROC.INVAL_ITLB_IDLE> Invalidate request for line "1938 << std::hex << r_dcache_tlb_inval_line.read() << std::endl;1939 r_itlb.print();1940 }1941 #endif1942 }1943 break;1944 }1945 /////////////////////1946 case INVAL_ITLB_SCAN:1947 {1948 paddr_t line = r_dcache_tlb_inval_line.read(); // nline1949 size_t way = r_inval_itlb_count.read()/m_itlb_sets; // way1950 size_t set = r_inval_itlb_count.read()%m_itlb_sets; // set1951 1952 bool ok = r_itlb.inval( line,1953 way,1954 set );1955 1956 #if DEBUG_INVAL_ITLB1957 if ( m_debug_inval_itlb_fsm )1958 {1959 std::cout << " <PROC.INVAL_ITLB_SCAN>" << std::hex1960 << " line = " << line << std::dec1961 << " / set = " << set1962 << " / way = " << way;1963 if ( ok ) std::cout << " / HIT" << std::endl;1964 else std::cout << " / MISS" << std::endl;1965 }1966 #endif1967 1968 r_inval_itlb_count = r_inval_itlb_count.read() + 1;1969 if ( r_inval_itlb_count.read() == (m_itlb_sets*m_itlb_ways - 1) )1970 {1971 r_inval_itlb_fsm = INVAL_ITLB_IDLE;1972 r_dcache_itlb_inval_req = false;1973 }1974 break;1975 }1976 } // end switch r_inval_itlb_fsm1977 1898 1978 1899 //////////////////////////////////////////////////////////////////////////////////// … … 2067 1988 // Three actions are executed in this P2 stage: 2068 1989 // - If r_dcache_p1_updt_cache is true, we update the local copy in dcache. 2069 // - If the modified cache line has copies in itlb (resp. dtlb), and if the 2070 // INVAL_ITLB (resp. INVAL_DTLB) FSM is idle, we launch the TLB invalidate 2071 // operation. This operation is NOT blocking for the processor: the DCACHE FSM 2072 // doesn't wait the TLB invalidate completion to handle processor requests. 2073 // If the INVAL_ITLB (resp INVAL_DTLB) FSM is already processintg a previous 2074 // invalidation request, the DCACHE FSM is frosen until completion of the 2075 // previous TLB invalidate operation. 1990 // - If the modified cache line has copies in TLBs, we launch a TLB invalidate 1991 // operation, that is blocking for the processor, because we switch to 1992 // DCACHE_INVAL_TLB 2076 1993 // - If the PTE dirty bit must be updated, we start a "long write", that is 2077 1994 // blocking for the processor, because we switch to the DCACHE_WRITE_SET_DIRTY 2078 // state, and the number of cycles can be large...2079 1995 2080 1996 bool long_write_set_dirty = false; 2081 bool tlb_inval_ frozen= false;1997 bool tlb_inval_required = false; 2082 1998 2083 1999 if ( r_dcache_p1_valid.read() ) // P2 stage activated 2084 2000 { 2085 2001 bool cache_updt = r_dcache_p1_updt_cache.read(); 2086 size_t cache_way= r_dcache_p1_cache_way.read();2087 size_t cache_set= r_dcache_p1_cache_set.read();2088 size_t cache_word= r_dcache_p1_cache_word.read();2002 size_t way = r_dcache_p1_cache_way.read(); 2003 size_t set = r_dcache_p1_cache_set.read(); 2004 size_t word = r_dcache_p1_cache_word.read(); 2089 2005 uint32_t wdata = r_dcache_p1_wdata.read(); 2090 2006 vci_be_t be = r_dcache_p1_be.read(); 2091 2007 2092 // The PTE address is used when the PTE dirty bit must be set. 2093 // It is the concatenation of the nline value (from dtlb) 2094 // and the word index (from virtual address) 2095 paddr_t pte_paddr = (paddr_t)(r_dcache_p1_tlb_nline.read()*(m_dcache_words<<2)) 2096 | (paddr_t)(r_dcache_p1_vaddr.read()%(m_dcache_words<<2)); 2097 2098 // The line index is used when a TLB inval is required 2099 paddr_t inval_line = r_dcache_p1_paddr.read()>>(uint32_log2(m_dcache_words<<2)); 2100 2101 // checking dcache update 2008 // update dcache if required 2102 2009 if ( cache_updt ) 2103 2010 { 2104 r_dcache.write( cache_way,2105 cache_set,2106 cache_word,2011 r_dcache.write( way, 2012 set, 2013 word, 2107 2014 wdata, 2108 2015 be ); … … 2110 2017 m_cpt_dcache_data_write++; 2111 2018 #endif 2112 2113 // Checking copies in TLBs 2114 bool itlb_inval = ( (r_mmu_mode.read() & INS_TLB_MASK) and 2115 r_dcache_in_itlb[cache_way*m_dcache_sets+cache_set] ); 2116 bool dtlb_inval = ( (r_mmu_mode.read() & DATA_TLB_MASK) and 2117 r_dcache_in_dtlb[cache_way*m_dcache_sets+cache_set] ); 2118 2119 if ( (dtlb_inval and r_dcache_dtlb_inval_req.read() ) or 2120 (itlb_inval and r_dcache_itlb_inval_req.read() ) ) // at least one FSM not idle 2019 // cache update can require itlb & dtlb inval 2020 bool inval_itlb = false; 2021 bool inval_dtlb = false; 2022 2023 if ( (r_mmu_mode.read() & DATA_TLB_MASK) and r_dcache_in_dtlb[way*m_dcache_sets+set] ) 2121 2024 { 2122 tlb_inval_frozen = true; 2025 r_dcache_in_dtlb[way*m_dcache_sets+set] = false; 2026 inval_dtlb = true; 2123 2027 } 2124 else // requested FSM idle 2028 if ( (r_mmu_mode.read() & INS_TLB_MASK) and r_dcache_in_itlb[m_dcache_sets*way+set] ) 2029 { 2030 r_dcache_in_itlb[way*m_dcache_sets+set] = false; 2031 inval_itlb = true; 2032 } 2033 if ( inval_itlb or inval_dtlb ) 2125 2034 { 2126 r_dcache_tlb_inval_line = inval_line;2127 r_dcache_itlb_inval_req = itlb_inval;2128 r_dcache_dtlb_inval_req = dtlb_inval;2129 r_dcache_in_itlb[cache_way*m_dcache_sets+cache_set] = false;2130 r_dcache_in_dtlb[cache_way*m_dcache_sets+cache_set] = false; 2035 tlb_inval_required = true; 2036 r_dcache_itlb_inval_req = inval_itlb; 2037 r_dcache_dtlb_inval_req = inval_dtlb; 2038 r_dcache_tlb_inval_count = 0; 2039 r_dcache_tlb_inval_line = r_dcache_p1_paddr.read()>>(uint32_log2(m_dcache_words<<2)); 2131 2040 } 2132 2041 } // end dcache update 2133 2042 2134 // checking dirty bit update2043 // checking if dirty bit update is required 2135 2044 if ( r_dcache_p1_set_dirty.read() ) 2136 2045 { 2137 long_write_set_dirty = true;2046 long_write_set_dirty = true; 2138 2047 r_dcache_p2_vaddr = r_dcache_p1_vaddr.read(); 2139 2048 r_dcache_p2_set_dirty = r_dcache_p1_set_dirty.read(); 2140 2049 r_dcache_p2_tlb_way = r_dcache_p1_tlb_way.read(); 2141 2050 r_dcache_p2_tlb_set = r_dcache_p1_tlb_set.read(); 2142 r_dcache_p2_pte_paddr = pte_paddr; 2051 // The PTE physical address is the concatenation of the nline value (from dtlb), 2052 // with the word index (obtained from the proper bits of the virtual address) 2053 if ( r_dcache_p1_tlb_big.read() ) // PTE1 2054 { 2055 r_dcache_p2_pte_paddr = (paddr_t)(r_dcache_p1_tlb_nline.read()*(m_dcache_words<<2)) | 2056 (paddr_t)((r_dcache_p1_vaddr.read()>>19) & 0x3c); 2057 } 2058 else // PTE2 2059 { 2060 r_dcache_p2_pte_paddr = (paddr_t)(r_dcache_p1_tlb_nline.read()*(m_dcache_words<<2)) | 2061 (paddr_t)((r_dcache_p1_vaddr.read()>>10) & 0x3c); 2062 } 2143 2063 } 2144 2064 … … 2148 2068 if ( cache_updt ) 2149 2069 std::cout << " <PROC.DCACHE_IDLE> P2 stage: cache update" << std::dec 2150 << " / way = " << cache_way2151 << " / set = " << cache_set2152 << " / word = " << cache_word << std::hex2070 << " / way = " << way 2071 << " / set = " << set 2072 << " / word = " << word << std::hex 2153 2073 << " / wdata = " << wdata 2154 2074 << " / be = " << be << std::endl; 2155 2075 if ( long_write_set_dirty ) 2156 2076 std::cout << " <PROC.DCACHE_IDLE> P2 stage: dirty bit update required" 2157 << " / pte_paddr = " << std::hex << pte_paddr<< std::endl;2077 << " / pte_paddr = " << std::hex << r_dcache_p2_pte_paddr.read() << std::endl; 2158 2078 } 2159 2079 #endif … … 2172 2092 // if there is local copy in dcache, or if the PTE dirty bit must be set. 2173 2093 2174 if ( r_dcache_p0_valid.read() and not tlb_inval_ frozen) // P1 stage activated2094 if ( r_dcache_p0_valid.read() and not tlb_inval_required ) // P1 stage activated 2175 2095 { 2176 2096 // write not cacheable, and previous non cacheable write registered … … 2234 2154 r_dcache_p1_tlb_set = r_dcache_p0_tlb_set; 2235 2155 r_dcache_p1_tlb_nline = r_dcache_p0_tlb_nline; 2156 r_dcache_p1_tlb_big = r_dcache_p0_tlb_big; 2236 2157 r_dcache_p1_cache_way = cache_way; 2237 2158 r_dcache_p1_cache_set = cache_set; … … 2249 2170 2250 2171 ///////////////////////////////////////////////////////////////////////////// 2251 // handling P0 writepipe-line stage2172 // handling P0 pipe-line stage 2252 2173 // This stage is controlling the DCACHE FSM state register: 2253 // - the FSM is frozen if a TLB invalidate operation must be delayed,2254 // - the long write requests have the highest priority,2174 // - the TLB invalidate requests have the highest priority, 2175 // - then the long write requests, 2255 2176 // - then the external coherence requests, 2256 2177 // - then the itlb miss requests, … … 2263 2184 bool p0_valid = false; // default value 2264 2185 2265 // TLB inval delayed 2266 if ( tlb_inval_frozen ) 2267 { 2268 break; 2186 // TLB inval required 2187 if ( tlb_inval_required ) 2188 { 2189 r_dcache_fsm_save = DCACHE_IDLE; 2190 r_dcache_fsm = DCACHE_INVAL_TLB_SCAN; 2269 2191 } 2270 2192 … … 2278 2200 else if ( r_tgt_dcache_req.read() ) 2279 2201 { 2280 r_dcache_fsm = DCACHE_CC_CHECK;2281 2202 r_dcache_fsm_save = DCACHE_IDLE; 2203 r_dcache_fsm = DCACHE_CC_CHECK; 2282 2204 } 2283 2205 … … 2747 2669 } 2748 2670 ///////////////////// 2749 case DCACHE_TLB_MISS: // This is the entry point for the sub-fsm handling tlb miss.2671 case DCACHE_TLB_MISS: // This is the entry point for the sub-fsm handling all tlb miss. 2750 2672 // - Input arguments are r_dcache_tlb_vaddr & r_dcache_tlb_ins 2751 // - It try to find the missing TLB entry in dcache,2673 // - The sub-fsm access the dcache to find the missing TLB entry, 2752 2674 // and activates the cache miss procedure in case of miss. 2753 2675 // - It bypass the first level page table access if possible. … … 2778 2700 r_dcache_fsm = DCACHE_TLB_PTE1_GET; 2779 2701 } 2780 else // Try to read directlythe PTE2 in dcache2702 else // Try to read the PTE2 in dcache 2781 2703 { 2782 2704 paddr = (paddr_t)ptba << PAGE_K_NBITS | … … 2818 2740 m_cpt_dcache_dir_read++; 2819 2741 #endif 2820 if ( hit ) // requesthit in dcache2742 if ( hit ) // hit in dcache 2821 2743 { 2822 2744 if ( not (entry & PTE_V_MASK) ) // unmapped … … 2841 2763 if ( m_debug_dcache_fsm ) 2842 2764 { 2843 std::cout << " <PROC.DCACHE_TLB_PTE1_GET> HIT in dcache, but unmapped:" 2844 << std::dec << " way = " << way 2765 std::cout << " <PROC.DCACHE_TLB_PTE1_GET> HIT in dcache, but unmapped" 2766 << std::hex << " / paddr = " << r_dcache_tlb_paddr.read() 2767 << std::dec << " / way = " << way 2845 2768 << std::dec << " / set = " << set 2846 2769 << std::dec << " / word = " << word … … 2872 2795 if ( m_debug_dcache_fsm ) 2873 2796 { 2874 std::cout << " <PROC.DCACHE_TLB_PTE1_GET> HIT in dcache " 2875 << std::dec << " way = " << way 2797 std::cout << " <PROC.DCACHE_TLB_PTE1_GET> HIT in dcache" 2798 << std::hex << " / paddr = " << r_dcache_tlb_paddr.read() 2799 << std::dec << " / way = " << way 2876 2800 << std::dec << " / set = " << set 2877 2801 << std::dec << " / word = " << word … … 2882 2806 else // PTE1 : update the TLB 2883 2807 { 2884 if ( r_dcache_tlb_ins.read() ) 2885 r_dcache_in_itlb[m_icache_sets*way+set] = true; 2886 else 2887 r_dcache_in_dtlb[m_dcache_sets*way+set] = true; 2808 if ( r_dcache_tlb_ins.read() ) r_dcache_in_itlb[m_icache_sets*way+set] = true; 2809 else r_dcache_in_dtlb[m_dcache_sets*way+set] = true; 2888 2810 r_dcache_tlb_pte_flags = entry; 2889 2811 r_dcache_tlb_cache_way = way; … … 2895 2817 if ( m_debug_dcache_fsm ) 2896 2818 { 2897 std::cout << " <PROC.DCACHE_TLB_PTE1_GET> HIT in dcache:" 2898 << std::dec << " way = " << way 2819 std::cout << " <PROC.DCACHE_TLB_PTE1_GET> HIT in dcache" 2820 << std::hex << " / paddr = " << r_dcache_tlb_paddr.read() 2821 << std::dec << " / way = " << way 2899 2822 << std::dec << " / set = " << set 2900 2823 << std::dec << " / word = " << word … … 3263 3186 // request a SC transaction to CMD FSM 3264 3187 { 3188 #if DEBUG_DCACHE 3189 if ( m_debug_dcache_fsm ) 3190 { 3191 std::cout << " <PROC.DCACHE_TLB_SC_UPDT> Update dcache: (L/R) bit" << std::endl; 3192 } 3193 #endif 3265 3194 r_dcache.write(r_dcache_tlb_cache_way.read(), 3266 3195 r_dcache_tlb_cache_set.read(), … … 3276 3205 } 3277 3206 //////////////////////// 3278 case DCACHE_TLB_SC_WAIT: // wait response to SC transaction from RSP FSM 3279 // we consume the response, and exit the sub-fsm. 3280 // we don't analyse the response, because 3281 // we don't care if the L/R bit update is not done 3282 // we must take the coherence requests because 3207 case DCACHE_TLB_SC_WAIT: // Waiting a response to SC transaction. 3208 // We consume the response in rsp FIFO, 3209 // and exit the sub-fsm, but we don't 3210 // analyse the response, because we don't 3211 // care if the L/R bit update is not done. 3212 // We must take the coherence requests because 3283 3213 // there is a risk of dead-lock 3284 3214 … … 3292 3222 } 3293 3223 3294 if ( not r_dcache_vci_sc_req.read() ) // response available 3295 { 3296 if ( r_vci_rsp_data_error.read() ) r_vci_rsp_data_error = false; 3297 else if ( r_vci_rsp_fifo_dcache.rok() ) vci_rsp_fifo_dcache_get = true; 3298 else 3299 { 3300 assert( false and "rsp_fifo should not be empty in DCACHE_TLB_SC_WAIT state" ); 3301 } 3302 r_dcache_fsm = DCACHE_TLB_RETURN; 3224 if ( r_vci_rsp_data_error.read() ) // bus error 3225 { 3226 std::cout << "BUS ERROR in DCACHE_TLB_SC_WAIT state" << std::endl; 3227 std::cout << "This should not happen in this state" << std::endl; 3228 exit(0); 3229 } 3230 else if ( r_vci_rsp_fifo_dcache.rok() ) // response available 3231 { 3232 #if DEBUG_DCACHE 3233 if ( m_debug_dcache_fsm ) 3234 { 3235 std::cout << " <PROC.DCACHE_TLB_SC_WAIT> SC response received" << std::endl; 3236 } 3237 #endif 3238 vci_rsp_fifo_dcache_get = true; 3239 r_dcache_fsm = DCACHE_TLB_RETURN; 3303 3240 } 3304 3241 break; 3305 3242 } 3306 3243 /////////////////////// 3307 case DCACHE_TLB_RETURN: // return to caller state depending on the tlb miss type 3308 { 3244 case DCACHE_TLB_RETURN: // return to caller depending on tlb miss type 3245 { 3246 #if DEBUG_DCACHE 3247 if ( m_debug_dcache_fsm ) 3248 { 3249 std::cout << " <PROC.DCACHE_TLB_RETURN> TLB MISS completed" << std::endl; 3250 } 3251 #endif 3309 3252 if ( r_dcache_tlb_ins.read() ) r_icache_tlb_miss_req = false; 3310 3253 r_dcache_fsm = DCACHE_IDLE; … … 3493 3436 case DCACHE_XTN_DC_INVAL_GO: // In this state, we invalidate the cache line & cleanup 3494 3437 // Blocked if previous cleanup not completed 3495 3438 // Test if itlb or dtlb inval is required 3496 3439 { 3497 3440 if ( not r_dcache_cleanup_req.read() ) 3498 3441 { 3499 3442 paddr_t nline; 3500 size_t way = r_dcache_xtn_way.read(); 3501 size_t set = r_dcache_xtn_set.read(); 3502 bool inval_tlb = false; 3443 size_t way = r_dcache_xtn_way.read(); 3444 size_t set = r_dcache_xtn_set.read(); 3445 bool inval_itlb = false; 3446 bool inval_dtlb = false; 3503 3447 3504 3448 r_icache.inval( way, … … 3511 3455 3512 3456 // possible itlb & dtlb invalidate requests 3513 r_dcache_tlb_inval_line = nline; 3514 3515 if ( (r_mmu_mode.read() & DATA_TLB_MASK) and 3516 r_dcache_in_dtlb[way*m_dcache_sets+set] ) 3517 { 3518 r_dcache_dtlb_inval_req = true; 3457 3458 if ( (r_mmu_mode.read() & DATA_TLB_MASK) and r_dcache_in_dtlb[way*m_dcache_sets+set] ) 3459 { 3519 3460 r_dcache_in_dtlb[way*m_dcache_sets+set] = false; 3520 inval_tlb = true; 3521 } 3522 if ( (r_mmu_mode.read() & INS_TLB_MASK) and 3523 r_dcache_in_itlb[m_dcache_sets*way+set] ) 3461 inval_dtlb = true; 3462 } 3463 if ( (r_mmu_mode.read() & INS_TLB_MASK) and r_dcache_in_itlb[m_dcache_sets*way+set] ) 3524 3464 { 3525 r_dcache_itlb_inval_req = true;3526 3465 r_dcache_in_itlb[way*m_dcache_sets+set] = false; 3527 inval_ tlb = true;3466 inval_itlb = true; 3528 3467 } 3529 3468 3530 3469 // no valid response until itlb & dtlb invalidated 3531 if (inval_tlb ) 3532 { 3533 r_dcache_fsm = DCACHE_XTN_DC_INVAL_WAIT; 3470 if ( inval_itlb or inval_dtlb ) 3471 { 3472 r_dcache_itlb_inval_req = inval_itlb; 3473 r_dcache_dtlb_inval_req = inval_dtlb; 3474 r_dcache_tlb_inval_line = nline; 3475 r_dcache_tlb_inval_count = 0; 3476 r_dcache_fsm_save = DCACHE_XTN_DC_INVAL_END; 3477 r_dcache_fsm = DCACHE_INVAL_TLB_SCAN; 3534 3478 } 3535 3479 else … … 3542 3486 } 3543 3487 ////////////////////////////// 3544 case DCACHE_XTN_DC_INVAL_WAIT: // waiting completion of itlb and dtlb invalidate 3545 { 3546 if ( not (r_dcache_itlb_inval_req.read() or r_dcache_dtlb_inval_req.read()) ) 3547 { 3548 r_dcache_fsm = DCACHE_IDLE; 3549 drsp.valid = true; 3550 } 3488 case DCACHE_XTN_DC_INVAL_END: // waiting completion of itlb and dtlb invalidate 3489 { 3490 r_dcache_fsm = DCACHE_IDLE; 3491 drsp.valid = true; 3551 3492 break; 3552 3493 } … … 3836 3777 //////////////////////////// 3837 3778 case DCACHE_WRITE_TLB_DIRTY: // set PTE dirty bit in dtlb 3779 // and get PTE in dcache 3838 3780 { 3839 3781 // set dirty bit in dtlb … … 3842 3784 3843 3785 // get PTE in dcache 3844 uint32_t pte _flags= 0;3786 uint32_t pte = 0; 3845 3787 size_t way; 3846 3788 size_t set; 3847 3789 size_t word; 3848 3790 bool hit = r_dcache.read( r_dcache_p2_pte_paddr.read(), 3849 &pte _flags,3791 &pte, 3850 3792 &way, 3851 3793 &set, … … 3859 3801 if ( m_debug_dcache_fsm ) 3860 3802 { 3861 std::cout << " <PROC.DCACHE_WRITE_TLB_DIRTY> Set PTE dirty bit in dtlb:" 3862 << " paddr = " << r_dcache_p2_pte_paddr.read() 3803 std::cout << " <PROC.DCACHE_WRITE_TLB_DIRTY> Set dirty bit in dtlb:" << std::dec 3863 3804 << " / tlb_way = " << r_dcache_p2_tlb_way.read() 3864 3805 << " / tlb_set = " << r_dcache_p2_tlb_set.read() << std::endl; 3806 r_dtlb.print(); 3807 std::cout << " Get PTE in dcache:" << std::hex 3808 << " paddr = " << r_dcache_p2_pte_paddr.read() 3809 << " / PTE = " << pte << std::dec 3810 << " / dcache_way = " << way 3811 << " / dcache_set = " << set << std::endl; 3865 3812 } 3866 3813 #endif … … 3870 3817 r_dcache_p2_pte_set = set; // register pte set in dcache; 3871 3818 r_dcache_p2_pte_word = word; // register pte word in dcache; 3872 r_dcache_p2_pte _flags = pte_flags;// register pte value3819 r_dcache_p2_pte = pte; // register pte value 3873 3820 r_dcache_fsm = DCACHE_WRITE_CACHE_DIRTY; 3874 3821 break; … … 3882 3829 r_dcache_p2_pte_set.read(), 3883 3830 r_dcache_p2_pte_word.read(), 3884 r_dcache_p2_pte _flags.read() | PTE_D_MASK,3831 r_dcache_p2_pte.read() | PTE_D_MASK, 3885 3832 0xF ); 3886 3833 … … 3892 3839 if ( m_debug_dcache_fsm ) 3893 3840 { 3894 std::cout << " <PROC.DCACHE_WRITE_CACHE_DIRTY> Set PTE dirty bit in dcache :"3841 std::cout << " <PROC.DCACHE_WRITE_CACHE_DIRTY> Set PTE dirty bit in dcache" 3895 3842 << " / way = " << r_dcache_p2_pte_way.read() 3896 3843 << " / set = " << r_dcache_p2_pte_set.read() 3897 3844 << " / word = " << r_dcache_p2_pte_word.read() << std::endl; 3845 std::cout << " Request SC transaction" 3846 << " / address = " << "bloup" 3847 << " / old = " << r_dcache_p2_pte.read() 3848 << " / new = " << (r_dcache_p2_pte.read() | PTE_D_MASK) << std::endl; 3898 3849 } 3899 3850 #endif 3900 3851 // request sc transaction to CMD_FSM 3901 3852 r_dcache_vci_sc_req = true; 3902 r_dcache_vci_sc_old = r_dcache_p2_pte _flags.read();3903 r_dcache_vci_sc_new = r_dcache_p2_pte _flags.read() | PTE_D_MASK;3853 r_dcache_vci_sc_old = r_dcache_p2_pte.read(); 3854 r_dcache_vci_sc_new = r_dcache_p2_pte.read() | PTE_D_MASK; 3904 3855 r_dcache_fsm = DCACHE_WRITE_SC_WAIT; 3905 3856 break; … … 4065 4016 { 4066 4017 paddr_t nline; 4067 size_t way = r_dcache_cc_way.read(); 4068 size_t set = r_dcache_cc_set.read(); 4069 bool inval_tlb = false; 4018 size_t way = r_dcache_cc_way.read(); 4019 size_t set = r_dcache_cc_set.read(); 4020 bool inval_itlb = false; 4021 bool inval_dtlb = false; 4070 4022 4071 4023 r_dcache.inval( way, … … 4074 4026 4075 4027 // possible itlb & dtlb invalidate requests 4076 r_dcache_tlb_inval_line = nline; 4077 4078 if ( (r_mmu_mode.read() & DATA_TLB_MASK) and 4079 r_dcache_in_dtlb[way*m_dcache_sets+set] ) 4080 { 4081 r_dcache_dtlb_inval_req = true; 4028 4029 if ( (r_mmu_mode.read() & DATA_TLB_MASK) and r_dcache_in_dtlb[way*m_dcache_sets+set] ) 4030 { 4031 r_dtlb.reset_bypass(nline); 4082 4032 r_dcache_in_dtlb[way*m_dcache_sets+set] = false; 4083 inval_tlb = true; 4084 } 4085 if ( (r_mmu_mode.read() & INS_TLB_MASK) and 4086 r_dcache_in_itlb[m_dcache_sets*way+set] ) 4033 inval_dtlb = true; 4034 } 4035 if ( (r_mmu_mode.read() & INS_TLB_MASK) and r_dcache_in_itlb[m_dcache_sets*way+set] ) 4087 4036 { 4088 r_ dcache_itlb_inval_req = true;4037 r_itlb.reset_bypass(nline); 4089 4038 r_dcache_in_itlb[way*m_dcache_sets+set] = false; 4090 inval_tlb = true; 4091 } 4092 4093 // no valid response until itlb & dtlb invalidated 4094 if (inval_tlb ) 4095 { 4096 r_dcache_fsm = DCACHE_CC_WAIT; 4039 inval_itlb = true; 4040 } 4041 4042 if ( inval_itlb or inval_dtlb ) // no valid response until itlb / dtlb invalidated 4043 { 4044 r_dcache_itlb_inval_req = inval_itlb; 4045 r_dcache_dtlb_inval_req = inval_dtlb; 4046 r_dcache_tlb_inval_line = nline; 4047 r_dcache_tlb_inval_count = 0; 4048 r_dcache_fsm = DCACHE_INVAL_TLB_SCAN; 4097 4049 } 4098 4050 else … … 4108 4060 std::cout << " <PROC.DCACHE_CC_INVAL> Invalidate cache line :" << std::dec 4109 4061 << " way = " << way 4110 << " / set = " << set << std::endl; 4062 << " / set = " << set; 4063 if ( inval_itlb ) std::cout << " / itlb inval required"; 4064 if ( inval_dtlb ) std::cout << " / dtlb inval required"; 4065 std::cout << std::endl; 4111 4066 } 4112 4067 #endif … … 4118 4073 // and test possible copies in TLBs 4119 4074 { 4120 size_t word = r_dcache_cc_word.read(); 4121 size_t way = r_dcache_cc_way.read(); 4122 size_t set = r_dcache_cc_set.read(); 4075 size_t word = r_dcache_cc_word.read(); 4076 size_t way = r_dcache_cc_way.read(); 4077 size_t set = r_dcache_cc_set.read(); 4078 bool inval_itlb = false; 4079 bool inval_dtlb = false; 4080 paddr_t nline = r_tgt_paddr.read() >> (uint32_log2(m_dcache_words)+2); 4123 4081 4124 4082 r_dcache.write( way, … … 4134 4092 if ( word == r_tgt_word_max.read() ) // last word 4135 4093 { 4136 // invalidate copies in TLBs 4137 if ( (r_mmu_mode.read() & DATA_TLB_MASK) and 4138 ( r_dcache_in_itlb[way*m_dcache_sets+set] or 4139 r_dcache_in_dtlb[m_dcache_sets*way+set] ) ) 4140 { 4141 r_dcache_tlb_inval_line = r_tgt_paddr.read() >> (uint32_log2(m_dcache_words)+2); 4142 r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set]; 4094 // possible itlb & dtlb invalidate requests 4095 4096 if ( (r_mmu_mode.read() & DATA_TLB_MASK) and r_dcache_in_dtlb[way*m_dcache_sets+set] ) 4097 { 4098 r_dtlb.reset_bypass(nline); 4099 r_dcache_in_dtlb[way*m_dcache_sets+set] = false; 4100 inval_dtlb = true; 4101 } 4102 if ( (r_mmu_mode.read() & INS_TLB_MASK) and r_dcache_in_itlb[way*m_dcache_sets+set] ) 4103 { 4104 r_itlb.reset_bypass(nline); 4143 4105 r_dcache_in_itlb[way*m_dcache_sets+set] = false; 4144 r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set]; 4145 r_dcache_in_dtlb[way*m_dcache_sets+set] = false; 4146 r_dcache_fsm = DCACHE_CC_WAIT; 4106 inval_itlb = true; 4107 } 4108 4109 if ( inval_itlb or inval_dtlb ) // no valid response until itlb / dtlb invalidated 4110 { 4111 r_dcache_itlb_inval_req = inval_itlb; 4112 r_dcache_dtlb_inval_req = inval_dtlb; 4113 r_dcache_tlb_inval_line = nline; 4114 r_dcache_tlb_inval_count = 0; 4115 r_dcache_fsm = DCACHE_INVAL_TLB_SCAN; 4147 4116 } 4148 4117 else … … 4161 4130 << " / set = " << set 4162 4131 << " / word = " << word 4163 << " / value = " << std::hex << r_tgt_buf[word] << std::endl; 4132 << " / value = " << std::hex << r_tgt_buf[word]; 4133 if ( inval_itlb ) std::cout << " / itlb inval required"; 4134 if ( inval_dtlb ) std::cout << " / dtlb inval required"; 4135 std::cout << std::endl; 4164 4136 } 4165 4137 #endif … … 4167 4139 break; 4168 4140 } 4169 //////////////////// 4170 case DCACHE_CC_WAIT: // wait completion of TLB invalidate 4171 { 4172 if ( not r_dcache_itlb_inval_req.read() and not r_dcache_dtlb_inval_req.read() ) 4173 { 4174 r_tgt_dcache_rsp = true; 4175 r_tgt_dcache_req = false; 4176 r_dcache_fsm = r_dcache_fsm_save.read(); 4177 } 4141 /////////////////////////// 4142 case DCACHE_INVAL_TLB_SCAN: // scan sequencially all TLB entries for both ITLB & DTLB 4143 // It makes the assumption that (m_itlb_sets == m_dtlb_sets) 4144 // and (m_itlb_ways == m_dtlb_ways) 4145 // Caution : we enter this state when a DCACHE line is modified, 4146 // and there is a copy in itlb or dtlb. 4147 // It can be caused by a coherence transaction, a XTN inval 4148 // or a WRITE hit. Input arguments are: 4149 // - r_dcache_tlb_inval_line 4150 // - r_dcache_tlb_inval_count 4151 // - r_dcache_itlb_inval_req 4152 // - r_dcache_dtlb_inval_req 4153 // - r_dcache_fsm_save 4154 { 4155 paddr_t line = r_dcache_tlb_inval_line.read(); // nline 4156 size_t way = r_dcache_tlb_inval_count.read()/m_itlb_sets; // way 4157 size_t set = r_dcache_tlb_inval_count.read()%m_itlb_sets; // set 4158 4159 if ( r_dcache_itlb_inval_req.read() ) 4160 { 4161 bool ok = r_itlb.inval( line, 4162 way, 4163 set ); 4164 #if DEBUG_DCACHE 4165 if ( m_debug_dcache_fsm and ok ) 4166 { 4167 std::cout << " <PROC.DCACHE_INVAL_TLB_SCAN> Invalidate ITLB entry:" << std::hex 4168 << " line = " << line << std::dec 4169 << " / set = " << set 4170 << " / way = " << way << std::endl; 4171 r_itlb.print(); 4172 } 4173 #endif 4174 } 4175 4176 if ( r_dcache_dtlb_inval_req.read() ) 4177 { 4178 bool ok = r_dtlb.inval( line, 4179 way, 4180 set ); 4181 #if DEBUG_DCACHE 4182 if ( m_debug_dcache_fsm and ok ) 4183 { 4184 std::cout << " <PROC.DCACHE_INVAL_TLB_SCAN> Invalidate DTLB entry:" << std::hex 4185 << " line = " << line << std::dec 4186 << " / set = " << set 4187 << " / way = " << way << std::endl; 4188 r_dtlb.print(); 4189 } 4190 #endif 4191 } 4192 4193 // return to the calling state when TLB inval completed 4194 if ( r_dcache_tlb_inval_count.read() == (m_dtlb_sets*m_dtlb_ways-1) ) 4195 { 4196 if ( r_dcache_fsm_save.read() != DCACHE_XTN_DC_INVAL_END ) // not an XTN inval 4197 { 4198 r_tgt_dcache_rsp = true; 4199 r_tgt_dcache_req = false; 4200 } 4201 r_dcache_dtlb_inval_req = false; 4202 r_dcache_itlb_inval_req = false; 4203 r_dcache_fsm = r_dcache_fsm_save.read(); 4204 } 4205 r_dcache_tlb_inval_count = r_dcache_tlb_inval_count.read() + 1; 4178 4206 } 4179 4207 } // end switch r_dcache_fsm … … 4194 4222 ///////////////// wbuf update ////////////////////////////////////////////////////// 4195 4223 r_wbuf.update(); 4196 4197 ////////////////////////////////////////////////////////////////////////////////////4198 // INVAL DTLB FSM4199 // This FSM works in parallel with the DCACHE FSM.4200 // When the r_dcache_dtlb_inval_req flip-flop is activated by the DCACHE FSM4201 // it scans sequencially all entries in the DTLB, and invalidates the4202 // entries matching the evicted line.4203 // It signals the completion of invalidation by reseting r_dcache_itlb_inval_req.4204 ////////////////////////////////////////////////////////////////////////////////////4205 4206 switch(r_inval_dtlb_fsm)4207 {4208 /////////////////////4209 case INVAL_DTLB_IDLE:4210 {4211 if ( r_dcache_dtlb_inval_req.read() )4212 {4213 r_dtlb.reset_bypass(r_dcache_tlb_inval_line.read());4214 r_inval_dtlb_count = 0;4215 r_inval_dtlb_fsm = INVAL_DTLB_SCAN;4216 4217 #if DEBUG_INVAL_DTLB4218 if ( m_debug_inval_dtlb_fsm )4219 {4220 std::cout << " <PROC.INVAL_DTLB_IDLE> Invalidate request for line "4221 << std::hex << r_dcache_tlb_inval_line.read() << std::endl;4222 r_dtlb.print();4223 }4224 #endif4225 }4226 break;4227 }4228 /////////////////////4229 case INVAL_DTLB_SCAN:4230 {4231 paddr_t line = r_dcache_tlb_inval_line.read(); // nline4232 size_t way = r_inval_dtlb_count.read()/m_itlb_sets; // way4233 size_t set = r_inval_dtlb_count.read()%m_itlb_sets; // set4234 4235 bool ok = r_dtlb.inval( line,4236 way,4237 set );4238 4239 #if DEBUG_INVAL_DTLB4240 if ( m_debug_inval_dtlb_fsm )4241 {4242 std::cout << " <PROC.INVAL_DTLB_SCAN>" << std::hex4243 << " line = " << line << std::dec4244 << " / set = " << set4245 << " / way = " << way;4246 if ( ok ) std::cout << " / HIT" << std::endl;4247 else std::cout << " / MISS" << std::endl;4248 }4249 #endif4250 4251 r_inval_dtlb_count = r_inval_dtlb_count.read() + 1;4252 if ( r_inval_dtlb_count.read() == (m_dtlb_sets*m_dtlb_ways - 1) )4253 {4254 r_inval_dtlb_fsm = INVAL_DTLB_IDLE;4255 r_dcache_dtlb_inval_req = false;4256 }4257 break;4258 }4259 } // end switch r_inval_dtlb_fsm4260 4224 4261 4225 /////////// test processor frozen ///////////////////////////////////////////// … … 4385 4349 { 4386 4350 r_vci_cmd_fsm = CMD_DATA_SC; 4387 r_dcache_vci_sc_req 4351 r_dcache_vci_sc_req = false; 4388 4352 r_vci_cmd_cpt = 0; 4389 4353 // m_cpt_sc_transaction++;
Note: See TracChangeset
for help on using the changeset viewer.