- Timestamp:
- Sep 30, 2014, 4:53:01 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/RWT/modules/vci_cc_vcache_wrapper/caba/source/src/vci_cc_vcache_wrapper.cpp
r805 r824 34 34 #include "../include/vci_cc_vcache_wrapper.h" 35 35 36 #define DEBUG_DCACHE 37 #define DEBUG_ICACHE 38 #define DEBUG_CMD 36 #define DEBUG_DCACHE 1 37 #define DEBUG_ICACHE 1 38 #define DEBUG_CMD 0 39 39 #define INSTRUMENTATION 1 40 40 … … 137 137 const char *vci_pktid_type_str[] = { 138 138 "TYPE_DATA_UNC", 139 "TYPE_READ_DATA_MISS", 140 "TYPE_READ_INS_UNC", 139 "TYPE_READ_DATA_MISS", 140 "TYPE_READ_INS_UNC", 141 141 "TYPE_READ_INS_MISS", 142 142 "TYPE_WRITE", … … 199 199 ///////////////////////////////// 200 200 tmpl(/**/)::VciCcVCacheWrapper( 201 sc_module_name 202 const int 203 const MappingTable 204 const IntTab 205 const size_t 206 const size_t 207 const size_t 208 const size_t 209 const size_t 210 const size_t 211 const size_t 212 const size_t 213 const size_t 214 const size_t 215 const size_t 216 const size_t 217 const size_t 218 const size_t 219 const size_t 220 const uint32_t 221 const uint32_t 222 const bool 201 sc_module_name name, 202 const int proc_id, 203 const MappingTable &mtd, 204 const IntTab &srcid, 205 const size_t cc_global_id, 206 const size_t itlb_ways, 207 const size_t itlb_sets, 208 const size_t dtlb_ways, 209 const size_t dtlb_sets, 210 const size_t icache_ways, 211 const size_t icache_sets, 212 const size_t icache_words, 213 const size_t dcache_ways, 214 const size_t dcache_sets, 215 const size_t dcache_words, 216 const size_t wbuf_nlines, 217 const size_t wbuf_nwords, 218 const size_t x_width, 219 const size_t y_width, 220 const uint32_t max_frozen_cycles, 221 const uint32_t debug_start_cycle, 222 const bool debug_ok ) 223 223 : soclib::caba::BaseModule(name), 224 224 … … 379 379 r_vci_rsp_ins_error("r_vci_rsp_ins_error"), 380 380 r_vci_rsp_data_error("r_vci_rsp_data_error"), 381 r_vci_rsp_fifo_icache("r_vci_rsp_fifo_icache", 2), 382 r_vci_rsp_fifo_dcache("r_vci_rsp_fifo_dcache", 2), 381 r_vci_rsp_fifo_icache("r_vci_rsp_fifo_icache", 2), // 2 words depth 382 r_vci_rsp_fifo_dcache("r_vci_rsp_fifo_dcache", 2), // 2 words depth 383 383 r_vci_rsp_fifo_rpktid("r_vci_rsp_fifo_rpktid", 2), // 2 words depth 384 384 r_cc_send_data_fifo("r_cc_send_data_fifo", 16), … … 390 390 r_cc_receive_data_ins("r_cc_receive_data_ins"), 391 391 r_cc_receive_word_idx("r_cc_receive_word_idx"), 392 r_cc_receive_updt_fifo_be("r_cc_receive_updt_fifo_be", 2), 393 r_cc_receive_updt_fifo_data("r_cc_receive_updt_fifo_data", 2), 394 r_cc_receive_updt_fifo_eop("r_cc_receive_updt_fifo_eop", 2), 392 r_cc_receive_updt_fifo_be("r_cc_receive_updt_fifo_be", 2), // 2 words depth 393 r_cc_receive_updt_fifo_data("r_cc_receive_updt_fifo_data", 2), // 2 words depth 394 r_cc_receive_updt_fifo_eop("r_cc_receive_updt_fifo_eop", 2), // 2 words depth 395 395 396 396 r_cc_receive_icache_req("r_cc_receive_icache_req"), … … 559 559 { 560 560 bool cache_hit; 561 size_t 562 size_t 563 size_t 564 uint32_t 561 size_t cache_way = 0; 562 size_t cache_set = 0; 563 size_t cache_word = 0; 564 uint32_t cache_rdata = 0; 565 565 566 566 cache_hit = r_dcache.read_neutral( addr, … … 574 574 std::cout << "Monitor PROC " << name() 575 575 << " DCACHE at cycle " << std::dec << m_cpt_total_cycles 576 << " / HIT = " << cache_hit 576 << " / HIT = " << cache_hit 577 577 << " / PADDR = " << std::hex << addr 578 << " / DATA = " << cache_rdata 578 << " / DATA = " << cache_rdata 579 579 << " / WAY = " << cache_way << std::endl; 580 580 m_debug_previous_d_hit = cache_hit; 581 581 } 582 582 … … 591 591 std::cout << "Monitor PROC " << name() 592 592 << " ICACHE at cycle " << std::dec << m_cpt_total_cycles 593 << " / HIT = " << cache_hit 593 << " / HIT = " << cache_hit 594 594 << " / PADDR = " << std::hex << addr 595 << " / DATA = " << cache_rdata 595 << " / DATA = " << cache_rdata 596 596 << " / WAY = " << cache_way << std::endl; 597 597 m_debug_previous_i_hit = cache_hit; 598 598 } 599 599 } … … 810 810 r_mmu_mode = 0x3; 811 811 812 812 // No request from ICACHE FSM to CMD FSM 813 813 r_icache_miss_req = false; 814 814 r_icache_unc_req = false; … … 865 865 m_debug_previous_i_hit = false; 866 866 m_debug_previous_d_hit = false; 867 m_debug_activated 867 m_debug_activated = false; 868 868 869 869 // SPECIAL REGISTERS ODCCP … … 944 944 m_cost_data_tlb_occup_cache_frz = 0; 945 945 946 947 948 949 946 m_cpt_ins_tlb_inval = 0; 947 m_cpt_data_tlb_inval = 0; 948 m_cost_ins_tlb_inval_frz = 0; 949 m_cost_data_tlb_inval_frz = 0; 950 950 951 951 m_cpt_cc_broadcast = 0; 952 952 953 954 955 956 957 958 959 953 m_cost_updt_data_frz = 0; 954 m_cost_inval_ins_frz = 0; 955 m_cost_inval_data_frz = 0; 956 m_cost_broadcast_frz = 0; 957 958 m_cpt_cc_cleanup_data = 0; 959 m_cpt_cc_cleanup_ins = 0; 960 960 961 961 m_cpt_cleanup_data_not_dirty = 0; … … 986 986 m_cpt_read = 0; 987 987 m_cpt_write = 0; 988 989 990 988 m_cpt_cc_update_data = 0; 989 m_cpt_cc_inval_ins = 0; 990 m_cpt_cc_inval_data = 0; 991 991 */ 992 992 … … 1106 1106 { 1107 1107 ///////////////// 1108 case ICACHE_IDLE: 1108 case ICACHE_IDLE: // In this state, we handle processor requests, XTN requests, 1109 1109 // and coherence requests with a fixed priority: 1110 1110 // 1/ Coherence requests => ICACHE_CC_CHECK … … 1183 1183 if ( m_ireq.valid ) 1184 1184 { 1185 bool 1186 paddr_t 1185 bool cacheable; 1186 paddr_t paddr; 1187 1187 bool tlb_hit = false; 1188 1188 pte_info_t tlb_flags; … … 1242 1242 // and there is no access rights checking 1243 1243 1244 if ( not (r_mmu_mode.read() & INS_TLB_MASK) ) 1244 if ( not (r_mmu_mode.read() & INS_TLB_MASK) ) // tlb not activated: 1245 1245 { 1246 1246 // cacheability … … 1248 1248 else cacheable = m_cacheability_table[(uint64_t)m_ireq.addr]; 1249 1249 } 1250 else 1251 { 1252 if ( tlb_hit ) 1250 else // itlb activated 1251 { 1252 if ( tlb_hit ) // ITLB hit 1253 1253 { 1254 1254 // cacheability … … 1295 1295 { 1296 1296 1297 if (cache_state == CACHE_SLOT_STATE_EMPTY) 1297 if (cache_state == CACHE_SLOT_STATE_EMPTY) // cache miss 1298 1298 { 1299 1299 … … 1305 1305 #if DEBUG_ICACHE 1306 1306 if ( m_debug_activated ) 1307 std::cout << " <PROC " << name() << " ICACHE_IDLE> READ MISS in icache" 1307 std::cout << " <PROC " << name() << " ICACHE_IDLE> READ MISS in icache" 1308 1308 << " : PADDR = " << std::hex << paddr << std::endl; 1309 1309 #endif 1310 1310 r_icache_miss_req = true; 1311 1311 } 1312 else if (cache_state == CACHE_SLOT_STATE_ZOMBI ) 1312 else if (cache_state == CACHE_SLOT_STATE_ZOMBI ) // pending cleanup 1313 1313 { 1314 1314 // stalled until cleanup is acknowledged 1315 1315 r_icache_fsm = ICACHE_IDLE; 1316 1316 } 1317 else 1317 else // cache hit 1318 1318 { 1319 1319 … … 1327 1327 #if DEBUG_ICACHE 1328 1328 if ( m_debug_activated ) 1329 std::cout << " <PROC " << name() << " ICACHE_IDLE> READ HIT in icache" 1329 std::cout << " <PROC " << name() << " ICACHE_IDLE> READ HIT in icache" 1330 1330 << " : PADDR = " << std::hex << paddr 1331 1331 << " / INST = " << cache_inst << std::dec << std::endl; … … 1333 1333 } 1334 1334 } 1335 else 1335 else // non cacheable read 1336 1336 { 1337 1337 r_icache_unc_req = true; … … 1342 1342 { 1343 1343 std::cout << " <PROC " << name() 1344 << " ICACHE_IDLE> READ UNCACHEABLE in icache" 1344 << " ICACHE_IDLE> READ UNCACHEABLE in icache" 1345 1345 << " : PADDR = " << std::hex << paddr << std::endl; 1346 1346 } … … 1351 1351 } 1352 1352 ///////////////////// 1353 case ICACHE_TLB_WAIT: 1353 case ICACHE_TLB_WAIT: // Waiting the itlb update by the DCACHE FSM after a tlb miss 1354 1354 // the itlb is udated by the DCACHE FSM, as well as the 1355 1355 // r_mmu_ietr and r_mmu_ibvar registers in case of error. … … 1386 1386 r_icache_fsm = ICACHE_IDLE; 1387 1387 } 1388 else 1388 else // tlb updated : return to IDLE state 1389 1389 { 1390 1390 r_icache_fsm = ICACHE_IDLE; … … 1394 1394 } 1395 1395 ////////////////////////// 1396 case ICACHE_XTN_TLB_FLUSH: 1396 case ICACHE_XTN_TLB_FLUSH: // invalidate in one cycle all non global TLB entries 1397 1397 { 1398 1398 r_itlb.flush(); … … 1402 1402 } 1403 1403 //////////////////////////// 1404 case ICACHE_XTN_CACHE_FLUSH: 1404 case ICACHE_XTN_CACHE_FLUSH: // Invalidate sequencially all cache lines, using 1405 1405 // r_icache_flush_count as a slot counter, 1406 1406 // looping in this state until all slots are visited. 1407 1407 // It can require two cycles per slot: 1408 1408 // We test here the slot state, and make the actual inval 1409 1409 // (if line is valid) in ICACHE_XTN_CACHE_FLUSH_GO state. 1410 1410 // A cleanup request is generated for each valid line 1411 1411 { 1412 1412 // coherence clack interrupt … … 1430 1430 int state; 1431 1431 paddr_t tag; 1432 size_t 1433 size_t 1432 size_t way = r_icache_flush_count.read()/m_icache_sets; 1433 size_t set = r_icache_flush_count.read()%m_icache_sets; 1434 1434 1435 1435 #ifdef INSTRUMENTATION … … 1457 1457 (m_icache_sets*m_icache_ways - 1) ) // last slot 1458 1458 { 1459 1459 r_dcache_xtn_req = false; 1460 1460 m_drsp.valid = true; 1461 r_icache_fsm= ICACHE_IDLE;1461 r_icache_fsm = ICACHE_IDLE; 1462 1462 } 1463 1463 … … 1472 1472 } 1473 1473 /////////////////////////////// 1474 case ICACHE_XTN_CACHE_FLUSH_GO: 1475 { 1476 size_t 1477 size_t 1474 case ICACHE_XTN_CACHE_FLUSH_GO: // Switch slot state to ZOMBI for an XTN flush 1475 { 1476 size_t way = r_icache_miss_way.read(); 1477 size_t set = r_icache_miss_set.read(); 1478 1478 1479 1479 #ifdef INSTRUMENTATION … … 1488 1488 (m_icache_sets*m_icache_ways - 1) ) // last slot 1489 1489 { 1490 1490 r_dcache_xtn_req = false; 1491 1491 m_drsp.valid = true; 1492 r_icache_fsm= ICACHE_IDLE;1492 r_icache_fsm = ICACHE_IDLE; 1493 1493 } 1494 1494 else … … 1500 1500 1501 1501 ////////////////////////// 1502 case ICACHE_XTN_TLB_INVAL: 1503 1502 case ICACHE_XTN_TLB_INVAL: // invalidate one TLB entry selected by the virtual address 1503 // stored in the r_dcache_save_wdata register 1504 1504 { 1505 1505 r_itlb.inval(r_dcache_save_wdata.read()); … … 1509 1509 } 1510 1510 /////////////////////////////// 1511 case ICACHE_XTN_CACHE_INVAL_VA: 1511 case ICACHE_XTN_CACHE_INVAL_VA: // Selective cache line invalidate with virtual address 1512 1512 // requires 3 cycles (in case of hit on itlb and icache). 1513 1514 1515 { 1516 paddr_t 1517 bool 1513 // In this state, access TLB to translate virtual address 1514 // stored in the r_dcache_save_wdata register. 1515 { 1516 paddr_t paddr; 1517 bool hit; 1518 1518 1519 1519 // read physical address in TLB when MMU activated 1520 if ( r_mmu_mode.read() & INS_TLB_MASK ) 1520 if ( r_mmu_mode.read() & INS_TLB_MASK ) // itlb activated 1521 1521 { 1522 1522 … … 1527 1527 &paddr); 1528 1528 } 1529 else 1530 { 1531 paddr 1532 hit 1533 } 1534 1535 if ( hit ) 1529 else // itlb not activated 1530 { 1531 paddr = (paddr_t)r_dcache_save_wdata.read(); 1532 hit = true; 1533 } 1534 1535 if ( hit ) // continue the selective inval process 1536 1536 { 1537 1537 r_icache_vci_paddr = paddr; 1538 1538 r_icache_fsm = ICACHE_XTN_CACHE_INVAL_PA; 1539 1539 } 1540 else 1540 else // miss : send a request to DCACHE FSM 1541 1541 { 1542 1542 … … 1545 1545 #endif 1546 1546 r_icache_tlb_miss_req = true; 1547 1547 r_icache_vaddr_save = r_dcache_save_wdata.read(); 1548 1548 r_icache_fsm = ICACHE_TLB_WAIT; 1549 1549 } … … 1551 1551 } 1552 1552 /////////////////////////////// 1553 case ICACHE_XTN_CACHE_INVAL_PA: 1553 case ICACHE_XTN_CACHE_INVAL_PA: // selective invalidate cache line with physical address 1554 1554 // require 2 cycles. In this state, we read directory 1555 1555 // with address stored in r_icache_vci_paddr register. 1556 1556 { 1557 1557 int state; 1558 size_t 1559 size_t 1560 size_t 1558 size_t way; 1559 size_t set; 1560 size_t word; 1561 1561 1562 1562 #ifdef INSTRUMENTATION … … 1569 1569 &word); 1570 1570 1571 if ( state == CACHE_SLOT_STATE_VALID_CC ) 1571 if ( state == CACHE_SLOT_STATE_VALID_CC ) // inval to be done 1572 1572 { 1573 1573 r_icache_miss_way = way; … … 1575 1575 r_icache_fsm = ICACHE_XTN_CACHE_INVAL_GO; 1576 1576 } 1577 else 1577 else // miss : acknowlege the XTN request and return 1578 1578 { 1579 1579 r_dcache_xtn_req = false; … … 1636 1636 bool found; 1637 1637 bool cleanup; 1638 size_t 1639 size_t 1640 paddr_t 1638 size_t way; 1639 size_t set; 1640 paddr_t victim; 1641 1641 1642 1642 #ifdef INSTRUMENTATION … … 1661 1661 r_icache_cc_send_nline = victim; 1662 1662 r_icache_cc_send_way = way; 1663 r_icache_cc_send_type = CC_TYPE_CLEANUP; 1663 r_icache_cc_send_type = CC_TYPE_CLEANUP; 1664 1664 } 1665 1665 else … … 1692 1692 } 1693 1693 /////////////////////// 1694 case ICACHE_MISS_CLEAN: 1694 case ICACHE_MISS_CLEAN: // switch the slot to zombi state 1695 1695 { 1696 1696 if (m_ireq.valid) m_cost_ins_miss_frz++; … … 1716 1716 } 1717 1717 ////////////////////// 1718 case ICACHE_MISS_WAIT: 1718 case ICACHE_MISS_WAIT: // waiting response from VCI_RSP FSM 1719 1719 { 1720 1720 if (m_ireq.valid) m_cost_ins_miss_frz++; … … 1725 1725 r_icache_cc_send_nline = r_icache_cleanup_victim_nline; 1726 1726 r_icache_cc_send_way = r_icache_miss_way; 1727 r_icache_cc_send_type = CC_TYPE_CLEANUP; 1727 r_icache_cc_send_type = CC_TYPE_CLEANUP; 1728 1728 r_icache_cleanup_victim_req = false; 1729 } 1729 } 1730 1730 1731 1731 // coherence clack interrupt … … 1736 1736 break; 1737 1737 } 1738 1738 1739 1739 // coherence interrupt 1740 1740 if ( r_cc_receive_icache_req.read() and not r_icache_cc_send_req.read() and not r_icache_cleanup_victim_req.read() ) … … 1762 1762 } 1763 1763 /////////////////////////// 1764 case ICACHE_MISS_DATA_UPDT: 1764 case ICACHE_MISS_DATA_UPDT: // update the cache (one word per cycle) 1765 1765 { 1766 1766 if ( m_ireq.valid ) m_cost_ins_miss_frz++; 1767 1767 1768 if ( r_vci_rsp_fifo_icache.rok() ) 1768 if ( r_vci_rsp_fifo_icache.rok() ) // response available 1769 1769 { 1770 1770 … … 1790 1790 r_icache_miss_word = r_icache_miss_word.read() + 1; 1791 1791 1792 if ( r_icache_miss_word.read() == m_icache_words-1 ) 1792 if ( r_icache_miss_word.read() == m_icache_words-1 ) // last word 1793 1793 { 1794 1794 r_icache_fsm = ICACHE_MISS_DIR_UPDT; … … 1798 1798 } 1799 1799 ////////////////////////// 1800 case ICACHE_MISS_DIR_UPDT: 1800 case ICACHE_MISS_DIR_UPDT: // Stalled if a victim line has been evicted, 1801 1801 // and the cleanup ack has not been received, 1802 1802 // as indicated by r_icache_miss_clack. … … 1814 1814 r_icache_cc_send_nline = r_icache_cleanup_victim_nline; 1815 1815 r_icache_cc_send_way = r_icache_miss_way; 1816 r_icache_cc_send_type = CC_TYPE_CLEANUP; 1816 r_icache_cc_send_type = CC_TYPE_CLEANUP; 1817 1817 r_icache_cleanup_victim_req = false; 1818 } 1818 } 1819 1819 1820 1820 // coherence clack interrupt … … 1895 1895 } 1896 1896 //////////////////// 1897 case ICACHE_UNC_WAIT: 1897 case ICACHE_UNC_WAIT: // waiting a response to an uncacheable read from VCI_RSP FSM 1898 1898 { 1899 1899 // coherence clack interrupt … … 1936 1936 } 1937 1937 ///////////////////// 1938 case ICACHE_CC_CHECK: 1938 case ICACHE_CC_CHECK: // This state is the entry point of a sub-fsm 1939 1939 // handling coherence requests. 1940 1940 // if there is a matching pending miss, it is … … 2028 2028 // CC request handler 2029 2029 2030 int 2031 size_t 2032 size_t 2033 size_t 2030 int state = 0; 2031 size_t way = 0; 2032 size_t set = 0; 2033 size_t word = 0; 2034 2034 2035 2035 #ifdef INSTRUMENTATION … … 2090 2090 } 2091 2091 ///////////////////// 2092 case ICACHE_CC_INVAL: 2092 case ICACHE_CC_INVAL: // hit inval : switch slot to ZOMBI state 2093 2093 { 2094 2094 assert (not r_icache_cc_send_req.read() && … … 2100 2100 #endif 2101 2101 2102 // Switch slot state to ZOMBI and send CLEANUP command 2102 // Switch slot state to ZOMBI and send CLEANUP command 2103 2103 r_icache.write_dir( r_icache_cc_way.read(), 2104 2104 r_icache_cc_set.read(), … … 2126 2126 } 2127 2127 //////////////////// 2128 case ICACHE_CC_UPDT: 2128 case ICACHE_CC_UPDT: // hit update : write one word per cycle 2129 2129 { 2130 2130 assert (not r_icache_cc_send_req.read() && … … 2165 2165 } 2166 2166 2167 if ( r_cc_receive_updt_fifo_eop.read() ) 2167 if ( r_cc_receive_updt_fifo_eop.read() ) // last word 2168 2168 { 2169 2169 // no need to write in the cache anymore … … 2306 2306 { 2307 2307 paddr_t paddr; // physical address 2308 pte_info_t 2309 size_t 2310 size_t 2311 paddr_t 2312 size_t 2313 size_t 2314 size_t 2315 uint32_t 2316 bool 2317 int 2308 pte_info_t tlb_flags; 2309 size_t tlb_way; 2310 size_t tlb_set; 2311 paddr_t tlb_nline = 0; 2312 size_t cache_way; 2313 size_t cache_set; 2314 size_t cache_word; 2315 uint32_t cache_rdata = 0; 2316 bool tlb_hit = false; 2317 int cache_state = CACHE_SLOT_STATE_EMPTY; 2318 2318 2319 2319 bool tlb_inval_required = false; // request TLB inval after cache update … … 2341 2341 { 2342 2342 // we take into account the paddr extension 2343 if (vci_param::N > 32) 2343 if (vci_param::N > 32) 2344 2344 paddr = paddr | ((paddr_t)(r_dcache_paddr_ext.read()) << 32); 2345 2345 } … … 2404 2404 { 2405 2405 tlb_inval_required = true; 2406 2407 2406 r_dcache_tlb_inval_set = 0; 2407 r_dcache_tlb_inval_line = r_dcache_save_paddr.read()>> 2408 2408 (uint32_log2(m_dcache_words<<2)); 2409 2409 … … 2620 2620 switch( xtn_opcode ) 2621 2621 { 2622 case iss_t::XTN_PTPR: 2622 case iss_t::XTN_PTPR: // itlb & dtlb must be flushed 2623 2623 r_dcache_xtn_req = true; 2624 2624 r_dcache_fsm = DCACHE_XTN_SWITCH; 2625 2625 break; 2626 2626 2627 case iss_t::XTN_TLB_MODE: 2627 case iss_t::XTN_TLB_MODE: // no cache or tlb access 2628 2628 r_mmu_mode = m_dreq.wdata; 2629 2629 m_drsp.valid = true; … … 2631 2631 break; 2632 2632 2633 case iss_t::XTN_DTLB_INVAL: 2633 case iss_t::XTN_DTLB_INVAL: // dtlb access 2634 2634 r_dcache_fsm = DCACHE_XTN_DT_INVAL; 2635 2635 break; 2636 2636 2637 case iss_t::XTN_ITLB_INVAL: 2637 case iss_t::XTN_ITLB_INVAL: // itlb access 2638 2638 r_dcache_xtn_req = true; 2639 2639 r_dcache_fsm = DCACHE_XTN_IT_INVAL; 2640 2640 break; 2641 2641 2642 case iss_t::XTN_DCACHE_INVAL: 2642 case iss_t::XTN_DCACHE_INVAL: // dcache, dtlb & itlb access 2643 2643 r_dcache_fsm = DCACHE_XTN_DC_INVAL_VA; 2644 2644 break; 2645 2645 2646 case iss_t::XTN_MMU_DCACHE_PA_INV: 2646 case iss_t::XTN_MMU_DCACHE_PA_INV: // dcache, dtlb & itlb access 2647 2647 r_dcache_fsm = DCACHE_XTN_DC_INVAL_PA; 2648 2648 if (sizeof(paddr_t) <= 32) … … 2659 2659 break; 2660 2660 2661 case iss_t::XTN_DCACHE_FLUSH: 2661 case iss_t::XTN_DCACHE_FLUSH: // itlb and dtlb must be reset 2662 2662 r_dcache_flush_count = 0; 2663 2663 r_dcache_fsm = DCACHE_XTN_DC_FLUSH; 2664 2664 break; 2665 2665 2666 case iss_t::XTN_ICACHE_INVAL: 2666 case iss_t::XTN_ICACHE_INVAL: // icache and itlb access 2667 2667 r_dcache_xtn_req = true; 2668 2668 r_dcache_fsm = DCACHE_XTN_IC_INVAL_VA; 2669 2669 break; 2670 2670 2671 case iss_t::XTN_MMU_ICACHE_PA_INV: 2671 case iss_t::XTN_MMU_ICACHE_PA_INV: // icache access 2672 2672 r_dcache_xtn_req = true; 2673 2673 r_dcache_fsm = DCACHE_XTN_IC_INVAL_PA; 2674 2674 break; 2675 2675 2676 case iss_t::XTN_ICACHE_FLUSH: 2676 case iss_t::XTN_ICACHE_FLUSH: // icache access 2677 2677 r_dcache_xtn_req = true; 2678 2678 r_dcache_fsm = DCACHE_XTN_IC_FLUSH; 2679 2679 break; 2680 2680 2681 case iss_t::XTN_SYNC: 2681 case iss_t::XTN_SYNC: // wait until write buffer empty 2682 2682 r_dcache_fsm = DCACHE_XTN_SYNC; 2683 2683 break; 2684 2684 2685 case iss_t::XTN_MMU_WORD_LO: 2685 case iss_t::XTN_MMU_WORD_LO: // no cache or tlb access 2686 2686 r_mmu_word_lo = m_dreq.wdata; 2687 2687 m_drsp.valid = true; … … 2689 2689 break; 2690 2690 2691 case iss_t::XTN_MMU_WORD_HI: 2691 case iss_t::XTN_MMU_WORD_HI: // no cache or tlb access 2692 2692 r_mmu_word_hi = m_dreq.wdata; 2693 2693 m_drsp.valid = true; … … 2712 2712 break; 2713 2713 2714 case iss_t::XTN_ICACHE_PREFETCH:// not implemented : no action2715 case iss_t::XTN_DCACHE_PREFETCH:// not implemented : no action2714 case iss_t::XTN_ICACHE_PREFETCH: // not implemented : no action 2715 case iss_t::XTN_DCACHE_PREFETCH: // not implemented : no action 2716 2716 m_drsp.valid = true; 2717 2717 r_dcache_fsm = DCACHE_IDLE; 2718 2718 break; 2719 2719 2720 2720 default: … … 2739 2739 else 2740 2740 { 2741 bool 2742 bool 2743 2744 if ( not (r_mmu_mode.read() & DATA_TLB_MASK) ) 2741 bool valid_req; 2742 bool cacheable; 2743 2744 if ( not (r_mmu_mode.read() & DATA_TLB_MASK) ) // dtlb not activated 2745 2745 { 2746 2746 valid_req = true; … … 2749 2749 else cacheable = m_cacheability_table[(uint64_t)m_dreq.addr]; 2750 2750 } 2751 else 2751 else // dtlb activated 2752 2752 { 2753 if ( tlb_hit ) 2753 if ( tlb_hit ) // tlb hit 2754 2754 { 2755 2755 // cacheability … … 2800 2800 } 2801 2801 } 2802 else 2802 else // tlb miss 2803 2803 { 2804 2804 valid_req = false; … … 2809 2809 } // end DTLB activated 2810 2810 2811 if ( valid_req ) 2811 if ( valid_req ) // processor request is valid (after MMU check) 2812 2812 { 2813 2813 // READ request … … 2818 2818 and not r_dcache_updt_req.read() ) 2819 2819 { 2820 if ( cacheable ) 2820 if ( cacheable ) // cacheable read 2821 2821 { 2822 2822 if ( cache_state == CACHE_SLOT_STATE_EMPTY ) // cache miss … … 2833 2833 if ( m_debug_activated ) 2834 2834 std::cout << " <PROC " << name() << " DCACHE_IDLE>" 2835 << " READ MISS in dcache" 2835 << " READ MISS in dcache" 2836 2836 << " / PADDR = " << std::hex << paddr << std::endl; 2837 2837 #endif … … 2860 2860 if ( m_debug_activated ) 2861 2861 std::cout << " <PROC " << name() << " DCACHE_IDLE>" 2862 << " READ HIT in dcache" 2863 << " : PADDR = " << std::hex << paddr 2862 << " READ HIT in dcache" 2863 << " : PADDR = " << std::hex << paddr 2864 2864 << " / DATA = " << std::hex << cache_rdata << std::dec << std::endl; 2865 2865 #endif 2866 2866 } 2867 2867 } 2868 else 2868 else // uncacheable read 2869 2869 { 2870 2870 r_dcache_vci_paddr = paddr; … … 2876 2876 if ( m_debug_activated ) 2877 2877 std::cout << " <PROC " << name() << " DCACHE_IDLE>" 2878 << " READ UNCACHEABLE in dcache" 2878 << " READ UNCACHEABLE in dcache" 2879 2879 << " / PADDR = " << std::hex << paddr << std::endl; 2880 2880 #endif … … 2911 2911 { 2912 2912 if ( (r_mmu_mode.read() & DATA_TLB_MASK ) 2913 and not tlb_flags.d ) 2913 and not tlb_flags.d ) // Dirty bit must be set 2914 2914 { 2915 2915 // The PTE physical address is obtained from the nline value (dtlb), 2916 2916 // and from the virtual address (word index) 2917 if ( tlb_flags.b ) 2917 if ( tlb_flags.b ) // PTE1 2918 2918 { 2919 2919 r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) | 2920 2920 (paddr_t)((m_dreq.addr>>19) & 0x3c); 2921 2921 } 2922 else 2922 else // PTE2 2923 2923 { 2924 2924 r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) | … … 2927 2927 r_dcache_fsm = DCACHE_DIRTY_GET_PTE; 2928 2928 } 2929 else 2929 else // Write request accepted 2930 2930 { 2931 2931 #ifdef INSTRUMENTATION … … 2936 2936 r_dcache_llsc_valid = false; 2937 2937 2938 if (not cacheable) 2939 { 2938 if (not cacheable) 2939 { 2940 2940 r_dcache_vci_paddr = paddr; 2941 2941 r_dcache_vci_wdata = m_dreq.wdata; … … 2951 2951 updt_request = true; 2952 2952 m_drsp.valid = true; 2953 if ( cache_state == CACHE_SLOT_STATE_VALID_NCC ) 2953 if ( cache_state == CACHE_SLOT_STATE_VALID_NCC ) 2954 2954 { 2955 2955 if ( r_dcache_content_state[cache_way*m_dcache_sets+cache_set] == LINE_CACHE_DATA_NOT_DIRTY ) … … 2996 2996 if ( m_debug_activated ) 2997 2997 std::cout << " <PROC " << name() << " DCACHE_IDLE>" 2998 << " WRITE REQ " 2998 << " WRITE REQ " 2999 2999 << " / wbuf_request = " << wbuf_request 3000 3000 << " / updt_request = " << updt_request … … 3018 3018 { 3019 3019 if ( (r_mmu_mode.read() & DATA_TLB_MASK ) 3020 and not tlb_flags.d ) 3020 and not tlb_flags.d ) // Dirty bit must be set 3021 3021 { 3022 3022 // The PTE physical address is obtained from the nline value (dtlb), 3023 3023 // and the word index (virtual address) 3024 if ( tlb_flags.b ) 3024 if ( tlb_flags.b ) // PTE1 3025 3025 { 3026 3026 r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) | 3027 3027 (paddr_t)((m_dreq.addr>>19) & 0x3c); 3028 3028 } 3029 else 3029 else // PTE2 3030 3030 { 3031 3031 r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) | … … 3037 3037 m_drsp.rdata = 0; 3038 3038 } 3039 else 3039 else // SC request accepted 3040 3040 { 3041 3041 #ifdef INSTRUMENTATION … … 3054 3054 else // local fail 3055 3055 { 3056 3057 3058 3056 m_drsp.valid = true; 3057 m_drsp.error = false; 3058 m_drsp.rdata = 0x1; 3059 3059 } 3060 3060 } … … 3065 3065 3066 3066 // itlb miss request 3067 3067 else if ( r_icache_tlb_miss_req.read() and not wbuf_write_miss ) 3068 3068 { 3069 3069 r_dcache_tlb_ins = true; … … 3091 3091 // r_mmu_ins_* or r_mmu_data* error reporting registers. 3092 3092 { 3093 uint32_t 3094 bool 3095 paddr_t 3093 uint32_t ptba = 0; 3094 bool bypass; 3095 paddr_t pte_paddr; 3096 3096 3097 3097 // evaluate bypass in order to skip first level page table access 3098 if ( r_dcache_tlb_ins.read() ) 3098 if ( r_dcache_tlb_ins.read() ) // itlb miss 3099 3099 { 3100 3100 bypass = r_itlb.get_bypass(r_dcache_tlb_vaddr.read(), &ptba); 3101 3101 } 3102 else 3102 else // dtlb miss 3103 3103 { 3104 3104 bypass = r_dtlb.get_bypass(r_dcache_tlb_vaddr.read(), &ptba); … … 3137 3137 } 3138 3138 ///////////////////////// 3139 case DCACHE_TLB_PTE1_GET: 3139 case DCACHE_TLB_PTE1_GET: // try to read a PT1 entry in dcache 3140 3140 { 3141 3141 // coherence clack request (from DSPIN CLACK) … … 3155 3155 } 3156 3156 3157 uint32_t 3158 size_t 3159 size_t 3160 size_t 3157 uint32_t entry; 3158 size_t way; 3159 size_t set; 3160 size_t word; 3161 3161 int cache_state; 3162 3162 r_dcache.read( r_dcache_tlb_paddr.read(), … … 3174 3174 if (( cache_state == CACHE_SLOT_STATE_VALID_NCC ) or ( cache_state == CACHE_SLOT_STATE_VALID_CC )) 3175 3175 { 3176 if ( not (entry & PTE_V_MASK) ) 3176 if ( not (entry & PTE_V_MASK) ) // unmapped 3177 3177 { 3178 3178 if ( r_dcache_tlb_ins.read() ) … … 3195 3195 if ( m_debug_activated ) 3196 3196 { 3197 std::cout << " <PROC " << name() 3197 std::cout << " <PROC " << name() 3198 3198 << " DCACHE_TLB_PTE1_GET> HIT in dcache, but unmapped" 3199 3199 << std::hex << " / paddr = " << r_dcache_tlb_paddr.read() … … 3206 3206 3207 3207 } 3208 else if( entry & PTE_T_MASK ) 3208 else if( entry & PTE_T_MASK ) // PTD : me must access PT2 3209 3209 { 3210 3210 // mark the cache line ac containing a PTD … … 3212 3212 3213 3213 // register bypass 3214 if ( r_dcache_tlb_ins.read() ) 3214 if ( r_dcache_tlb_ins.read() ) // itlb 3215 3215 { 3216 3216 r_itlb.set_bypass(r_dcache_tlb_vaddr.read(), … … 3218 3218 r_dcache_tlb_paddr.read() / (m_icache_words<<2) ); 3219 3219 } 3220 else 3220 else // dtlb 3221 3221 { 3222 3222 r_dtlb.set_bypass(r_dcache_tlb_vaddr.read(), … … 3232 3232 if ( m_debug_activated ) 3233 3233 { 3234 std::cout << " <PROC " << name() 3234 std::cout << " <PROC " << name() 3235 3235 << " DCACHE_TLB_PTE1_GET> HIT in dcache" 3236 3236 << std::hex << " / paddr = " << r_dcache_tlb_paddr.read() … … 3242 3242 #endif 3243 3243 } 3244 else 3244 else // PTE1 : we must update the TLB 3245 3245 { 3246 3246 r_dcache_content_state[m_icache_sets*way+set] = LINE_CACHE_IN_TLB; … … 3256 3256 if ( m_debug_activated ) 3257 3257 { 3258 std::cout << " <PROC " << name() 3258 std::cout << " <PROC " << name() 3259 3259 << " DCACHE_TLB_PTE1_GET> HIT in dcache" 3260 3260 << std::hex << " / paddr = " << r_dcache_tlb_paddr.read() … … 3272 3272 r_dcache_fsm = DCACHE_TLB_PTE1_GET; 3273 3273 } 3274 else 3274 else // we must load the missing cache line in dcache 3275 3275 { 3276 3276 r_dcache_vci_miss_req = true; … … 3283 3283 if ( m_debug_activated ) 3284 3284 { 3285 std::cout << " <PROC " << name() 3285 std::cout << " <PROC " << name() 3286 3286 << " DCACHE_TLB_PTE1_GET> MISS in dcache:" 3287 3287 << " PTE1 address = " << std::hex << r_dcache_tlb_paddr.read() << std::endl; … … 3292 3292 } 3293 3293 //////////////////////////// 3294 case DCACHE_TLB_PTE1_SELECT: 3295 { 3296 size_t 3297 size_t 3294 case DCACHE_TLB_PTE1_SELECT: // select a slot for PTE1 3295 { 3296 size_t way; 3297 size_t set; 3298 3298 3299 3299 if ( r_dcache_tlb_ins.read() ) … … 3325 3325 { 3326 3326 if ( r_dcache_tlb_ins.read() ) 3327 std::cout << " <PROC " << name() 3327 std::cout << " <PROC " << name() 3328 3328 << " DCACHE_TLB_PTE1_SELECT> Select a slot in ITLB:"; 3329 3329 else 3330 std::cout << " <PROC " << name() 3330 std::cout << " <PROC " << name() 3331 3331 << ".DCACHE_TLB_PTE1_SELECT> Select a slot in DTLB:"; 3332 3332 std::cout << " way = " << std::dec << way … … 3337 3337 } 3338 3338 ////////////////////////// 3339 case DCACHE_TLB_PTE1_UPDT: 3339 case DCACHE_TLB_PTE1_UPDT: // write a new PTE1 in tlb after testing the L/R bit 3340 3340 // - if L/R bit already set, exit the sub-fsm. 3341 3341 // - if not, we update the page table but we dont write … … 3343 3343 // the coherence mechanism. 3344 3344 { 3345 paddr_t 3345 paddr_t nline = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2); 3346 3346 uint32_t pte = r_dcache_tlb_pte_flags.read(); 3347 bool 3348 bool 3347 bool pt_updt = false; 3348 bool local = true; 3349 3349 3350 3350 // We should compute the access locality: … … 3355 3355 // As long as this computation is not done, all access are local. 3356 3356 3357 if ( local ) 3357 if ( local ) // local access 3358 3358 { 3359 3359 if ( not ((pte & PTE_L_MASK) == PTE_L_MASK) ) // we must set the L bit … … 3366 3366 } 3367 3367 } 3368 else 3368 else // remote access 3369 3369 { 3370 3370 if ( not ((pte & PTE_R_MASK) == PTE_R_MASK) ) // we must set the R bit … … 3378 3378 } 3379 3379 3380 if ( not pt_updt ) 3380 if ( not pt_updt ) // update TLB and return 3381 3381 { 3382 3382 if ( r_dcache_tlb_ins.read() ) 3383 3383 { 3384 r_itlb.write( true, 3384 r_itlb.write( true, // 2M page 3385 3385 pte, 3386 0, 3386 0, // argument unused for a PTE1 3387 3387 r_dcache_tlb_vaddr.read(), 3388 3388 r_dcache_tlb_way.read(), … … 3396 3396 if ( m_debug_activated ) 3397 3397 { 3398 std::cout << " <PROC " << name() 3398 std::cout << " <PROC " << name() 3399 3399 << " DCACHE_TLB_PTE1_UPDT> write PTE1 in ITLB" 3400 3400 << " / set = " << std::dec << r_dcache_tlb_set.read() … … 3406 3406 else 3407 3407 { 3408 r_dtlb.write( true, 3408 r_dtlb.write( true, // 2M page 3409 3409 pte, 3410 0, 3410 0, // argument unused for a PTE1 3411 3411 r_dcache_tlb_vaddr.read(), 3412 3412 r_dcache_tlb_way.read(), … … 3420 3420 if ( m_debug_activated ) 3421 3421 { 3422 std::cout << " <PROC " << name() 3422 std::cout << " <PROC " << name() 3423 3423 << " DCACHE_TLB_PTE1_UPDT> write PTE1 in DTLB" 3424 3424 << " / set = " << std::dec << r_dcache_tlb_set.read() … … 3437 3437 if ( m_debug_activated ) 3438 3438 { 3439 std::cout << " <PROC " << name() 3439 std::cout << " <PROC " << name() 3440 3440 << " DCACHE_TLB_PTE1_UPDT> L/R bit update required" 3441 3441 << std::endl; … … 3446 3446 } 3447 3447 ///////////////////////// 3448 case DCACHE_TLB_PTE2_GET: 3448 case DCACHE_TLB_PTE2_GET: // Try to get a PTE2 (64 bits) in the dcache 3449 3449 { 3450 3450 // coherence clack request (from DSPIN CLACK) … … 3464 3464 } 3465 3465 3466 uint32_t 3467 uint32_t 3468 size_t 3469 size_t 3470 size_t 3466 uint32_t pte_flags = 0; 3467 uint32_t pte_ppn = 0; 3468 size_t way = 0; 3469 size_t set = 0; 3470 size_t word = 0; 3471 3471 int cache_state = 0; 3472 3472 … … 3484 3484 if ((cache_state == CACHE_SLOT_STATE_VALID_CC) or (cache_state == CACHE_SLOT_STATE_VALID_NCC)) 3485 3485 { 3486 if ( not (pte_flags & PTE_V_MASK) ) 3486 if ( not (pte_flags & PTE_V_MASK) ) // unmapped 3487 3487 { 3488 3488 if ( r_dcache_tlb_ins.read() ) … … 3512 3512 #endif 3513 3513 } 3514 else 3514 else // mapped : we must update the TLB 3515 3515 { 3516 3516 r_dcache_content_state[m_dcache_sets*way+set] = LINE_CACHE_IN_TLB; … … 3527 3527 if ( m_debug_activated ) 3528 3528 { 3529 std::cout << " <PROC " << name() 3529 std::cout << " <PROC " << name() 3530 3530 << " DCACHE_TLB_PTE2_GET> HIT in dcache:" 3531 3531 << " PTE_FLAGS = " << std::hex << pte_flags … … 3543 3543 if ( m_debug_activated ) 3544 3544 { 3545 std::cout << " <PROC " << name() 3545 std::cout << " <PROC " << name() 3546 3546 << " DCACHE_TLB_PTE2_GET> ZOMBI in dcache: waiting cleanup ack" 3547 3547 << std::endl; … … 3577 3577 { 3578 3578 r_itlb.select( r_dcache_tlb_vaddr.read(), 3579 false, 3579 false, // PTE2 3580 3580 &way, 3581 3581 &set ); … … 3587 3587 { 3588 3588 r_dtlb.select( r_dcache_tlb_vaddr.read(), 3589 false, 3589 false, // PTE2 3590 3590 &way, 3591 3591 &set ); … … 3614 3614 } 3615 3615 ////////////////////////// 3616 case DCACHE_TLB_PTE2_UPDT: 3616 case DCACHE_TLB_PTE2_UPDT: // write a new PTE2 in tlb after testing the L/R bit 3617 3617 // - if L/R bit already set, exit the sub-fsm. 3618 3618 // - if not, we update the page table but we dont write … … 3620 3620 // the coherence mechanism. 3621 3621 { 3622 paddr_t 3622 paddr_t nline = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2); 3623 3623 uint32_t pte_flags = r_dcache_tlb_pte_flags.read(); 3624 3624 uint32_t pte_ppn = r_dcache_tlb_pte_ppn.read(); … … 3633 3633 // As long as this computation is not done, all access are local. 3634 3634 3635 if ( local ) 3635 if ( local ) // local access 3636 3636 { 3637 3637 if ( not ((pte_flags & PTE_L_MASK) == PTE_L_MASK) ) // we must set the L bit … … 3641 3641 r_dcache_vci_cas_new = pte_flags | PTE_L_MASK; 3642 3642 pte_flags = pte_flags | PTE_L_MASK; 3643 3643 r_dcache_tlb_pte_flags = pte_flags; 3644 3644 } 3645 3645 } … … 3652 3652 r_dcache_vci_cas_new = pte_flags | PTE_R_MASK; 3653 3653 pte_flags = pte_flags | PTE_R_MASK; 3654 3654 r_dcache_tlb_pte_flags = pte_flags; 3655 3655 } 3656 3656 } … … 3660 3660 if ( r_dcache_tlb_ins.read() ) 3661 3661 { 3662 r_itlb.write( false, 3662 r_itlb.write( false, // 4K page 3663 3663 pte_flags, 3664 3664 pte_ppn, … … 3684 3684 else 3685 3685 { 3686 r_dtlb.write( false, 3686 r_dtlb.write( false, // 4K page 3687 3687 pte_flags, 3688 3688 pte_ppn, … … 3711 3711 else // update page table but not TLB 3712 3712 { 3713 r_dcache_fsm = DCACHE_TLB_LR_UPDT; 3713 r_dcache_fsm = DCACHE_TLB_LR_UPDT; // dcache and page table update 3714 3714 3715 3715 #if DEBUG_DCACHE … … 3772 3772 } 3773 3773 3774 r_dcache_fsm = DCACHE_TLB_RETURN; 3774 r_dcache_fsm = DCACHE_TLB_RETURN; 3775 3775 } 3776 3776 else … … 3790 3790 } 3791 3791 //////////////////////// 3792 case DCACHE_TLB_LR_WAIT: 3792 case DCACHE_TLB_LR_WAIT: // Waiting the response to SC transaction for DIRTY bit. 3793 3793 // We consume the response in rsp FIFO, 3794 3794 // and exit the sub-fsm, but we don't … … 3815 3815 } 3816 3816 3817 if ( r_vci_rsp_data_error.read() ) 3817 if ( r_vci_rsp_data_error.read() ) // bus error 3818 3818 { 3819 3819 std::cout << "BUS ERROR in DCACHE_TLB_LR_WAIT state" << std::endl; … … 3821 3821 exit(0); 3822 3822 } 3823 3824 3823 else if ( r_vci_rsp_fifo_dcache.rok() ) // response available 3824 { 3825 3825 #if DEBUG_DCACHE 3826 3826 if ( m_debug_activated ) … … 3836 3836 } 3837 3837 /////////////////////// 3838 case DCACHE_TLB_RETURN: 3838 case DCACHE_TLB_RETURN: // return to caller depending on tlb miss type 3839 3839 { 3840 3840 #if DEBUG_DCACHE … … 3850 3850 } 3851 3851 /////////////////////// 3852 case DCACHE_XTN_SWITCH: 3852 case DCACHE_XTN_SWITCH: // The r_ptpr registers must be written, 3853 3853 // and both itlb and dtlb must be flushed. 3854 3854 // Caution : the itlb miss requests must be taken … … 3890 3890 } 3891 3891 ///////////////////// 3892 case DCACHE_XTN_SYNC: 3892 case DCACHE_XTN_SYNC: // waiting until write buffer empty 3893 3893 // The coherence request must be taken 3894 3894 // as there is a risk of dead-lock … … 3959 3959 } 3960 3960 ///////////////////////// 3961 case DCACHE_XTN_DC_FLUSH: 3961 case DCACHE_XTN_DC_FLUSH: // Invalidate sequencially all cache lines, using 3962 3962 // r_dcache_flush_count as a slot counter, 3963 3963 // looping in this state until all slots have been visited. … … 4125 4125 } 4126 4126 ///////////////////////// 4127 case DCACHE_XTN_DT_INVAL: 4127 case DCACHE_XTN_DT_INVAL: // handling processor XTN_DTLB_INVAL request 4128 4128 { 4129 4129 r_dtlb.inval(r_dcache_save_wdata.read()); … … 4135 4135 case DCACHE_XTN_DC_INVAL_VA: // selective cache line invalidate with virtual address 4136 4136 // requires 3 cycles: access tlb, read cache, inval cache 4137 4137 // we compute the physical address in this state 4138 4138 { 4139 4139 paddr_t paddr; 4140 4140 bool hit; 4141 4141 4142 if ( r_mmu_mode.read() & DATA_TLB_MASK ) 4142 if ( r_mmu_mode.read() & DATA_TLB_MASK ) // dtlb activated 4143 4143 { 4144 4144 … … 4149 4149 &paddr ); 4150 4150 } 4151 else 4151 else // dtlb not activated 4152 4152 { 4153 4153 paddr = (paddr_t)r_dcache_save_wdata.read(); 4154 if (vci_param::N > 32) 4154 if (vci_param::N > 32) 4155 4155 paddr = paddr | ((paddr_t)(r_dcache_paddr_ext.read()) << 32); 4156 4156 hit = true; 4157 4157 } 4158 4158 4159 if ( hit ) 4159 if ( hit ) // tlb hit 4160 4160 { 4161 4161 r_dcache_save_paddr = paddr; 4162 4162 r_dcache_fsm = DCACHE_XTN_DC_INVAL_PA; 4163 4163 } 4164 else 4165 4164 else // tlb miss 4165 { 4166 4166 4167 4167 #ifdef INSTRUMENTATION 4168 4168 m_cpt_data_tlb_miss++; 4169 4169 #endif 4170 r_dcache_tlb_ins = false; 4170 r_dcache_tlb_ins = false; // dtlb 4171 4171 r_dcache_tlb_vaddr = r_dcache_save_wdata.read(); 4172 4172 r_dcache_fsm = DCACHE_TLB_MISS; … … 4190 4190 // In this state we read dcache. 4191 4191 { 4192 size_t 4193 size_t 4194 size_t 4192 size_t way; 4193 size_t set; 4194 size_t word; 4195 4195 int state; 4196 4196 … … 4204 4204 &word ); 4205 4205 4206 if ((state == CACHE_SLOT_STATE_VALID_CC) or (state == CACHE_SLOT_STATE_VALID_NCC)) 4206 if ((state == CACHE_SLOT_STATE_VALID_CC) or (state == CACHE_SLOT_STATE_VALID_NCC)) // inval to be done 4207 4207 { 4208 4208 r_dcache_xtn_way = way; … … 4210 4210 r_dcache_xtn_state = state; 4211 4211 r_dcache_xtn_data_addr = r_dcache_save_paddr.read()&~0x3F; 4212 4212 4213 4213 if( (state == CACHE_SLOT_STATE_VALID_NCC) and (r_dcache_content_state[way*m_dcache_sets+set] == LINE_CACHE_DATA_NOT_DIRTY) ) 4214 4214 { … … 4216 4216 } 4217 4217 r_dcache_fsm = DCACHE_XTN_DC_INVAL_GO; 4218 4219 } 4220 else 4218 4219 } 4220 else // miss : nothing to do 4221 4221 { 4222 4222 r_dcache_fsm = DCACHE_IDLE; … … 4240 4240 //////////////////////////// 4241 4241 case DCACHE_XTN_DC_INVAL_GO: // In this state, we invalidate the cache line 4242 4242 // Blocked if previous cleanup not completed 4243 4243 // Test if itlb or dtlb inval is required 4244 4244 { … … 4246 4246 { 4247 4247 int state = r_dcache_xtn_state.read(); 4248 size_t 4249 size_t 4248 size_t way = r_dcache_xtn_way.read(); 4249 size_t set = r_dcache_xtn_set.read(); 4250 4250 paddr_t nline = r_dcache_save_paddr.read() / (m_dcache_words<<2); 4251 4251 … … 4323 4323 } 4324 4324 #endif 4325 4325 } 4326 4326 break; 4327 4327 } … … 4363 4363 4364 4364 ////////////////////////////// 4365 case DCACHE_XTN_DC_INVAL_END: 4365 case DCACHE_XTN_DC_INVAL_END: // send response to processor XTN request 4366 4366 { 4367 4367 r_dcache_fsm = DCACHE_IDLE; … … 4531 4531 } 4532 4532 /////////////////////// 4533 case DCACHE_MISS_CLEAN: 4533 case DCACHE_MISS_CLEAN: // switch the slot to ZOMBI state 4534 4534 // and possibly request itlb or dtlb invalidate 4535 4535 { … … 4585 4585 } 4586 4586 ////////////////////// 4587 case DCACHE_MISS_WAIT: 4587 case DCACHE_MISS_WAIT: // waiting the response to a miss request from VCI_RSP FSM 4588 4588 // This state is in charge of error signaling 4589 4589 // There is 5 types of error depending on the requester … … 4618 4618 } 4619 4619 4620 if ( r_vci_rsp_data_error.read() ) 4620 if ( r_vci_rsp_data_error.read() ) // bus error 4621 4621 { 4622 4622 switch ( r_dcache_miss_type.read() ) … … 4672 4672 r_vci_rsp_data_error = false; 4673 4673 } 4674 else if ( r_vci_rsp_fifo_dcache.rok() ) 4674 else if ( r_vci_rsp_fifo_dcache.rok() ) // valid response available 4675 4675 { 4676 4676 r_dcache_miss_word = 0; 4677 4677 r_dcache_fsm = DCACHE_MISS_DATA_UPDT; 4678 4678 } 4679 4679 break; 4680 4680 } 4681 4681 ////////////////////////// 4682 case DCACHE_MISS_DATA_UPDT: 4682 case DCACHE_MISS_DATA_UPDT: // update the dcache (one word per cycle) 4683 4683 { 4684 4684 if ( m_dreq.valid) m_cost_data_miss_frz++; 4685 4685 4686 if ( r_vci_rsp_fifo_dcache.rok() && r_vci_rsp_fifo_rpktid.rok()) 4686 if ( r_vci_rsp_fifo_dcache.rok() && r_vci_rsp_fifo_rpktid.rok()) // one word available 4687 4687 { 4688 4688 #ifdef INSTRUMENTATION … … 4860 4860 } 4861 4861 4862 if ( r_vci_rsp_data_error.read() ) 4862 if ( r_vci_rsp_data_error.read() ) // bus error 4863 4863 { 4864 4864 if(r_dcache_vci_unc_write.read()) … … 4873 4873 break; 4874 4874 } 4875 4876 4875 else if ( r_vci_rsp_fifo_dcache.rok() ) // data available 4876 { 4877 4877 // consume data 4878 4878 vci_rsp_fifo_dcache_get = true; … … 4882 4882 if ( m_dreq.valid and (m_dreq.addr == r_dcache_save_vaddr.read()) ) 4883 4883 { 4884 4884 m_drsp.valid = true; 4885 4885 m_drsp.error = false; 4886 4887 } 4888 4886 m_drsp.rdata = r_vci_rsp_fifo_dcache.read(); 4887 } 4888 } 4889 4889 break; 4890 4890 } … … 4908 4908 } 4909 4909 4910 if ( r_vci_rsp_data_error.read() ) 4910 if ( r_vci_rsp_data_error.read() ) // bus error 4911 4911 { 4912 4912 r_mmu_detr = MMU_READ_DATA_ILLEGAL_ACCESS; … … 4918 4918 break; 4919 4919 } 4920 4921 4920 else if ( r_vci_rsp_fifo_dcache.rok() ) // data available 4921 { 4922 4922 // consume data 4923 4923 vci_rsp_fifo_dcache_get = true; … … 4940 4940 r_dcache_fsm = DCACHE_IDLE; 4941 4941 } 4942 4942 } 4943 4943 break; 4944 4944 } 4945 4945 //////////////////// 4946 case DCACHE_SC_WAIT: 4946 case DCACHE_SC_WAIT: // waiting VCI response to a SC transaction 4947 4947 { 4948 4948 // coherence clack request (from DSPIN CLACK) … … 4962 4962 } 4963 4963 4964 if ( r_vci_rsp_data_error.read() ) 4964 if ( r_vci_rsp_data_error.read() ) // bus error 4965 4965 { 4966 4966 r_mmu_detr = MMU_READ_DATA_ILLEGAL_ACCESS; … … 4972 4972 break; 4973 4973 } 4974 4975 4974 else if ( r_vci_rsp_fifo_dcache.rok() ) // response available 4975 { 4976 4976 // consume response 4977 4977 vci_rsp_fifo_dcache_get = true; … … 4979 4979 m_drsp.rdata = r_vci_rsp_fifo_dcache.read(); 4980 4980 r_dcache_fsm = DCACHE_IDLE; 4981 4981 } 4982 4982 break; 4983 4983 } 4984 4984 ////////////////////////// 4985 case DCACHE_DIRTY_GET_PTE: 4985 case DCACHE_DIRTY_GET_PTE: // This sub_fsm set the PTE Dirty bit in memory 4986 4986 // before handling a processor WRITE or SC request 4987 4987 // Input argument is r_dcache_dirty_paddr … … 5083 5083 if (!r_cas_islocal.read()) 5084 5084 { 5085 if ( r_vci_rsp_data_error.read() ) 5085 if ( r_vci_rsp_data_error.read() ) // bus error 5086 5086 { 5087 5087 std::cout << "BUS ERROR in DCACHE_DIRTY_WAIT state" << std::endl; … … 5089 5089 exit(0); 5090 5090 } 5091 else if ( r_vci_rsp_fifo_dcache.rok() ) 5091 else if ( r_vci_rsp_fifo_dcache.rok() ) // response available 5092 5092 { 5093 5093 vci_rsp_fifo_dcache_get = true; … … 5155 5155 // << " DCACHE_CC_CHECK> paddr = " << paddr 5156 5156 // << " r_dcache_vci_paddr = " << r_dcache_vci_paddr.read() 5157 // << " mask = " << mask 5158 // << " (r_dcache_fsm_cc_save == DCACHE_MISS_WAIT) = " 5157 // << " mask = " << mask 5158 // << " (r_dcache_fsm_cc_save == DCACHE_MISS_WAIT) = " 5159 5159 // << (r_dcache_fsm_cc_save == DCACHE_MISS_WAIT) 5160 // << " (r_dcache_fsm_cc_save == DCACHE_MISS_DIR_UPDT) = " 5160 // << " (r_dcache_fsm_cc_save == DCACHE_MISS_DIR_UPDT) = " 5161 5161 // << (r_dcache_fsm_cc_save == DCACHE_MISS_DIR_UPDT) 5162 // << " ((r_dcache_vci_paddr.read() & mask) == (paddr & mask)) = " 5162 // << " ((r_dcache_vci_paddr.read() & mask) == (paddr & mask)) = " 5163 5163 // << ((r_dcache_vci_paddr.read() & mask) == (paddr & mask)) 5164 5164 // << std::dec <<std::endl; … … 5206 5206 } 5207 5207 5208 5208 5209 5209 // Match between MISS address and CC address 5210 5210 // note: In the same cycle we can handle a CLACK and a MISS match 5211 5211 // because the CLACK access the directory but the MISS match dont. 5212 if (r_cc_receive_dcache_req.read() and 5212 if (r_cc_receive_dcache_req.read() and 5213 5213 ((r_dcache_fsm_cc_save == DCACHE_MISS_SELECT ) or 5214 5214 (r_dcache_fsm_cc_save == DCACHE_MISS_WAIT ) or … … 5250 5250 5251 5251 // CC request handler 5252 5252 5253 5253 int state = 0; 5254 5254 size_t way = 0; … … 5365 5365 // If the type of inval request from Memcache is configuration 5366 5366 // (software), we send a classic CLEANUP 5367 if (cache_state == CACHE_SLOT_STATE_VALID_CC or r_cc_receive_dcache_inval_is_config.read()) 5367 if (cache_state == CACHE_SLOT_STATE_VALID_CC or r_cc_receive_dcache_inval_is_config.read()) 5368 5368 { 5369 5369 r_dcache.write_dir( way, … … 5388 5388 if (cache_state == CACHE_SLOT_STATE_VALID_NCC and not r_cc_receive_dcache_inval_is_config.read()) 5389 5389 { 5390 r_dcache_cc_cleanup_line_ncc = true; 5390 r_dcache_cc_cleanup_line_ncc = true; 5391 5391 if ((r_dcache_content_state[way*m_dcache_sets+set] != LINE_CACHE_DATA_NOT_DIRTY) or r_dcache_dirty_save.read() or dirty_save) //must send data 5392 5392 { … … 5404 5404 set, 5405 5405 CACHE_SLOT_STATE_ZOMBI ); 5406 5406 5407 5407 r_dcache_cc_cleanup_updt_data = false; 5408 5408 r_dcache_fsm = r_dcache_fsm_cc_save.read(); … … 5417 5417 break; 5418 5418 } 5419 5419 5420 5420 ///////////////////// 5421 5421 case DCACHE_CC_INVAL_DATA: … … 5487 5487 "ERROR in DCACHE_CC_INVAL: the r_dcache_cc_send_req " 5488 5488 "must not be set"); 5489 5489 5490 5490 if ( not r_cc_receive_updt_fifo_be.rok() ) break; 5491 5491 … … 5538 5538 } 5539 5539 /////////////////////////// 5540 case DCACHE_INVAL_TLB_SCAN: 5540 case DCACHE_INVAL_TLB_SCAN: // Scan sequencially all sets for both ITLB & DTLB 5541 5541 // It makes assumption: m_itlb_sets == m_dtlb_sets 5542 5542 // All ways are handled in parallel. … … 5554 5554 // - r_dcache_fsm_scan_save 5555 5555 { 5556 paddr_t 5556 paddr_t line = r_dcache_tlb_inval_line.read(); 5557 5557 size_t set = r_dcache_tlb_inval_set.read(); 5558 5558 size_t way; … … 5611 5611 if ( (m_ireq.valid and not m_irsp.valid) or (m_dreq.valid and not m_drsp.valid) ) 5612 5612 { 5613 m_cpt_frz_cycles++; 5614 m_cpt_stop_simulation++; 5613 m_cpt_frz_cycles++; // used for instrumentation 5614 m_cpt_stop_simulation++; // used for debug 5615 5615 if ( m_cpt_stop_simulation > m_max_frozen_cycles ) 5616 5616 { … … 5942 5942 { 5943 5943 std::cout << "ERROR in VCI_CC_VCACHE " << name() 5944 << " VCI response packet too short" 5944 << " VCI response packet too short" 5945 5945 << " for instruction miss" << std::endl; 5946 5946 exit(0); … … 6131 6131 { 6132 6132 // the new client is dcache and has a cleanup request 6133 if ( (update_last_client == 0) and 6133 if ( (update_last_client == 0) and 6134 6134 (r_dcache_cc_send_type.read() == CC_TYPE_CLEANUP)) 6135 6135 r_cc_send_fsm = CC_SEND_CLEANUP_1; 6136 6136 // the new client is dcache and has a multi acknowledgement request 6137 else if ( (update_last_client == 0) and 6137 else if ( (update_last_client == 0) and 6138 6138 (r_dcache_cc_send_type.read() == CC_TYPE_MULTI_ACK)) 6139 6139 r_cc_send_fsm = CC_SEND_MULTI_ACK; 6140 6140 // the new client is icache and has a cleanup request 6141 else if ( (update_last_client == 1) and 6141 else if ( (update_last_client == 1) and 6142 6142 (r_icache_cc_send_type.read() == CC_TYPE_CLEANUP)) 6143 6143 r_cc_send_fsm = CC_SEND_CLEANUP_1; … … 6252 6252 } 6253 6253 // test for a multi updt 6254 else if (receive_type == DspinRwtParam::TYPE_MULTI_UPDT_DATA) 6254 else if (receive_type == DspinRwtParam::TYPE_MULTI_UPDT_DATA) 6255 6255 { 6256 6256 r_cc_receive_fsm = CC_RECEIVE_DATA_UPDT_HEADER; … … 6288 6288 // not to actually post a request to an available cache => need a 6289 6289 // flip_flop to check that ? 6290 if (not (r_cc_receive_icache_req.read()) and 6290 if (not (r_cc_receive_icache_req.read()) and 6291 6291 not (r_cc_receive_dcache_req.read()) and 6292 6292 (p_dspin_m2p.write.read())) … … 6333 6333 uint64_t receive_data = p_dspin_m2p.data.read(); 6334 6334 // for data INVAL, wait for dcache to take the request 6335 if (p_dspin_m2p.write.read() and 6335 if (p_dspin_m2p.write.read() and 6336 6336 not r_cc_receive_dcache_req.read() ) 6337 6337 { … … 6352 6352 uint64_t receive_data = p_dspin_m2p.data.read(); 6353 6353 // for ins INVAL, wait for icache to take the request 6354 if (p_dspin_m2p.write.read() and 6354 if (p_dspin_m2p.write.read() and 6355 6355 not r_cc_receive_icache_req.read() ) 6356 6356 { … … 6472 6472 6473 6473 ///////////////// DSPIN CLACK interface /////////////// 6474 6474 6475 6475 uint64_t clack_type = DspinRwtParam::dspin_get(r_dspin_clack_flit.read(), 6476 6476 DspinRwtParam::CLACK_TYPE); … … 6559 6559 p_vci.pktid = 0; 6560 6560 p_vci.srcid = m_srcid; 6561 p_vci.cons = is_sc_or_cas; 6562 p_vci.contig = not is_sc_or_cas; 6561 p_vci.cons = is_sc_or_cas; 6562 p_vci.contig = not is_sc_or_cas; 6563 6563 p_vci.wrap = false; 6564 6564 p_vci.clen = 0; … … 6567 6567 if ( m_monitor_ok ) { 6568 6568 if ( p_vci.cmdack.read() == true and p_vci.cmdval == true) { 6569 if (((p_vci.address.read()) >= m_monitor_base) and 6569 if (((p_vci.address.read()) >= m_monitor_base) and 6570 6570 ((p_vci.address.read()) < m_monitor_base + m_monitor_length) ) { 6571 6571 std::cout << "CC_VCACHE Monitor " << name() << std::hex 6572 << " Access type = " << vci_cmd_type_str[p_vci.cmd.read()] 6572 << " Access type = " << vci_cmd_type_str[p_vci.cmd.read()] 6573 6573 << " Pktid type = " << vci_pktid_type_str[p_vci.pktid.read()] 6574 6574 << " : address = " << p_vci.address.read() 6575 << " / be = " << p_vci.be.read(); 6575 << " / be = " << p_vci.be.read(); 6576 6576 if ( p_vci.cmd.read() == vci_param::CMD_WRITE ) { 6577 6577 std::cout << " / data = " << p_vci.wdata.read(); … … 6721 6721 } // end switch r_vci_rsp_fsm 6722 6722 6723 6724 // Send coherence packets on DSPIN P2M 6725 // it depends on the CC_SEND FSM 6723 6724 // Send coherence packets on DSPIN P2M 6725 // it depends on the CC_SEND FSM 6726 6726 6727 6727 uint64_t dspin_send_data = 0; … … 6747 6747 if(r_cc_send_last_client.read() == 0) // dcache active request 6748 6748 { 6749 uint64_t dest = (uint64_t) r_dcache_cc_send_nline.read() 6750 >> (m_nline_width - m_x_width - m_y_width) 6749 uint64_t dest = (uint64_t) r_dcache_cc_send_nline.read() 6750 >> (m_nline_width - m_x_width - m_y_width) 6751 6751 << (DspinRwtParam::GLOBALID_WIDTH - m_x_width - m_y_width); 6752 6752 DspinRwtParam::dspin_set(dspin_send_data, … … 6772 6772 else // icache active request 6773 6773 { 6774 uint64_t dest = (uint64_t) r_icache_cc_send_nline.read() 6775 >> (m_nline_width - m_x_width - m_y_width) 6774 uint64_t dest = (uint64_t) r_icache_cc_send_nline.read() 6775 >> (m_nline_width - m_x_width - m_y_width) 6776 6776 << (DspinRwtParam::GLOBALID_WIDTH - m_x_width - m_y_width); 6777 6777 … … 6833 6833 r_cc_send_data_fifo.read(), 6834 6834 DspinRwtParam::CLEANUP_DATA_UPDT); 6835 6835 6836 6836 p_dspin_p2m.data = dspin_send_data; 6837 6837 p_dspin_p2m.write = true; … … 6852 6852 if(r_cc_send_last_client.read() == 0) // dcache active request 6853 6853 { 6854 uint64_t dest = (uint64_t) r_dcache_cc_send_nline.read() 6855 >> (m_nline_width - m_x_width - m_y_width) 6854 uint64_t dest = (uint64_t) r_dcache_cc_send_nline.read() 6855 >> (m_nline_width - m_x_width - m_y_width) 6856 6856 << (DspinRwtParam::GLOBALID_WIDTH - m_x_width - m_y_width); 6857 6857 6858 6858 DspinRwtParam::dspin_set(dspin_send_data, 6859 6859 dest, … … 6866 6866 else // icache active request 6867 6867 { 6868 uint64_t dest = (uint64_t) r_icache_cc_send_nline.read() 6869 >> (m_nline_width - m_x_width - m_y_width) 6868 uint64_t dest = (uint64_t) r_icache_cc_send_nline.read() 6869 >> (m_nline_width - m_x_width - m_y_width) 6870 6870 << (DspinRwtParam::GLOBALID_WIDTH - m_x_width - m_y_width); 6871 6871 6872 6872 6873 6873 DspinRwtParam::dspin_set(dspin_send_data, … … 6889 6889 6890 6890 // Receive coherence packets 6891 // It depends on the CC_RECEIVE FSM 6891 // It depends on the CC_RECEIVE FSM 6892 6892 switch( r_cc_receive_fsm.read() ) 6893 6893 { … … 6946 6946 case CC_RECEIVE_INS_UPDT_HEADER: 6947 6947 { 6948 if ( not r_cc_receive_icache_req.read()) 6948 if ( not r_cc_receive_icache_req.read()) 6949 6949 p_dspin_m2p.read = true; 6950 6950 else … … 7001 7001 } 7002 7002 7003 p_dspin_clack.read = dspin_clack_get; 7003 p_dspin_clack.read = dspin_clack_get; 7004 7004 } // end genMoore 7005 7005
Note: See TracChangeset
for help on using the changeset viewer.