Changeset 188 for trunk/modules/vci_cc_xcache_wrapper_v4/caba/source
- Timestamp:
- Jan 8, 2012, 2:36:49 PM (13 years ago)
- Location:
- trunk/modules/vci_cc_xcache_wrapper_v4/caba/source
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/include/vci_cc_xcache_wrapper_v4.h
r175 r188 1 1 /* -*- c++ -*- 2 * File : vci_cc_xcache_wrapper_v4.h 3 * Copyright (c) UPMC, Lip6, SoC 4 * Authors : Alain GREINER 5 * Date : 27/11/2011 2 6 * 3 7 * SOCLIB_LGPL_HEADER_BEGIN … … 20 24 * 21 25 * SOCLIB_LGPL_HEADER_END 22 *23 * Copyright (c) UPMC, Lip6, SoC24 * Alain Greiner <alain.greiner@lip6.fr>, 200825 *26 * Maintainers: alain27 26 */ 28 27 … … 38 37 #include "generic_cache.h" 39 38 #include "generic_fifo.h" 39 #include "generic_cam.h" 40 40 #include "vci_initiator.h" 41 41 #include "vci_target.h" 42 42 #include "mapping_table.h" 43 43 #include "static_assert.h" 44 45 /* 46 * ---------------------------------------------------------- 47 * Implementation 48 * ---------------------------------------------------------- 49 * 50 * CC_XCACHE_WRAPPER_MULTI_CACHE 51 * 1 - icache static partitionnement 52 * 2 - icache dedicated 53 * 54 * ---------------------------------------------------------- 55 * Debug 56 * ---------------------------------------------------------- 57 * 58 * CC_XCACHE_WRAPPER_STOP_SIMULATION 59 * stop simulation if processor is stall after a long time 60 * (configurable with "stop_simulation" function) 61 * 62 * CC_XCACHE_WRAPPER_DEBUG 63 * Add log to help the debugging 64 * 65 * CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN 66 * Number of cycle before to prinf debug message 67 * 68 * CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 69 * Print transaction between : 70 * - the cpu and the cache (icache and dcache) 71 * - vci 72 * - cleanup 73 * - coherency 74 * 75 * MWBUF_VHDL_TESTBENCH 76 * generate a vhdl testbench for multi write buffer 77 */ 78 79 // implementation 80 #ifndef CC_XCACHE_WRAPPER_MULTI_CACHE 81 #define CC_XCACHE_WRAPPER_MULTI_CACHE 2 82 // if multi_cache : 83 // <tsar toplevel>/modules/vci_mem_cache_v4/caba/source/include/mem_cache_directory_v4.h : L1_MULTI_CACHE 1 84 #endif 85 86 // debug 87 #ifndef CC_XCACHE_WRAPPER_STOP_SIMULATION 88 #define CC_XCACHE_WRAPPER_STOP_SIMULATION 1 89 #endif 90 #ifndef CC_XCACHE_WRAPPER_DEBUG 91 #define CC_XCACHE_WRAPPER_DEBUG 0 92 #endif 93 #ifndef CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN 94 #define CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN 1013300 95 #endif 96 #ifndef CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 97 #define CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 0 98 #define CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION_PATH "log" 99 #endif 100 #ifndef MWBUF_VHDL_TESTBENCH 101 #define MWBUF_VHDL_TESTBENCH 0 102 #endif 44 #include "iss2.h" 103 45 104 46 namespace soclib { … … 113 55 : public soclib::caba::BaseModule 114 56 { 115 typedef uint64_t vhdl_tb_t; 116 typedef sc_dt::sc_uint<40> addr_40; 117 typedef uint32_t data_t; 118 typedef uint32_t tag_t; 119 typedef uint32_t be_t; 120 typedef typename vci_param::fast_addr_t vci_addr_t; 57 typedef uint32_t data_t; 58 typedef uint32_t tag_t; 59 typedef uint32_t be_t; 60 typedef typename vci_param::fast_addr_t vci_addr_t; 121 61 122 enum dcache_fsm_state_e { 62 enum dcache_fsm_state_e 63 { 123 64 DCACHE_IDLE, 124 65 DCACHE_WRITE_UPDT, … … 127 68 DCACHE_MISS_UPDT, 128 69 DCACHE_UNC_WAIT, 129 DCACHE_SC_WAIT,130 70 DCACHE_INVAL, 71 DCACHE_INVAL_GO, 131 72 DCACHE_SYNC, 132 73 DCACHE_ERROR, 133 74 DCACHE_CC_CHECK, 134 75 DCACHE_CC_INVAL, 135 DCACHE_CC_CLEANUP, 136 }; 137 138 enum icache_fsm_state_e { 76 DCACHE_CC_UPDT, 77 }; 78 79 enum icache_fsm_state_e 80 { 139 81 ICACHE_IDLE, 140 82 ICACHE_MISS_VICTIM, … … 143 85 ICACHE_UNC_WAIT, 144 86 ICACHE_ERROR, 145 ICACHE_CC_CLEANUP,146 87 ICACHE_CC_CHECK, 147 88 ICACHE_CC_INVAL, 148 }; 149 150 enum cmd_fsm_state_e { 89 ICACHE_CC_UPDT, 90 }; 91 92 enum cmd_fsm_state_e 93 { 151 94 CMD_IDLE, 152 95 CMD_INS_MISS, … … 158 101 }; 159 102 160 enum rsp_fsm_state_e { 103 enum rsp_fsm_state_e 104 { 161 105 RSP_IDLE, 162 106 RSP_INS_MISS, … … 168 112 }; 169 113 170 enum tgt_fsm_state_e { 114 enum tgt_fsm_state_e 115 { 171 116 TGT_IDLE, 172 117 TGT_UPDT_WORD, … … 180 125 }; 181 126 182 enum cleanup_fsm_state_e { 183 CLEANUP_IDLE, 184 CLEANUP_REQ, 185 CLEANUP_RSP_DCACHE, 186 CLEANUP_RSP_ICACHE, 187 }; 188 189 enum transaction_type_c_e { 190 // convention with memcache 191 TYPE_DATA_CLEANUP = 0x0, 192 TYPE_INS_CLEANUP = 0x1 193 }; 194 195 enum transaction_type_rw_e { 127 enum cleanup_cmd_fsm_state_e 128 { 129 CLEANUP_DATA_IDLE, 130 CLEANUP_INS_IDLE, 131 CLEANUP_DATA_GO, 132 CLEANUP_INS_GO, 133 }; 134 135 enum transaction_type_d_e 136 { 196 137 // convention with memcache 197 138 // b0 : 1 if cached … … 202 143 TYPE_INS_UNC = 0x2, 203 144 TYPE_INS_MISS = 0x3, 204 TYPE_DATA_SC = 0x4, // sc is data and no cached205 145 }; 206 146 … … 210 150 sc_in<bool> p_clk; 211 151 sc_in<bool> p_resetn; 212 sc_in<bool> ** p_irq;//[m_nb_cpu][iss_t::n_irq];213 soclib::caba::VciInitiator<vci_param> p_vci_ini_ rw;152 sc_in<bool> * p_irq; // [iss_t::n_irq]; 153 soclib::caba::VciInitiator<vci_param> p_vci_ini_d; 214 154 soclib::caba::VciInitiator<vci_param> p_vci_ini_c; 215 soclib::caba::VciTarget<vci_param> p_vci_tgt ;155 soclib::caba::VciTarget<vci_param> p_vci_tgt_c; 216 156 217 157 private: 218 158 219 159 // STRUCTURAL PARAMETERS 220 const soclib::common::AddressDecodingTable<vci_addr_t, bool> m_cacheability_table;221 const soclib::common::Segment m_segment;222 iss_t ** m_iss; //[m_nb_cpu] 223 const uint32_t m_srcid_rw;224 const uint32_t m_srcid_c;160 const soclib::common::AddressDecodingTable<vci_addr_t, bool> m_cacheability_table; 161 const soclib::common::Segment m_segment; 162 163 const uint32_t m_srcid_d; 164 const uint32_t m_srcid_c; 225 165 226 const size_t m_nb_cpu; 227 const size_t m_nb_icache; 228 const size_t m_nb_dcache; 229 const size_t m_nb_cache; 230 const size_t m_dcache_ways; 231 const size_t m_dcache_words; 232 const uint32_t m_dcache_words_shift; 233 const size_t m_dcache_yzmask; 234 const size_t m_icache_ways; 235 const size_t m_icache_words; 236 const uint32_t m_icache_words_shift; 237 const size_t m_icache_yzmask; 238 const size_t m_cache_words; // max between m_dcache_words and m_icache_words 239 240 #if CC_XCACHE_WRAPPER_STOP_SIMULATION 241 bool m_stop_simulation; 242 uint32_t m_stop_simulation_nb_frz_cycles_max; 243 uint32_t * m_stop_simulation_nb_frz_cycles; //[m_nb_cpu] 244 #endif // CC_XCACHE_WRAPPER_STOP_SIMULATION 245 246 // REGISTERS 247 sc_signal<uint32_t> r_cpu_prior; 248 sc_signal<uint32_t> * r_icache_lock;//[m_nb_icache] 249 sc_signal<uint32_t> * r_dcache_lock;//[m_nb_dcache] 250 sc_signal<bool> * r_dcache_sync;//[m_nb_dcache] 251 252 sc_signal<int> * r_dcache_fsm; //[m_nb_dcache] 253 sc_signal<int> * r_dcache_fsm_save; //[m_nb_dcache] 254 sc_signal<addr_40> * r_dcache_addr_save; //[m_nb_dcache] 255 sc_signal<data_t> * r_dcache_wdata_save; //[m_nb_dcache] 256 sc_signal<data_t> * r_dcache_rdata_save; //[m_nb_dcache] 257 sc_signal<int> * r_dcache_type_save; //[m_nb_dcache] 258 sc_signal<be_t> * r_dcache_be_save; //[m_nb_dcache] 259 sc_signal<bool> * r_dcache_cached_save; //[m_nb_dcache] 260 sc_signal<uint32_t> * r_dcache_num_cpu_save; //[m_nb_dcache] 261 sc_signal<bool> * r_dcache_cleanup_req; //[m_nb_dcache] 262 sc_signal<addr_40> * r_dcache_cleanup_line; //[m_nb_dcache] 263 sc_signal<bool> * r_dcache_miss_req; //[m_nb_dcache] 264 sc_signal<size_t> * r_dcache_miss_way; //[m_nb_dcache] 265 sc_signal<size_t> * r_dcache_miss_set; //[m_nb_dcache] 266 sc_signal<bool> * r_dcache_unc_req; //[m_nb_dcache] 267 sc_signal<bool> * r_dcache_sc_req; //[m_nb_dcache] 268 sc_signal<bool> * r_dcache_inval_rsp; //[m_nb_dcache] 269 sc_signal<size_t> * r_dcache_update_addr; //[m_nb_dcache] 270 sc_signal<data_t> ** r_dcache_ll_data; //[m_nb_dcache][m_nb_cpu] 271 sc_signal<addr_40> ** r_dcache_ll_addr; //[m_nb_dcache][m_nb_cpu] 272 sc_signal<bool> ** r_dcache_ll_valid; //[m_nb_dcache][m_nb_cpu] 273 sc_signal<bool> * r_dcache_previous_unc; //[m_nb_dcache] 166 const size_t m_dcache_ways; 167 const size_t m_icache_ways; 168 169 const size_t m_cache_words; 170 const size_t m_cache_words_shift; 171 const vci_addr_t m_cache_yzmask; 172 173 const uint32_t m_max_frozen_cycles; 174 175 iss_t * r_iss; 176 MultiWriteBuffer<vci_addr_t> * r_wbuf; 177 GenericCache<vci_addr_t> * r_icache; 178 GenericCache<vci_addr_t> * r_dcache; 179 180 sc_signal<int> r_icache_fsm; 181 sc_signal<int> r_icache_fsm_save; // return state for coherence request 182 sc_signal<vci_addr_t> r_icache_addr_save; // address requested by proc 183 sc_signal<bool> r_icache_miss_req; // set by icache_fsm / reset by cmd_fsm 184 sc_signal<bool> r_icache_unc_req; // set by icache_fsm / reset by cmd_fsm 185 sc_signal<bool> r_icache_cleanup_req; // a victim line must be evicted 186 sc_signal<vci_addr_t> r_icache_cleanup_line; // address of the selected victim line 187 sc_signal<size_t> r_icache_cleanup_way; // way of the selected victim line 188 sc_signal<size_t> r_icache_cleanup_set; // set of the selected victim line 189 sc_signal<bool> r_icache_miss_inval; // cancellation request for pending miss 190 sc_signal<size_t> r_icache_update_word; // word index for update (intern/extern) 191 sc_signal<data_t> r_icache_unc_buf; // Non cacheable read buffer (one word) 192 sc_signal<bool> r_icache_unc_valid; // Non cacheable read buffer valid 193 sc_signal<size_t> r_icache_cc_way; // way index for coherence request 194 sc_signal<size_t> r_icache_cc_set; // set index for coherence request 195 196 sc_signal<int> r_dcache_fsm; 197 sc_signal<int> r_dcache_fsm_save; // return state when coherence request 198 sc_signal<vci_addr_t> r_dcache_addr_save; // address requested by proc 199 sc_signal<data_t> r_dcache_wdata_save; // data written (for dcache update) 200 sc_signal<be_t> r_dcache_be_save; // byte enable (for dcache update) 201 sc_signal<be_t> r_dcache_way_save; // selected way (in case of hit) 202 sc_signal<be_t> r_dcache_set_save; // selected set (in case of hit) 203 sc_signal<be_t> r_dcache_word_save; // selected word (in case of hit) 204 sc_signal<bool> r_dcache_cleanup_req; // a victim line must be evicted 205 sc_signal<vci_addr_t> r_dcache_cleanup_line; // address of the selected victim line 206 sc_signal<size_t> r_dcache_cleanup_way; // way of the selected victim line 207 sc_signal<size_t> r_dcache_cleanup_set; // set of the selected victim line 208 sc_signal<bool> r_dcache_miss_req; // set by dcache_fsm / reset by cmd_fsm 209 sc_signal<bool> r_dcache_unc_req; // set by dcache_fsm / reset by cmd_fsm 210 sc_signal<bool> r_dcache_sc_req; // set by dcache_fsm / reset by cmd_fsm 211 sc_signal<bool> r_dcache_miss_inval; // cancellation of a pending miss 212 sc_signal<size_t> r_dcache_update_word; // word index for update (intern/extern) 213 sc_signal<data_t> r_dcache_ll_data; // LL reservation data 214 sc_signal<vci_addr_t> r_dcache_ll_addr; // ll reservation address 215 sc_signal<bool> r_dcache_ll_valid; // ll reservation valid 216 sc_signal<bool> r_dcache_pending_unc_write; // Non cacheable write pending 217 sc_signal<data_t> r_dcache_unc_buf; // Non cacheable read buffer (one word) 218 sc_signal<bool> r_dcache_unc_valid; // Non cacheable read buffer valid 219 sc_signal<size_t> r_dcache_cc_way; // way index for coherence request 220 sc_signal<size_t> r_dcache_cc_set; // set index for coherence request 274 221 275 sc_signal<int> * r_icache_fsm; //[m_nb_icache]276 sc_signal<int> * r_icache_fsm_save; //[m_nb_icache]277 sc_signal<addr_40> * r_icache_addr_save; //[m_nb_icache]278 sc_signal<bool> * r_icache_miss_req; //[m_nb_icache]279 sc_signal<size_t> * r_icache_miss_way; //[m_nb_icache]280 sc_signal<size_t> * r_icache_miss_set; //[m_nb_icache]281 sc_signal<bool> * r_icache_unc_req; //[m_nb_icache]282 sc_signal<bool> * r_icache_cleanup_req; //[m_nb_icache]283 sc_signal<addr_40> * r_icache_cleanup_line; //[m_nb_icache]284 sc_signal<bool> * r_icache_inval_rsp; //[m_nb_icache]285 sc_signal<size_t> * r_icache_update_addr; //[m_nb_icache]286 sc_signal<bool> * r_icache_buf_unc_valid;//[m_nb_icache]287 288 222 sc_signal<int> r_vci_cmd_fsm; 289 sc_signal<size_t> r_vci_cmd_min; 290 sc_signal<size_t> r_vci_cmd_max; 223 sc_signal<size_t> r_vci_cmd_min; // min word index for a write burst 224 sc_signal<size_t> r_vci_cmd_max; // max word index for a write burst 291 225 sc_signal<size_t> r_vci_cmd_cpt; 292 sc_signal<bool> r_vci_cmd_dcache_prior; 293 sc_signal<uint32_t> r_vci_cmd_num_icache_prior; 294 sc_signal<uint32_t> r_vci_cmd_num_dcache_prior; 295 sc_signal<uint32_t> r_vci_cmd_num_cache; 226 sc_signal<bool> r_vci_cmd_imiss_prio; // round-robin flip-flop to access wbuf 296 227 297 228 sc_signal<int> r_vci_rsp_fsm; 298 229 sc_signal<size_t> r_vci_rsp_cpt; 299 sc_signal<uint32_t> r_vci_rsp_num_cache; 300 sc_signal<bool> * r_vci_rsp_ins_error; //[m_nb_icache] 301 sc_signal<bool> * r_vci_rsp_data_error; //[m_nb_dcache] 302 303 GenericFifo<data_t> r_vci_rsp_fifo_icache_data; 304 GenericFifo<uint32_t> r_vci_rsp_fifo_icache_num_cache; 305 GenericFifo<data_t> r_vci_rsp_fifo_dcache_data; 306 GenericFifo<uint32_t> r_vci_rsp_fifo_dcache_num_cache; 307 308 data_t * r_tgt_buf; //[m_cache_words] 309 be_t * r_tgt_be; //[m_cache_words] 310 sc_signal<uint32_t> r_cache_word; 311 312 sc_signal<int> r_vci_tgt_fsm; 313 sc_signal<addr_40> r_tgt_iaddr; 314 sc_signal<addr_40> r_tgt_daddr; 315 sc_signal<size_t> r_tgt_word; 316 sc_signal<bool> r_tgt_update; 317 sc_signal<bool> r_tgt_update_data; 318 //sc_signal<bool> r_tgt_brdcast; 230 sc_signal<bool> r_vci_rsp_ins_error; // set by rsp_fsm / reset by icache_fsm 231 sc_signal<bool> r_vci_rsp_data_error; // set by rsp_fsm / reset by dcache_fsm 232 GenericFifo<data_t> r_vci_rsp_fifo_icache; // response fifo to ICACHE FSM 233 GenericFifo<data_t> r_vci_rsp_fifo_dcache; // response FIFO to DCACHE FSM 234 235 sc_signal<int> r_tgt_fsm; // target port on coherence network 236 sc_signal<bool> r_tgt_icache_rsp; // VCI response required when true 237 sc_signal<bool> r_tgt_dcache_rsp; // VCI response required when true 238 sc_signal<vci_addr_t> r_tgt_addr; // address of the target line 239 sc_signal<size_t> r_tgt_word_min; // index of the first word to be updated 240 sc_signal<size_t> r_tgt_word_max; // index of the last word to be updated 241 sc_signal<size_t> r_tgt_word_count; // word counter to fill the tgt_buf 242 sc_signal<bool> r_tgt_update; // update request when true 243 sc_signal<bool> r_tgt_update_data; // update_data request when true 319 244 sc_signal<size_t> r_tgt_srcid; 320 245 sc_signal<size_t> r_tgt_pktid; 321 246 sc_signal<size_t> r_tgt_trdid; 322 //sc_signal<size_t> r_tgt_plen; 323 sc_signal<uint32_t> r_tgt_num_cache; 324 sc_signal<bool> * r_tgt_icache_req; //[m_nb_icache] 325 sc_signal<bool> * r_tgt_icache_rsp; //[m_nb_icache] 326 sc_signal<bool> * r_tgt_dcache_req; //[m_nb_dcache] 327 sc_signal<bool> * r_tgt_dcache_rsp; //[m_nb_dcache] 328 329 sc_signal<int> r_cleanup_fsm; // controls initiator port of the coherence network 330 sc_signal<uint32_t> r_cleanup_num_cache; 331 sc_signal<bool> r_cleanup_icache; 332 333 MultiWriteBuffer<addr_40>** r_wbuf; 334 GenericCache<vci_addr_t> ** r_icache; 335 GenericCache<vci_addr_t> ** r_dcache; 336 337 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 338 bool generate_log_transaction_file_icache; 339 bool generate_log_transaction_file_dcache; 340 bool generate_log_transaction_file_cmd; 341 bool generate_log_transaction_file_tgt; 342 bool generate_log_transaction_file_cleanup; 343 344 std::ofstream * log_transaction_file_icache; //[m_nb_cpu] 345 std::ofstream * log_transaction_file_dcache; //[m_nb_cpu] 346 std::ofstream log_transaction_file_cmd; 347 std::ofstream log_transaction_file_tgt; 348 std::ofstream log_transaction_file_cleanup; 349 #endif 350 351 #if MWBUF_VHDL_TESTBENCH 352 bool simulation_started; 353 bool generate_vhdl_testbench_mwbuf; 354 std::ofstream * vhdl_testbench_mwbuf; //[m_nb_dcache] 355 #endif 356 357 // Activity counters 358 uint32_t m_cpt_dcache_data_read; // * DCACHE DATA READ 359 uint32_t m_cpt_dcache_data_write; // * DCACHE DATA WRITE 360 uint32_t m_cpt_dcache_dir_read; // * DCACHE DIR READ 361 uint32_t m_cpt_dcache_dir_write; // * DCACHE DIR WRITE 362 363 uint32_t m_cpt_icache_data_read; // * ICACHE DATA READ 364 uint32_t m_cpt_icache_data_write; // * ICACHE DATA WRITE 365 uint32_t m_cpt_icache_dir_read; // * ICACHE DIR READ 366 uint32_t m_cpt_icache_dir_write; // * ICACHE DIR WRITE 367 368 uint32_t m_cpt_cc_update_icache; // number of coherence update packets (for icache) 369 uint32_t m_cpt_cc_update_dcache; // number of coherence update packets (for dcache) 370 uint32_t m_cpt_cc_inval_broadcast; // number of coherence inval packets 371 uint32_t m_cpt_cc_inval_icache; // number of coherence inval packets 372 uint32_t m_cpt_cc_inval_dcache; // number of coherence inval packets 373 uint32_t m_cpt_cc_update_icache_word_useful; // number of valid word in coherence update packets 374 uint32_t m_cpt_cc_update_dcache_word_useful; // number of valid word in coherence update packets 375 376 uint32_t * m_cpt_frz_cycles; // * number of cycles where the cpu is frozen 377 uint32_t m_cpt_total_cycles; // total number of cycles 378 379 uint32_t m_cpt_data_read; // number of data read 380 uint32_t m_cpt_data_read_miss; // number of data read miss 381 uint32_t m_cpt_data_read_uncached; // number of data read uncached 382 uint32_t m_cpt_data_write; // number of data write 383 uint32_t m_cpt_data_write_miss; // number of data write miss 384 uint32_t m_cpt_data_write_uncached; // number of data write uncached 385 uint32_t m_cpt_ins_miss; // * number of instruction miss 386 387 uint32_t m_cost_write_frz; // * number of frozen cycles related to write buffer 388 uint32_t m_cost_data_miss_frz; // * number of frozen cycles related to data miss 389 uint32_t m_cost_unc_read_frz; // * number of frozen cycles related to uncached read 390 uint32_t m_cost_ins_miss_frz; // * number of frozen cycles related to ins miss 391 392 uint32_t m_cpt_imiss_transaction; // * number of VCI instruction miss transactions 393 uint32_t m_cpt_dmiss_transaction; // * number of VCI data miss transactions 394 uint32_t m_cpt_unc_transaction; // * number of VCI uncached read transactions 395 uint32_t m_cpt_data_write_transaction; // * number of VCI write transactions 396 397 uint32_t m_cost_imiss_transaction; // * cumulated duration for VCI IMISS transactions 398 uint32_t m_cost_dmiss_transaction; // * cumulated duration for VCI DMISS transactions 399 uint32_t m_cost_unc_transaction; // * cumulated duration for VCI UNC transactions 400 uint32_t m_cost_write_transaction; // * cumulated duration for VCI WRITE transactions 401 uint32_t m_length_write_transaction; // * cumulated length for VCI WRITE transactions 402 403 uint32_t * m_cpt_icache_access; //[m_nb_icache] 404 uint32_t * m_cpt_dcache_access; //[m_nb_dcache] 405 uint32_t * m_cpt_dcache_hit_after_miss_read; //[m_nb_dcache] 406 uint32_t * m_cpt_dcache_hit_after_miss_write; //[m_nb_dcache] 407 uint32_t * m_cpt_dcache_store_after_store; //[m_nb_dcache] 408 uint32_t * m_cpt_icache_miss_victim_wait; //[m_nb_icache] 409 uint32_t * m_cpt_dcache_miss_victim_wait; //[m_nb_dcache] 410 411 uint32_t ** m_cpt_fsm_dcache; //[m_nb_dcache] 412 uint32_t ** m_cpt_fsm_icache; //[m_nb_icache] 413 uint32_t * m_cpt_fsm_cmd; 414 uint32_t * m_cpt_fsm_rsp; 415 uint32_t * m_cpt_fsm_tgt; 416 uint32_t * m_cpt_fsm_cleanup; 417 418 // Non blocking multi-cache 419 typename iss_t::InstructionRequest * ireq ; //[m_nb_icache] 420 typename iss_t::InstructionResponse * irsp ; //[m_nb_icache] 421 bool * ireq_cached ; //[m_nb_icache] 422 uint32_t * ireq_num_cpu; //[m_nb_dcache] 423 typename iss_t::DataRequest * dreq ; //[m_nb_dcache] 424 typename iss_t::DataResponse * drsp ; //[m_nb_dcache] 425 bool * dreq_cached ; //[m_nb_dcache] 426 uint32_t * dreq_num_cpu; //[m_nb_dcache] 427 428 const uint32_t m_num_cache_LSB; 429 const uint32_t m_num_cache_MSB; 430 addr_40 m_num_cache_LSB_mask; 431 addr_40 m_num_cache_mask; 247 sc_signal<bool> r_tgt_icache_req; // coherence request to ICACHE 248 sc_signal<bool> r_tgt_dcache_req; // coherence request to DCACHE 249 sc_signal<data_t> * r_tgt_buf; // [m_cache_words] 250 sc_signal<be_t> * r_tgt_be; // [m_cache_words] 251 252 sc_signal<int> r_cleanup_fsm; // send cleanup commands 253 sc_signal<size_t> r_cleanup_trdid; // index for trdid 254 GenericCam<vci_addr_t> r_cleanup_buffer; // registration buffer for cleanups 255 256 // ISS interface variables (used for communication 257 // between transition() and print_trace() functions 258 bool m_ireq_valid; 259 uint32_t m_ireq_addr; 260 soclib::common::Iss2::ExecMode m_ireq_mode; 261 262 bool m_irsp_valid; 263 uint32_t m_irsp_instruction; 264 bool m_irsp_error; 265 266 bool m_dreq_valid; 267 uint32_t m_dreq_addr; 268 soclib::common::Iss2::ExecMode m_dreq_mode; 269 soclib::common::Iss2::DataOperationType m_dreq_type; 270 uint32_t m_dreq_wdata; 271 uint8_t m_dreq_be; 272 273 bool m_drsp_valid; 274 uint32_t m_drsp_rdata; 275 bool m_drsp_error; 276 277 // Activity counters (for power consumption evaluation) 278 uint32_t m_conso_dcache_data_read; // DCACHE DATA READ activity 279 uint32_t m_conso_dcache_data_write; // DCACHE DATA WRITE activity 280 uint32_t m_conso_dcache_dir_read; // DCACHE DIR READ activity 281 uint32_t m_conso_dcache_dir_write; // DCACHE DIR WRITE activity 282 283 uint32_t m_conso_icache_data_read; // ICACHE DATA READ activity 284 uint32_t m_conso_icache_data_write; // ICACHE DATA WRITE activity 285 uint32_t m_conso_icache_dir_read; // ICACHE DIR READ activity 286 uint32_t m_conso_icache_dir_write; // ICACHE DIR WRITE activity 287 288 uint32_t m_conso_wbuf_read; // WBUF READ activity 289 uint32_t m_conso_wbuf_write; // WBUF WRITE activity 290 291 uint32_t m_cpt_cc_update_icache; // number of coherence update packets for icache 292 uint32_t m_cpt_cc_update_dcache; // number of coherence update packets for dcache 293 uint32_t m_cpt_cc_inval_icache; // number of coherence inval packets for icache 294 uint32_t m_cpt_cc_inval_dcache; // number of coherence inval packets for dcache 295 uint32_t m_cpt_cc_inval_broadcast; // number of coherence broadcast packets 296 297 uint32_t m_cpt_frz_cycles; // total number of cpu frozen cycles 298 uint32_t m_cpt_total_cycles; // total number of cycles from reset 299 uint32_t m_cpt_stop_simulation; // consecutive frozen cycles counter 300 301 uint32_t m_cpt_ins_cacheable; // number of cacheable instructions 302 uint32_t m_cpt_ins_uncacheable; // number of non cacheable instructions 303 uint32_t m_cpt_ins_miss; // number of cacheable instruction miss 304 305 uint32_t m_cpt_data_read_cacheable; // number of cacheable data read 306 uint32_t m_cpt_data_read_miss; // number of cacheable data read miss 307 uint32_t m_cpt_data_read_uncacheable; // number of non cacheable data read 308 uint32_t m_cpt_data_write_cacheable; // number of cacheable write 309 uint32_t m_cpt_data_write_uncacheable; // number of non cacheable write 310 uint32_t m_cpt_data_write_hit; // number of cacheable write making hit 311 uint32_t m_cpt_data_ll; // number of LL requests 312 uint32_t m_cpt_data_sc; // number of SC requests 313 314 uint32_t m_cpt_xtn_dcache_inval; // dcache line invalidation request 315 uint32_t m_cpt_xtn_sync; // write buffer flush request 316 317 uint32_t m_cost_write_frz; // number of frozen cycles related to write buffer 318 uint32_t m_cost_data_miss_frz; // number of frozen cycles related to data miss 319 uint32_t m_cost_ins_miss_frz; // number of frozen cycles related to ins miss 320 321 uint32_t m_cpt_imiss_transaction; // number of VCI inst read miss transactions 322 uint32_t m_cpt_dmiss_transaction; // number of VCI data read miss transactions 323 uint32_t m_cpt_iunc_transaction; // number of VCI uncacheable inst read transactions 324 uint32_t m_cpt_dunc_transaction; // number of VCI uncacheable data read transactions 325 uint32_t m_cpt_write_transaction; // number of VCI write transactions 326 uint32_t m_cpt_sc_transaction; // number of VCI sc transactions 327 328 uint32_t m_cost_imiss_transaction; // cumulated duration for VCI IMISS transactions 329 uint32_t m_cost_dmiss_transaction; // cumulated duration for VCI DMISS transactions 330 uint32_t m_cost_unc_transaction; // cumulated duration for VCI UNC transactions 331 uint32_t m_cost_write_transaction; // cumulated duration for VCI WRITE transactions 332 uint32_t m_length_write_transaction; // cumulated length for VCI WRITE transactions 333 334 335 uint32_t * m_cpt_fsm_dcache; // array of number of cycles per state 336 uint32_t * m_cpt_fsm_icache; // array of number of cycles per state 337 uint32_t * m_cpt_fsm_cmd; // array of number of cycles per state 338 uint32_t * m_cpt_fsm_rsp; // array of number of cycles per state 339 uint32_t * m_cpt_fsm_tgt; // array of number of cycles per state 340 uint32_t * m_cpt_fsm_cleanup; // array of number of cycles per state 432 341 433 342 protected: … … 437 346 438 347 VciCcXCacheWrapperV4( 439 sc_module_name insname, 440 int proc_id, 441 const soclib::common::MappingTable &mtp, 442 const soclib::common::MappingTable &mtc, 443 const soclib::common::IntTab &initiator_index_rw, 444 const soclib::common::IntTab &initiator_index_c, 445 const soclib::common::IntTab &target_index, 446 size_t nb_cpu, 447 size_t nb_dcache, 448 size_t icache_ways, 449 size_t icache_sets, 450 size_t icache_words, 451 size_t dcache_ways, 452 size_t dcache_sets, 453 size_t dcache_words, 454 size_t wbuf_nwords, 455 size_t wbuf_nlines 456 ); 348 sc_module_name insname, 349 int proc_id, 350 const soclib::common::MappingTable &mtd, 351 const soclib::common::MappingTable &mtc, 352 const soclib::common::IntTab &initiator_index_d, 353 const soclib::common::IntTab &initiator_index_c, 354 const soclib::common::IntTab &target_index_c, 355 size_t icache_ways, 356 size_t icache_sets, 357 size_t icache_words, 358 size_t dcache_ways, 359 size_t dcache_sets, 360 size_t dcache_words, 361 size_t wbuf_nwords, 362 size_t wbuf_nlines, 363 uint32_t max_frozen_cycles = 1000); 457 364 458 365 ~VciCcXCacheWrapperV4(); 459 366 460 void print_trace(size_t mode = 0); 461 void print_cpi(); 462 void print_stats(bool print_wbuf=true, bool print_fsm=true); 463 464 void stop_simulation (uint32_t); 465 void log_transaction ( bool generate_file_icache 466 ,bool generate_file_dcache 467 ,bool generate_file_cmd 468 ,bool generate_file_tgt 469 ,bool generate_file_cleanup); 470 471 void vhdl_testbench (bool generate_file_mwbuf); 367 void print_trace(size_t mode = 0); 368 void print_cpi(); 369 void print_stats(bool print_wbuf=true, bool print_fsm=true); 472 370 473 371 private: … … 475 373 void transition(); 476 374 void genMoore(); 477 478 uint32_t get_num_cache (addr_40 & addr);479 uint32_t get_num_cache_only(addr_40 addr);480 void set_num_cache (addr_40 & addr, uint32_t num_cache);481 addr_40 set_num_cache_only(addr_40 addr, uint32_t num_cache);482 375 483 376 soclib_static_assert((int)iss_t::SC_ATOMIC == (int)vci_param::STORE_COND_ATOMIC); … … 487 380 }} 488 381 489 #endif /* SOCLIB_CABA_VCI_CC_ XCACHE_WRAPPER_V4_H */382 #endif /* SOCLIB_CABA_VCI_CC_VCACHE_WRAPPER_V4_H */ 490 383 491 384 // Local Variables: -
trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/src/vci_cc_xcache_wrapper_v4.cpp
r175 r188 1 1 /* -*- c++ -*- 2 * File : vci_cc_xcache_wrapper_v4.cpp 3 * Date : 26/11/2011 4 * Copyright : UPMC / LIP6 5 * Authors : Alain Greiner 2 6 * 3 7 * SOCLIB_LGPL_HEADER_BEGIN … … 21 25 * SOCLIB_LGPL_HEADER_END 22 26 * 23 * Copyright (c) UPMC, Lip6 , SoC24 * Alain Greiner <alain.greiner@lip6.fr>, 20 0827 * Copyright (c) UPMC, Lip6 28 * Alain Greiner <alain.greiner@lip6.fr>, 2011 25 29 * 26 * Maintainers: alain eric.guthmuller@polytechnique.edu nipo30 * Maintainers: alain 27 31 */ 28 32 29 /////////////////////////////////////////////////////////////////////////////30 // History31 // - 25/04/200832 // The existing vci_xcache component has been extended to include33 // a VCI target port to support a directory based coherence protocol.34 // Two types of packets can be send by the L2 cache to the L1 cache35 // * INVALIDATE packets : length = 136 // * UPDATE packets : length = n + 237 // The CLEANUP packets are sent by the L1 cache to the L2 cache,38 // to signal a replaced cache line.39 // - 12/08/200840 // The vci_cc_xcache_wrapper component instanciates directly the processsor41 // iss, in order to supress the processor/cache interface.42 // According to the VCI advanced specification, this component uses one43 // word VCI CMD packets for MISS transactions, and accept one word VCI RSP44 // packets for Write burst transactions.45 // The write buffer has been modified to use the WriteBuffer object.46 // A VCI write burst is constructed when two conditions are satisfied :47 // The processor make strictly successive write requests, and they are48 // in the same cache line. The write buffer performs re-ordering, to49 // respect the contiguous addresses VCI constraint. In case of several50 // WRITE_WORD requests in the same word, only the last request is conserved.51 // In case of several WRITE_HALF or WRITE_WORD requests in the same word,52 // the requests are merged in the same word. In case of uncached write53 // requests, each request is transmited as a single VCI transaction.54 // Both the data & instruction caches can be flushed in one single cycle.55 ///////////////////////////////////////////////////////////////////////////////56 57 #include <iomanip>58 #include "arithmetics.h"59 #include "size.h"60 33 #include "../include/vci_cc_xcache_wrapper_v4.h" 61 namespace soclib { 62 namespace caba { 34 35 #define DEBUG_GLOBAL 0 36 #define DEBUG_DCACHE 0 37 #define DEBUG_ICACHE 0 38 39 #define DEBUG_START_CYCLE 0 40 #define DEBUG_ID 0 41 42 namespace soclib { namespace caba { 43 63 44 namespace { 64 65 // =====[ DEBUG ]==================================== 66 67 #define ASSERT_VERBOSE 68 #define ASSERT_NCYCLES m_cpt_total_cycles 69 70 #include "debug.h" 71 72 #if CC_XCACHE_WRAPPER_DEBUG 73 # define PRINTF(msg...) PRINTF_COND(m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN,msg) 74 #else 75 # define PRINTF(msg...) 76 #endif 77 78 ///////////////////////////////////////////////////////////////////// 79 // Management of address stocked in icache/dcache/mwbuf in case 80 // of multiple bank implementation 81 ///////////////////////////////////////////////////////////////////// 82 83 // =====[ MULTI_CACHE ]============================== 84 85 #if (CC_XCACHE_WRAPPER_MULTI_CACHE==1) 86 # define get_num_icache( addr,num_cpu) get_num_cache (addr) 87 # define get_num_icache_only(addr,num_cpu) get_num_cache_only(addr) 88 # define set_num_icache( addr,num_cache) set_num_cache (addr,num_cache) 89 # define set_num_icache_only(addr,num_cache) set_num_cache_only(addr,num_cache) 90 #elif (CC_XCACHE_WRAPPER_MULTI_CACHE==2) 91 # define get_num_icache( addr,num_cpu) num_cpu 92 # define get_num_icache_only(addr,num_cpu) num_cpu 93 # define set_num_icache( addr,num_cache) do {} while (0) 94 # define set_num_icache_only(addr,num_cache) addr 95 #else 96 #error "Invalid value to CC_XCACHE_WRAPPER_MULTI_CACHE" 97 #endif 98 # define get_num_dcache( addr) get_num_cache (addr) 99 # define get_num_dcache_only(addr) get_num_cache_only(addr) 100 # define set_num_dcache( addr,num_cache) set_num_cache (addr,num_cache) 101 # define set_num_dcache_only(addr,num_cache) set_num_cache_only(addr,num_cache) 102 103 const char *dcache_fsm_state_str[] = { 45 const char *dcache_fsm_state_str[] = 46 { 104 47 "DCACHE_IDLE", 105 48 "DCACHE_WRITE_UPDT", … … 108 51 "DCACHE_MISS_UPDT", 109 52 "DCACHE_UNC_WAIT", 110 "DCACHE_SC_WAIT",111 53 "DCACHE_INVAL", 54 "DCACHE_INVAL_GO", 112 55 "DCACHE_SYNC", 113 56 "DCACHE_ERROR", 114 57 "DCACHE_CC_CHECK", 115 58 "DCACHE_CC_INVAL", 116 "DCACHE_CC_ CLEANUP",59 "DCACHE_CC_UPDT", 117 60 }; 118 const char *icache_fsm_state_str[] = { 61 const char *icache_fsm_state_str[] = 62 { 119 63 "ICACHE_IDLE", 120 64 "ICACHE_MISS_VICTIM", … … 123 67 "ICACHE_UNC_WAIT", 124 68 "ICACHE_ERROR", 125 "ICACHE_CC_CLEANUP",126 69 "ICACHE_CC_CHECK", 127 70 "ICACHE_CC_INVAL", 71 "ICACHE_CC_UPDT", 128 72 }; 129 const char *cmd_fsm_state_str[] = { 73 const char *cmd_fsm_state_str[] = 74 { 130 75 "CMD_IDLE", 131 76 "CMD_INS_MISS", … … 136 81 "CMD_DATA_SC", 137 82 }; 138 const char *rsp_fsm_state_str[] = { 83 const char *rsp_fsm_state_str[] = 84 { 139 85 "RSP_IDLE", 140 86 "RSP_INS_MISS", … … 145 91 "RSP_DATA_SC", 146 92 }; 147 const char *tgt_fsm_state_str[] = { 93 const char *tgt_fsm_state_str[] = 94 { 148 95 "TGT_IDLE", 149 96 "TGT_UPDT_WORD", … … 157 104 }; 158 105 159 const char *cleanup_fsm_state_str[] = { 160 "CLEANUP_IDLE", 161 "CLEANUP_REQ", 162 "CLEANUP_RSP_DCACHE", 163 "CLEANUP_RSP_ICACHE", 106 const char *cleanup_fsm_state_str[] = 107 { 108 "CLEANUP_DATA_IDLE", 109 "CLEANUP_DATA_GO", 110 "CLEANUP_INS_IDLE", 111 "CLEANUP_INS_GO", 164 112 }; 165 113 } 166 114 167 typedef long long unsigned int blob_t; 168 169 #define tmpl(...) template<typename vci_param, typename iss_t> __VA_ARGS__ VciCcXCacheWrapperV4<vci_param, iss_t> 170 171 using soclib::common::uint32_log2; 172 173 ///////////////////////////////// 174 tmpl(/**/)::VciCcXCacheWrapperV4( 175 ///////////////////////////////// 176 sc_module_name name, 177 int proc_id, 178 const soclib::common::MappingTable &mtp, 179 const soclib::common::MappingTable &mtc, 180 const soclib::common::IntTab &initiator_index_rw, 181 const soclib::common::IntTab &initiator_index_c, 182 const soclib::common::IntTab &target_index, 183 size_t nb_cpu, 184 size_t nb_dcache, 185 size_t icache_ways, 186 size_t icache_sets, 187 size_t icache_words, 188 size_t dcache_ways, 189 size_t dcache_sets, 190 size_t dcache_words, 191 size_t wbuf_nwords, 192 size_t wbuf_nlines 193 ) 194 : 195 soclib::caba::BaseModule(name), 196 197 p_clk ("clk"), 198 p_resetn ("resetn"), 199 p_vci_ini_rw("vci_ini_rw"), 200 p_vci_ini_c ("vci_ini_c"), 201 p_vci_tgt ("vci_tgt"), 202 203 m_cacheability_table(mtp.getCacheabilityTable<vci_addr_t>()), 204 m_segment(mtc.getSegment(target_index)), 205 m_srcid_rw(mtp.indexForId(initiator_index_rw)), 206 m_srcid_c(mtc.indexForId(initiator_index_c)), 207 208 m_nb_cpu(nb_cpu), 209 #if (CC_XCACHE_WRAPPER_MULTI_CACHE==1) 210 m_nb_icache(nb_dcache), 211 #elif (CC_XCACHE_WRAPPER_MULTI_CACHE==2) 212 m_nb_icache(m_nb_cpu), 115 #define tmpl(...) template<typename vci_param, typename iss_t> __VA_ARGS__ VciCcXCacheWrapperV4<vci_param, iss_t> 116 117 using soclib::common::uint32_log2; 118 119 ///////////////////////////////// 120 tmpl(/**/)::VciCcXCacheWrapperV4( 121 sc_module_name name, 122 int proc_id, 123 const soclib::common::MappingTable &mtp, 124 const soclib::common::MappingTable &mtc, 125 const soclib::common::IntTab &initiator_index_d, 126 const soclib::common::IntTab &initiator_index_c, 127 const soclib::common::IntTab &target_index_c, 128 size_t icache_ways, 129 size_t icache_sets, 130 size_t icache_words, 131 size_t dcache_ways, 132 size_t dcache_sets, 133 size_t dcache_words, 134 size_t wbuf_nwords, 135 size_t wbuf_nlines, 136 uint32_t max_frozen_cycles) 137 : 138 soclib::caba::BaseModule(name), 139 140 p_clk ("clk"), 141 p_resetn ("resetn"), 142 p_vci_ini_d ("vci_ini_d"), 143 p_vci_ini_c ("vci_ini_c"), 144 p_vci_tgt_c ("vci_tgt_c"), 145 146 m_cacheability_table(mtp.getCacheabilityTable<vci_addr_t>()), 147 m_segment(mtc.getSegment(target_index_c)), 148 m_srcid_d(mtp.indexForId(initiator_index_d)), 149 m_srcid_c(mtc.indexForId(initiator_index_c)), 150 151 m_dcache_ways(dcache_ways), 152 m_icache_ways(icache_ways), 153 154 m_cache_words(icache_words), 155 m_cache_words_shift(uint32_log2(icache_words)+uint32_log2(sizeof(data_t))), 156 m_cache_yzmask((~0)<<m_cache_words_shift), 157 158 m_max_frozen_cycles(max_frozen_cycles), 159 160 r_icache_fsm("r_icache_fsm"), 161 r_icache_fsm_save("r_icache_fsm_save"), 162 r_icache_addr_save("r_icache_addr_save"), 163 r_icache_miss_req("r_icache_miss_req"), 164 r_icache_unc_req("r_icache_unc_req"), 165 r_icache_cleanup_req("r_icache_cleanup_req"), 166 r_icache_cleanup_line("r_icache_cleanup_line"), 167 r_icache_cleanup_way("r_icache_cleanup_way"), 168 r_icache_cleanup_set("r_icache_cleanup_set"), 169 r_icache_miss_inval("r_icache_miss_inval"), 170 r_icache_update_word("r_icache_update_word"), 171 172 r_dcache_fsm("r_dcache_fsm"), 173 r_dcache_fsm_save("r_dcache_fsm_save"), 174 r_dcache_addr_save("r_dcache_addr_save"), 175 r_dcache_wdata_save("r_dcache_wdata_save"), 176 r_dcache_be_save("r_dcache_be_save"), 177 r_dcache_way_save("r_dcache_way_save"), 178 r_dcache_set_save("r_dcache_set_save"), 179 r_dcache_word_save("r_dcache_word_save"), 180 r_dcache_cleanup_req("r_dcache_cleanup_req"), 181 r_dcache_cleanup_line("r_dcache_cleanup_line"), 182 r_dcache_cleanup_way("r_dcache_cleanup_way"), 183 r_dcache_cleanup_set("r_dcache_cleanup_set"), 184 r_dcache_miss_req("r_dcache_miss_req"), 185 r_dcache_unc_req("r_dcache_unc_req"), 186 r_dcache_sc_req("r_dcache_sc_req"), 187 r_dcache_miss_inval("r_dcache_miss_inval"), 188 r_dcache_update_word("r_dcache_update_word"), 189 r_dcache_ll_data("r_dcache_ll_data"), 190 r_dcache_ll_addr("r_dcache_ll_addr"), 191 r_dcache_ll_valid("r_dcache_ll_valid"), 192 193 r_vci_cmd_fsm("r_vci_cmd_fsm"), 194 r_vci_cmd_min("r_vci_cmd_min"), 195 r_vci_cmd_max("r_vci_cmd_max"), 196 r_vci_cmd_cpt("r_vci_cmd_cpt"), 197 r_vci_cmd_imiss_prio("r_vci_cmd_imiss_prio"), 198 199 r_vci_rsp_fsm("r_vci_rsp_fsm"), 200 r_vci_rsp_cpt("r_vci_rsp_cpt"), 201 r_vci_rsp_ins_error("r_vci_rsp_ins_error"), 202 r_vci_rsp_data_error("r_vci_rsp_data_error"), 203 r_vci_rsp_fifo_icache("r_vci_rsp_fifo_icache" ,2), // two words depth 204 r_vci_rsp_fifo_dcache("r_vci_rsp_fifo_dcache" ,2), // two words depth 205 206 r_tgt_fsm("r_tgt_fsm"), 207 r_tgt_icache_rsp("r_tgt_icache_rsp"), 208 r_tgt_dcache_rsp("r_tgt_dcache_rsp"), 209 r_tgt_addr("r_tgt_daddr"), 210 r_tgt_word_min("r_tgt_word_min"), 211 r_tgt_word_max("r_tgt_word_max"), 212 r_tgt_word_count("r_tgt_word_count"), 213 r_tgt_update("r_tgt_update"), 214 r_tgt_update_data("r_tgt_update_data"), 215 r_tgt_srcid("r_tgt_srcid"), 216 r_tgt_pktid("r_tgt_pktid"), 217 r_tgt_trdid("r_tgt_trdid"), 218 r_tgt_icache_req("r_tgt_icache_req"), 219 r_tgt_dcache_req("r_tgt_dcache_req"), 220 221 r_cleanup_fsm("r_cleanup_fsm"), 222 r_cleanup_trdid("r_cleanup_trdid"), 223 r_cleanup_buffer(16) // up to 16 simultaneous cleanup transactions 224 { 225 assert( ((icache_words*vci_param::B) < (1<<vci_param::K)) and 226 "Need more PLEN bits."); 227 228 assert( (vci_param::T > 2) and ((1<<(vci_param::T-1)) >= (wbuf_nlines)) and 229 "Need more TRDID bits."); 230 231 assert( (icache_words == dcache_words) and 232 "icache_words must be equal at dcache_words."); 233 234 p_irq = new sc_in<bool> [iss_t::n_irq]; 235 236 r_iss = new iss_t (this->name() , proc_id); 237 r_icache = new GenericCache<vci_addr_t>("icache", icache_ways, icache_sets, icache_words); 238 r_dcache = new GenericCache<vci_addr_t>("dcache", dcache_ways, dcache_sets, dcache_words); 239 r_wbuf = new MultiWriteBuffer<vci_addr_t>("wbuf", wbuf_nwords, wbuf_nlines, dcache_words); 240 241 r_tgt_buf = new sc_signal<data_t> [m_cache_words]; 242 r_tgt_be = new sc_signal<be_t> [m_cache_words]; 243 244 m_cpt_fsm_dcache = new uint32_t [32]; 245 m_cpt_fsm_icache = new uint32_t [32]; 246 m_cpt_fsm_cmd = new uint32_t [32]; 247 m_cpt_fsm_rsp = new uint32_t [32]; 248 m_cpt_fsm_tgt = new uint32_t [32]; 249 m_cpt_fsm_cleanup = new uint32_t [32]; 250 251 SC_METHOD(transition); 252 dont_initialize(); 253 sensitive << p_clk.pos(); 254 255 SC_METHOD(genMoore); 256 dont_initialize(); 257 sensitive << p_clk.neg(); 258 259 typename iss_t::CacheInfo cache_info; 260 cache_info.has_mmu = false; 261 cache_info.icache_line_size = icache_words*sizeof(data_t); 262 cache_info.icache_assoc = icache_ways; 263 cache_info.icache_n_lines = icache_sets; 264 cache_info.dcache_line_size = dcache_words*sizeof(data_t); 265 cache_info.dcache_assoc = dcache_ways; 266 cache_info.dcache_n_lines = dcache_sets; 267 268 r_iss->setCacheInfo(cache_info); 269 270 } // end constructor 271 272 /////////////////////////////////// 273 tmpl(/**/)::~VciCcXCacheWrapperV4() 274 { 275 delete r_icache ; 276 delete r_wbuf ; 277 delete r_dcache ; 278 delete r_iss; 279 delete [] p_irq; 280 delete [] r_tgt_buf; 281 delete [] r_tgt_be; 282 } 283 284 //////////////////////// 285 tmpl(void)::print_cpi() 286 { 287 std::cout << "CPU " << m_srcid_d << " : CPI = " 288 << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles) 289 << std::endl ; 290 } 291 292 /* 293 294 //////////////////////////////////////////////////////// 295 tmpl(void)::print_stats(bool print_wbuf, bool print_fsm) 296 { 297 std::cout << "------------------------------------" << std:: dec << std::endl; 298 std::cout << "CPU " << m_srcid_d << " / Time = " << m_cpt_total_cycles << std::endl; 299 300 float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles); 301 302 std::cout << "- CPI : " 303 << (float)m_cpt_total_cycles/run_cycles << std::endl ; 304 305 std::cout << "- CACHABLE INSTRUCTIONS : " 306 << m_cpt_ins_cacheable << std::endl ; 307 308 std::cout << "- INSTRUCTION CACHE MISS RATE : " 309 << (float)m_cpt_ins_miss*100.0/(float)m_cpt_ins_cacheable 310 << " %" << std::endl ; 311 312 std::cout << "- NON CACHABLE INSTRUCTIONS : " 313 << m_cpt_ins_uncacheable << std::endl ; 314 315 std::cout << "- CACHABLE DATA READ : " 316 << m_cpt_data_read_cacheable << std::endl; 317 318 std::cout << "- DATA CACHE MISS RATE : " 319 << (float)m_cpt_data_read_miss*100.0/(float)m_cpt_data_read_cacheable 320 << " %" << std::endl; 321 322 std::cout << "- CACHABLE DATA WRITE : " 323 << m_cpt_data_write_cacheable << std::endl ; 324 325 std::cout << "- CACHED WRITE RATE : " 326 << (float)m_cpt_data_write_hit*100.0/(float)m_cpt_data_write_cacheable 327 << " %" << std::endl; 328 329 std::cout << "- NON CACHABLE DATA READ : " 330 << m_cpt_data_read_uncacheable << std::endl; 331 332 std::cout << "- NON CACHABLE DATA WRITE : " 333 << m_cpt_data_write_uncacheable << std::endl; 334 335 std::cout << "- WRITE RATE : " 336 << (float)m_cpt_data_write_cacheable*100.0/(float)m_cpt_ins_cacheable 337 << " %" << std::endl; 338 339 std::cout << "- READ RATE : " 340 << (float)m_cpt_data_read_cacheable*100.0/(float)m_cpt_ins_cacheable 341 << " %" << std::endl; 342 343 std::cout << "- AVERAGE INSTRUCTION MISS COST : " 344 << (float)m_cost_ins_miss_frz/(float)m_cpt_ins_miss << std::endl; 345 346 std::cout << "- AVERAGE DATA MISS COST : " 347 << (float)m_cost_data_miss_frz/m_cpt_data_read_miss << std::endl; 348 349 std::cout << "- AVERAGE WRITE COST : " 350 << (float)m_cost_write_frz/m_cpt_data_write_cacheable << std::endl; 351 352 std::cout << "- CC_UPDATE_ICACHE : " 353 << m_cpt_cc_update_icache << std::endl; 354 355 std::cout << "- CC_UPDATE_DCACHE : " 356 << m_cpt_cc_update_dcache << std::endl; 357 358 std::cout << "- CC_INVAL_ICACHE : " 359 << m_cpt_cc_inval_icache << std::endl; 360 361 std::cout << "- CC_INVAL_ICACHE : " 362 << m_cpt_cc_inval_icache << std::endl; 363 364 std::cout << "-CC_BROADCAST : " 365 << m_cpt_cc_inval_broadcast << std::endl; 366 367 // this part is removed because soclib::common::size() not found ... 368 369 if (print_fsm) 370 { 371 std::cout << "- DCACHE FSM" << std::endl; 372 for (uint32_t i=0; i<soclib::common::size(dcache_fsm_state_str ); ++i) 373 std::cout << " + " << dcache_fsm_state_str[i] << " : " 374 << m_cpt_fsm_dcache [i] << std::endl; 375 376 std::cout << "- ICACHE FSM" << std::endl; 377 for (uint32_t i=0; i<soclib::common::size(icache_fsm_state_str ); ++i) 378 std::cout << " + " << icache_fsm_state_str[i] << " : " 379 << m_cpt_fsm_icache [i] << std::endl; 380 381 std::cout << "- CMD FSM" << std::endl; 382 for (uint32_t i=0; i<soclib::common::size(cmd_fsm_state_str ); ++i) 383 std::cout << " + " << cmd_fsm_state_str[i] << " : " 384 << m_cpt_fsm_cmd [i] << std::endl; 385 386 std::cout << "- RSP FSM" << std::endl; 387 for (uint32_t i=0; i<soclib::common::size(rsp_fsm_state_str ); ++i) 388 std::cout << " + " << rsp_fsm_state_str[i] << " : " 389 << m_cpt_fsm_rsp [i] << std::endl; 390 391 std::cout << "- TGT FSM" << std::endl; 392 for (uint32_t i=0; i<soclib::common::size(tgt_fsm_state_str ); ++i) 393 std::cout << " + " << tgt_fsm_state_str[i] << " : " 394 << m_cpt_fsm_tgt [i] << std::endl; 395 396 std::cout << "- CLEANUP FSM" << std::endl; 397 for (uint32_t i=0; i<soclib::common::size(cleanup_fsm_state_str ); ++i) 398 std::cout << " + " << cleanup_fsm_state_str[i] << " : " 399 << m_cpt_fsm_cleanup [i] << std::endl; 400 } 401 402 if (print_wbuf) r_wbuf->printStatistics(); 403 } 404 405 */ 406 //////////////////////////////////// 407 tmpl(void)::print_trace(size_t mode) 408 { 409 // b0 : write buffer print trace 410 // b1 : write buffer verbose 411 // b2 : dcache print trace 412 // b3 : icache print trace 413 414 typename iss_t::InstructionRequest ireq; 415 typename iss_t::InstructionResponse irsp; 416 typename iss_t::DataRequest dreq; 417 typename iss_t::DataResponse drsp; 418 419 ireq.valid = m_ireq_valid; 420 ireq.addr = m_ireq_addr; 421 ireq.mode = m_ireq_mode; 422 423 irsp.valid = m_irsp_valid; 424 irsp.instruction = m_irsp_instruction; 425 irsp.error = m_irsp_error; 426 427 dreq.valid = m_dreq_valid; 428 dreq.addr = m_dreq_addr; 429 dreq.mode = m_dreq_mode; 430 dreq.type = m_dreq_type; 431 dreq.wdata = m_dreq_wdata; 432 dreq.be = m_dreq_be; 433 434 drsp.valid = m_drsp_valid; 435 drsp.rdata = m_drsp_rdata; 436 drsp.error = m_drsp_error; 437 438 std::cout << std::dec << "Proc " << name() << std::endl; 439 440 std::cout << " " << ireq << std::endl; 441 std::cout << " " << irsp << std::endl; 442 std::cout << " " << dreq << std::endl; 443 std::cout << " " << drsp << std::endl; 444 445 std::cout << " " << icache_fsm_state_str[r_icache_fsm.read()] 446 << " | " << dcache_fsm_state_str[r_dcache_fsm.read()] 447 << " | " << cmd_fsm_state_str[r_vci_cmd_fsm.read()] 448 << " | " << rsp_fsm_state_str[r_vci_rsp_fsm.read()] 449 << " | " << tgt_fsm_state_str[r_tgt_fsm.read()] 450 << " | " << cleanup_fsm_state_str[r_cleanup_fsm.read()] << std::endl; 451 452 if(mode & 0x1) 453 { 454 std::cout << " Write Buffer" << std::endl; 455 r_wbuf->printTrace((mode>>1)&1); 456 } 457 if(mode & 0x4) 458 { 459 std::cout << " Data cache" << std::endl; 460 r_dcache->printTrace(); 461 } 462 if(mode & 0x8) 463 { 464 std::cout << " Instruction cache" << std::endl; 465 r_icache->printTrace(); 466 } 467 } 468 469 ////////////////////////// 470 tmpl(void)::transition() 471 ////////////////////////// 472 { 473 // Reset 474 if ( not p_resetn.read() ) 475 { 476 // iss, write buffer & caches 477 r_iss->reset(); 478 r_wbuf->reset(); 479 r_dcache->reset(); 480 r_icache->reset(); 481 r_cleanup_buffer.reset(); 482 483 // FSM states 484 r_icache_fsm = ICACHE_IDLE; 485 r_dcache_fsm = DCACHE_IDLE; 486 r_vci_cmd_fsm = CMD_IDLE; 487 r_vci_rsp_fsm = RSP_IDLE; 488 r_tgt_fsm = TGT_IDLE; 489 r_cleanup_fsm = CLEANUP_DATA_IDLE; 490 491 // synchronisation flip-flops between TGT FSM and ICACHE/DCACHE FSMs 492 r_tgt_icache_req = false; 493 r_tgt_dcache_req = false; 494 495 // synchronisation flip-flops between ICACHE/DCACHE FSMs and CLEANUP FSM 496 r_icache_cleanup_req = false; 497 r_dcache_cleanup_req = false; 498 499 // synchronisation flip-flops between ICACHE FSMs and VCI FSMs 500 r_icache_miss_req = false; 501 r_icache_unc_req = false; 502 r_icache_miss_inval = false; 503 r_vci_rsp_ins_error = false; 504 505 // synchronisation flip-flops between DCACHE FSMs and VCI FSMs 506 r_dcache_miss_req = false; 507 r_dcache_unc_req = false; 508 r_dcache_sc_req = false; 509 r_dcache_miss_inval = false; 510 r_vci_rsp_data_error = false; 511 512 // pending non cacheable write 513 r_dcache_pending_unc_write = false; 514 515 // linked load reservation flip-flop 516 r_dcache_ll_valid = false; 517 518 // uncacheable read buffers 519 r_icache_unc_valid = false; 520 r_dcache_unc_valid = false; 521 522 // response FIFOs 523 r_vci_rsp_fifo_icache.init(); 524 r_vci_rsp_fifo_dcache.init(); 525 526 // activity counters (consommation) 527 m_conso_dcache_data_read = 0; 528 m_conso_dcache_data_write = 0; 529 m_conso_dcache_dir_read = 0; 530 m_conso_dcache_dir_write = 0; 531 532 m_conso_icache_data_read = 0; 533 m_conso_icache_data_write = 0; 534 m_conso_icache_dir_read = 0; 535 m_conso_icache_dir_write = 0; 536 537 m_conso_wbuf_read = 0; 538 m_conso_wbuf_write = 0; 539 540 // coherence request counters 541 m_cpt_cc_update_icache = 0; 542 m_cpt_cc_update_dcache = 0; 543 m_cpt_cc_inval_icache = 0; 544 m_cpt_cc_inval_dcache = 0; 545 m_cpt_cc_inval_broadcast = 0; 546 547 // CPI computation 548 m_cpt_frz_cycles = 0; 549 m_cpt_total_cycles = 0; 550 m_cpt_stop_simulation = 0; 551 552 // number of executed instructions 553 m_cpt_ins_cacheable = 0; 554 m_cpt_ins_uncacheable = 0; 555 m_cpt_ins_miss = 0; 556 557 // number of data requests 558 m_cpt_data_read_cacheable = 0; 559 m_cpt_data_read_miss = 0; 560 m_cpt_data_read_uncacheable = 0; 561 m_cpt_data_write_cacheable = 0; 562 m_cpt_data_write_uncacheable = 0; 563 m_cpt_data_write_hit = 0; 564 m_cpt_data_ll = 0; 565 m_cpt_data_sc = 0; 566 567 // number of external register requests 568 m_cpt_xtn_dcache_inval = 0; 569 m_cpt_xtn_sync = 0; 570 571 // cumulated cost (frozen cycles) for write and miss 572 m_cost_write_frz = 0; 573 m_cost_data_miss_frz = 0; 574 m_cost_ins_miss_frz = 0; 575 576 m_cpt_imiss_transaction = 0; 577 m_cpt_dmiss_transaction = 0; 578 m_cpt_iunc_transaction = 0; 579 m_cpt_dunc_transaction = 0; 580 m_cpt_write_transaction = 0; 581 m_cpt_sc_transaction = 0; 582 583 m_cost_imiss_transaction = 0; 584 m_cost_dmiss_transaction = 0; 585 m_cost_unc_transaction = 0; 586 m_cost_write_transaction = 0; 587 m_length_write_transaction = 0; 588 589 for (uint32_t i=0; i<32 ; ++i) 590 m_cpt_fsm_icache [i] = 0; 591 for (uint32_t i=0; i<32 ; ++i) 592 m_cpt_fsm_dcache [i] = 0; 593 for (uint32_t i=0; i<32 ; ++i) 594 m_cpt_fsm_cmd [i] = 0; 595 for (uint32_t i=0; i<32 ; ++i) 596 m_cpt_fsm_rsp [i] = 0; 597 for (uint32_t i=0; i<32 ; ++i) 598 m_cpt_fsm_tgt [i] = 0; 599 for (uint32_t i=0; i<32 ; ++i) 600 m_cpt_fsm_cleanup [i] = 0; 601 602 return; 603 } 604 605 // Response FIFOs default values 606 bool vci_rsp_fifo_icache_get = false; 607 bool vci_rsp_fifo_icache_put = false; 608 data_t vci_rsp_fifo_icache_data = 0; 609 610 bool vci_rsp_fifo_dcache_get = false; 611 bool vci_rsp_fifo_dcache_put = false; 612 data_t vci_rsp_fifo_dcache_data = 0; 613 614 // FSMs activity 615 m_cpt_fsm_dcache [r_dcache_fsm.read() ] ++; 616 m_cpt_fsm_icache [r_icache_fsm.read() ] ++; 617 m_cpt_fsm_cmd [r_vci_cmd_fsm.read()] ++; 618 m_cpt_fsm_rsp [r_vci_rsp_fsm.read()] ++; 619 m_cpt_fsm_tgt [r_tgt_fsm.read() ] ++; 620 m_cpt_fsm_cleanup [r_cleanup_fsm.read()] ++; 621 622 m_cpt_total_cycles++; 623 624 ////////////////////////////////////////////////////////////////////////////// 625 // The TGT_FSM receives the coherence requests. 626 // It controls the following ressources: 627 // - r_tgt_fsm 628 // - r_tgt_buf[nwords] 629 // - r_tgt_be[nwords] 630 // - r_tgt_update 631 // - r_tgt_word_min 632 // - r_tgt_word_max 633 // - r_tgt_word_count 634 // - r_tgt_addr 635 // - r_tgt_srcid 636 // - r_tgt_trdid 637 // - r_tgt_pktid 638 // - r_tgt_icache_req (set) 639 // - r_tgt_dcache_req (set) 640 // 641 // All VCI commands must be CMD_WRITE. 642 // - If the 2 LSB bits of the VCI address are 11, it is a broadcast request. 643 // It is a multicast request otherwise. 644 // - For multicast requests, the ADDRESS[2] bit distinguishes DATA/INS 645 // (0 for data / 1 for instruction), and the ADDRESS[3] bit distinguishes 646 // INVAL/UPDATE (0 for invalidate / 1 for UPDATE). 647 // 648 // For all types of coherence resqests, the line index (i.e. the Z & Y fields) 649 // is coded on 34 bits, and is contained in the WDATA and BE fields 650 // of the first VCI flit. 651 // - for a multicast invalidate or for a broadcast invalidate request 652 // the VCI packet length is 1 word. 653 // - for an update request the VCI packet length is (n+2) words. 654 // The WDATA field of the second VCI word contains the word index. 655 // The WDATA field of the n following words contains the values. 656 // - for all transaction types, the VCI response is one single word. 657 // In case of errors in the VCI command packet, the simulation 658 // is stopped with an error message. 659 // 660 // This FSM is NOT pipelined : It consumes a new request on the VCI port 661 // only when the previous request is completed. 662 // 663 // The VCI_TGT FSM stores the external request arguments in the 664 // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req 665 // and/or the r_tgt_dcache_req flip-flops to signal the coherence request 666 // to the ICACHE & DCACHE FSMs in the REQ_ICACHE, REQ_DCACHE & REQ_BROADCAST 667 // states. It waits the completion of the coherence request by polling the 668 // r_tgt_*cache_req flip-flops in the RSP_ICACHE, RSP_DCACHE & RSP_BROADCAST 669 // states. These flip-flops are reset by the ICACHE_FSM and/or DCACHE_FSM. 670 // These two FSMs signal if a VCI answer must be send by setting 671 // the r_tgt_icache_rsp and/or the r_tgt_dcache_rsp flip_flops. 672 /////////////////////////////////////////////////////////////////////////////// 673 674 switch( r_tgt_fsm.read() ) 675 { 676 ////////////// 677 case TGT_IDLE: 678 { 679 vci_addr_t tgt_addr; 680 681 if ( p_vci_tgt_c.cmdval.read() ) 682 { 683 vci_addr_t address = p_vci_tgt_c.address.read(); 684 685 if ( p_vci_tgt_c.cmd.read() != vci_param::CMD_WRITE) 686 { 687 std::cout << "error in component VCI_CC_XCACHE_WRAPPER " 688 << name() << std::endl; 689 std::cout << "coherence request is not a write" 690 << std::endl; 691 exit(0); 692 } 693 694 // address checking for multi-update or multi-invalidate 695 if ( ((address&0x3) != 0x3) and (not m_segment.contains(address)) ) 696 { 697 std::cout << "error in component VCI_CC_XCACHE_WRAPPER " 698 << name() << std::endl; 699 std::cout << "out of segment coherence request" 700 << std::endl; 701 exit(0); 702 } 703 704 // address of the target cache line = nline * m_cache_words * 4 705 tgt_addr = (vci_addr_t)(((((uint64_t)p_vci_tgt_c.be.read() & 0x3) << 32) | 706 (uint64_t)p_vci_tgt_c.wdata.read() ) << m_cache_words_shift); 707 708 r_tgt_srcid = p_vci_tgt_c.srcid.read(); 709 r_tgt_trdid = p_vci_tgt_c.trdid.read(); 710 r_tgt_pktid = p_vci_tgt_c.pktid.read(); 711 r_tgt_addr = tgt_addr; // target line (for *CACHE FSMs) 712 713 if ( (address&0x3) == 0x3 ) // broadcast invalidate 714 { 715 if ( not p_vci_tgt_c.eop.read() ) 716 { 717 std::cout << "error in component VCI_CC_XCACHE_WRAPPER " 718 << name() << std::endl; 719 std::cout << "the BROADCAST INVALIDATE command length must be one word" 720 << std::endl; 721 exit(0); 722 } 723 r_tgt_update = false; 724 r_tgt_fsm = TGT_REQ_BROADCAST; 725 726 m_cpt_cc_inval_broadcast++ ; 727 } 728 else // multi-update or multi-invalidate 729 { 730 uint32_t cell = address - m_segment.baseAddress(); 731 if (cell == 0) // invalidate data 732 { 733 if ( not p_vci_tgt_c.eop.read() ) 734 { 735 std::cout << "error in component VCI_CC_XCACHE_WRAPPER " 736 << name() << std::endl; 737 std::cout << "the MULTI-INVALIDATE command length must be one word" 738 << std::endl; 739 exit(0); 740 } 741 r_tgt_update = false; 742 r_tgt_fsm = TGT_REQ_DCACHE; 743 744 m_cpt_cc_inval_dcache++ ; 745 } 746 else if (cell == 4) // invalidate instruction 747 { 748 if ( not p_vci_tgt_c.eop.read() ) 749 { 750 std::cout << "error in component VCI_CC_VCACHE_WRAPPER " 751 << name() << std::endl; 752 std::cout << "the MULTI-INVALIDATE command length must be one word" 753 << std::endl; 754 exit(0); 755 } 756 r_tgt_update = false; 757 r_tgt_fsm = TGT_REQ_ICACHE; 758 759 m_cpt_cc_inval_icache++ ; 760 } 761 else if (cell == 8) // update data 762 { 763 if ( p_vci_tgt_c.eop.read() ) 764 { 765 std::cout << "error in component VCI_CC_VCACHE_WRAPPER " 766 << name() << std::endl; 767 std::cout << "the MULTI-UPDATE command length must be N+2 words" 768 << std::endl; 769 exit(0); 770 } 771 r_tgt_update = true; 772 r_tgt_update_data = true; 773 r_tgt_fsm = TGT_UPDT_WORD; 774 775 m_cpt_cc_update_dcache++; 776 } 777 else // update instruction 778 { 779 780 781 if ( p_vci_tgt_c.eop.read() ) 782 { 783 std::cout << "error in component VCI_CC_VCACHE_WRAPPER " 784 << name() << std::endl; 785 std::cout << "the MULTI-UPDATE command length must be N+2 words" 786 << std::endl; 787 exit(0); 788 } 789 r_tgt_update = true; 790 r_tgt_update_data = false; 791 r_tgt_fsm = TGT_UPDT_WORD; 792 793 m_cpt_cc_update_icache++; 794 } 795 } // end if multi 796 } // end if cmdval 797 break; 798 } 799 ////////////////// 800 case TGT_UPDT_WORD: // first word index acquisition fo update requests 801 802 { 803 if (p_vci_tgt_c.cmdval.read()) 804 { 805 if ( p_vci_tgt_c.eop.read() ) 806 { 807 std::cout << "error in component VCI_CC_XCACHE_WRAPPER " 808 << name() << std::endl; 809 std::cout << "the MULTI-UPDATE command length must be N+2 words" 810 << std::endl; 811 exit(0); 812 } 813 814 for ( size_t i=0 ; i<m_cache_words ; i++ ) r_tgt_be[i] = 0; 815 816 r_tgt_word_min = p_vci_tgt_c.wdata.read(); // first modified word 817 r_tgt_word_count = p_vci_tgt_c.wdata.read(); // initializes the word counter 818 r_tgt_fsm = TGT_UPDT_DATA; 819 } 820 break; 821 } 822 /////////////////// 823 case TGT_UPDT_DATA: // data acquisition for update requests 824 { 825 if (p_vci_tgt_c.cmdval.read()) 826 { 827 size_t word = r_tgt_word_count.read(); 828 if ( word >= m_cache_words ) 829 { 830 std::cout << "error in component VCI_CC_XCACHE_WRAPPER " 831 << name() << std::endl; 832 std::cout << "the reveived MULTI-UPDATE command length is wrong" 833 << std::endl; 834 exit(0); 835 } 836 837 r_tgt_buf[word] = p_vci_tgt_c.wdata.read(); 838 r_tgt_be [word] = p_vci_tgt_c.be.read(); 839 840 r_tgt_word_count = word + 1; 841 if (p_vci_tgt_c.eop.read()) // last word 842 { 843 r_tgt_word_max = word; // last modified word 844 if(r_tgt_update_data.read()) r_tgt_fsm = TGT_REQ_DCACHE; 845 else r_tgt_fsm = TGT_REQ_ICACHE; 846 } 847 } 848 break; 849 } 850 /////////////////////// 851 case TGT_REQ_BROADCAST: // set the requests (if no previous request pending) 852 { 853 if (not r_tgt_icache_req.read() and not r_tgt_dcache_req.read()) 854 { 855 r_tgt_fsm = TGT_RSP_BROADCAST; 856 r_tgt_icache_req = true; 857 r_tgt_dcache_req = true; 858 } 859 break; 860 } 861 //////////////////// 862 case TGT_REQ_ICACHE: // set the request (if no previous request pending) 863 { 864 if ( not r_tgt_icache_req.read() ) 865 { 866 r_tgt_fsm = TGT_RSP_ICACHE; 867 r_tgt_icache_req = true; 868 } 869 break; 870 } 871 //////////////////// 872 case TGT_REQ_DCACHE: // set the request (if no previous request pending) 873 { 874 if ( not r_tgt_dcache_req.read() ) 875 { 876 r_tgt_fsm = TGT_RSP_DCACHE; 877 r_tgt_dcache_req = true; 878 } 879 break; 880 } 881 /////////////////////// 882 case TGT_RSP_BROADCAST: // waiting acknowlege from both dcache fsm and icache fsm 883 // no VCI response when the r_tgt_*cache_rsp flip_flop is false 884 { 885 if ( not r_tgt_icache_req.read() and not r_tgt_dcache_req.read() ) 886 { 887 if ( r_tgt_icache_rsp.read() or r_tgt_dcache_rsp.read() ) // at least one response 888 { 889 if ( p_vci_tgt_c.rspack.read()) 890 { 891 // reset dcache first if activated 892 if (r_tgt_dcache_rsp) r_tgt_dcache_rsp = false; 893 else r_tgt_icache_rsp = false; 894 } 895 } 896 else 897 { 898 r_tgt_fsm = TGT_IDLE; 899 } 900 } 901 break; 902 } 903 //////////////////// 904 case TGT_RSP_ICACHE: // waiting acknowledge from the icache fsm 905 { 906 // no VCI response when the r_tgt_icache_rsp flip_flop is false 907 if ( not r_tgt_icache_req.read() and p_vci_tgt_c.rspack.read() ) 908 { 909 r_tgt_fsm = TGT_IDLE; 910 r_tgt_icache_rsp = false; 911 } 912 break; 913 } 914 //////////////////// 915 case TGT_RSP_DCACHE: // waiting acknowledge from the dcache fsm 916 { 917 // no VCI response when the r_tgt_dcache_rsp flip_flop is false 918 if ( not r_tgt_dcache_req.read() and p_vci_tgt_c.rspack.read() ) 919 { 920 r_tgt_fsm = TGT_IDLE; 921 r_tgt_dcache_rsp = false; 922 } 923 break; 924 } 925 } // end switch TGT_FSM 926 927 ///////////////////////////////////////////////////////////////////// 928 // Get data and instruction requests from processor 929 /////////////////////////////////////////////////////////////////////// 930 931 typename iss_t::InstructionRequest ireq = ISS_IREQ_INITIALIZER; 932 typename iss_t::DataRequest dreq = ISS_DREQ_INITIALIZER; 933 934 r_iss->getRequests(ireq, dreq); 935 936 /////////////////////////////////////////////////////////////////////////////// 937 // The ICACHE FSM controls the following ressources: 938 // - r_icache_fsm 939 // - r_icache_fsm_save 940 // - r_icache_addr_save 941 // - r_icache_miss_req (set) 942 // - r_icache_unc_req (set) 943 // - r_icache_cleanup_req (set) 944 // - r_icache_cleanup_line 945 // - r_icache_cleanup_set 946 // - r_icache_cleanup_way 947 // - r_icache_miss_inval 948 // - r_icache (instruction cache access) 949 // - r_vci_rsp_ins_error (reset) 950 // - r_tgt_icache_req (reset) 951 // - r_tgt_icache_rsp 952 // - ireq & irsp structures for communication with the processor 953 // 954 // 1/ Coherence requests (update or invalidate) have highest priority. 955 // They are taken into account in IDLE, UNC_WAIT, and MISS_WAIT states. 956 // In case of coherence request the ICACHE FSM goes to the CC_CHECK 957 // state to test the cache hit, and then to the CC_INVAL or 958 // CC_UPDATE states to execute the request. It reset the r_tgt_icache_req 959 // flip_flop to signal completion, writes in the r_tgt_icache_rsp 960 // to allow the VCI response, and returns in the pre-empted state. 961 // 962 // 2/ Processor requests are taken into account only in the IDLE state. 963 // In case of miss, or in case of uncached instruction, the FSM 964 // writes the missing address line in the r_icache_addr_save register 965 // and sets the r_icache_miss_req or the r_icache_unc_req flip-flops. 966 // These request flip-flops are reset by the VCI_RSP FSM 967 // when the VCI transaction is completed. 968 // 969 // 3/ In case of uncacheable instruction, the VCI_RSP FSM writes the 970 // requested instruction in the r_icache_unc_buf register, and 971 // sets the r_icache_unc_valid flip_flop. This flip_flop is reset 972 // by the ICACHE FSM. 973 // 974 // 4/ In case of bus error, the VCI_RSP FSM sets the r_vci_rsp_ins_error 975 // flip-flop, and does not write any data in the response FIFO. 976 // The r_vci_rsp_ins_error flip-flop is reset by the ICACHE FSM. 977 //////////////////////////////////////////////////////////////////////////////// 978 979 // The default value for irsp.valid is false 980 typename iss_t::InstructionResponse irsp = ISS_IRSP_INITIALIZER; 981 982 switch( r_icache_fsm.read() ) 983 { 984 ///////////////// 985 case ICACHE_IDLE: 986 { 987 if ( r_tgt_icache_req.read() ) // coherence request 988 { 989 r_icache_fsm = ICACHE_CC_CHECK; 990 r_icache_fsm_save = r_icache_fsm.read(); 991 break; 992 } 993 if ( ireq.valid ) // processor request 994 { 995 bool cacheable = m_cacheability_table[ireq.addr]; 996 vci_addr_t addr = (vci_addr_t)ireq.addr; 997 998 if ( cacheable ) // cacheable 999 { 1000 data_t inst; 1001 bool hit = r_icache->read(addr, &inst); 1002 m_conso_icache_dir_read++; 1003 m_conso_icache_data_read++; 1004 if ( !hit ) // cacheable miss 1005 { 1006 // in order to avoid a dead-lock with the mem_cache 1007 // (in case of simultaneous broadcast for example), 1008 // we check that the previous cleanup request is completed 1009 // and the ICACHE FSM is blocked in IDLE state until completion 1010 if ( not r_icache_cleanup_req.read() ) 1011 { 1012 r_icache_fsm = ICACHE_MISS_VICTIM; 1013 r_icache_miss_req = true; 1014 r_icache_addr_save = addr; 1015 m_cpt_ins_miss++; 1016 m_cost_ins_miss_frz++; 1017 } 1018 } 1019 else // cacheable hit 1020 { 1021 irsp.valid = true; 1022 irsp.instruction = inst; 1023 m_cpt_ins_cacheable++; 1024 } 1025 } 1026 else // non cacheable 1027 { 1028 if ( r_icache_unc_valid.read() and (addr == r_icache_addr_save.read()) ) 1029 { 1030 r_icache_unc_valid = false; 1031 irsp.valid = true; 1032 irsp.instruction = r_icache_unc_buf.read(); 1033 m_cpt_ins_uncacheable++; 1034 } 1035 else 1036 { 1037 r_icache_unc_valid = false; 1038 r_icache_fsm = ICACHE_UNC_WAIT; 1039 r_icache_unc_req = true; 1040 r_icache_addr_save = addr; 1041 } 1042 } 1043 } 1044 break; 1045 } 1046 //////////////////////// 1047 case ICACHE_MISS_VICTIM: // Selects (and invalidates) a victim line 1048 { // Set the r_icache_cleanup_req flip-flop 1049 // when the selected slot is not empty 1050 m_cost_ins_miss_frz++; 1051 1052 size_t way; 1053 size_t set; 1054 vci_addr_t victim; 1055 1056 r_icache_cleanup_req = r_icache->victim_select( r_icache_addr_save.read(), 1057 &victim, 1058 &way, 1059 &set ); 1060 r_icache_cleanup_line = victim; 1061 r_icache_cleanup_way = way; 1062 r_icache_cleanup_set = set; 1063 r_icache_fsm = ICACHE_MISS_WAIT; 1064 break; 1065 } 1066 ////////////////////// 1067 case ICACHE_MISS_WAIT: // waiting the response to a miss request 1068 { // to test a bus error 1069 m_cost_ins_miss_frz++; 1070 1071 if ( r_tgt_icache_req.read() ) // coherence request 1072 { 1073 r_icache_fsm = ICACHE_CC_CHECK; 1074 r_icache_fsm_save = r_icache_fsm.read(); 1075 break; 1076 } 1077 1078 if ( r_vci_rsp_ins_error.read() ) 1079 { 1080 r_icache_fsm = ICACHE_ERROR; 1081 } 1082 else if ( r_vci_rsp_fifo_icache.rok() ) 1083 { 1084 r_icache_update_word = 0; 1085 r_icache_fsm = ICACHE_MISS_UPDT; 1086 } 1087 break; 1088 } 1089 ////////////////////// 1090 case ICACHE_MISS_UPDT: // Update the cache (one word per cycle) 1091 { 1092 m_cost_ins_miss_frz++; 1093 if ( r_vci_rsp_fifo_icache.rok() ) 1094 { 1095 size_t word = r_icache_update_word.read(); 1096 vci_addr_t addr = r_icache_addr_save.read(); 1097 size_t way = r_icache_cleanup_way.read(); 1098 size_t set = r_icache_cleanup_set.read(); 1099 1100 m_conso_icache_data_write++; 1101 // if the pending miss is cancelled by a matching coherence request 1102 // we pop the FIFO, but we don't update the cache 1103 if ( not r_icache_miss_inval.read() ) 1104 r_icache->write( way, 1105 set, 1106 word, 1107 r_vci_rsp_fifo_icache.read() ); 1108 1109 vci_rsp_fifo_icache_get = true; 1110 r_icache_update_word = word+1; 1111 1112 // if last word, finish the update 1113 if ( word == m_cache_words-1 ) 1114 { 1115 if ( not r_icache_miss_inval.read() ) 1116 { 1117 m_conso_icache_dir_write++; 1118 r_icache->victim_update_tag(addr, way, set); 1119 } 1120 r_icache_miss_inval = false; 1121 r_icache_fsm = ICACHE_IDLE; 1122 } 1123 } 1124 break; 1125 } 1126 ///////////////////// 1127 case ICACHE_UNC_WAIT: // waiting the response to an uncached request 1128 { 1129 if ( r_tgt_icache_req.read() ) // coherence request 1130 { 1131 r_icache_fsm = ICACHE_CC_CHECK; 1132 r_icache_fsm_save = r_icache_fsm.read(); 1133 break; 1134 } 1135 if ( r_vci_rsp_ins_error ) 1136 { 1137 r_icache_fsm = ICACHE_ERROR; 1138 } 1139 else if ( r_vci_rsp_fifo_icache.rok() ) 1140 { 1141 vci_rsp_fifo_icache_get = true; 1142 r_icache_unc_buf = r_vci_rsp_fifo_icache.read(); 1143 r_icache_unc_valid = true; 1144 r_icache_fsm = ICACHE_IDLE; 1145 } 1146 break; 1147 } 1148 ////////////////// 1149 case ICACHE_ERROR: 1150 { 1151 irsp.error = true; 1152 irsp.valid = true; 1153 r_icache_fsm = ICACHE_IDLE; 1154 r_vci_rsp_ins_error = false; 1155 break; 1156 } 1157 ///////////////////// 1158 case ICACHE_CC_CHECK: // check directory in case of coherence request 1159 { 1160 vci_addr_t addr = r_tgt_addr.read(); 1161 vci_addr_t mask = ~((m_cache_words<<2)-1); 1162 1163 if( (r_icache_fsm_save.read() == ICACHE_MISS_WAIT) and 1164 ((r_icache_addr_save.read() & mask) == (addr & mask))) 1165 // The coherence request matches a pending miss 1166 { 1167 r_icache_miss_inval = true; 1168 r_tgt_icache_req = false; 1169 r_tgt_icache_rsp = r_tgt_update.read(); 1170 r_icache_fsm = r_icache_fsm_save.read(); 1171 } 1172 else // no match for a pending miss 1173 { 1174 size_t way; 1175 size_t set; 1176 size_t word; 1177 bool hit = r_icache->hit(addr, 1178 &way, 1179 &set, 1180 &word); 1181 r_icache_cc_way = way; 1182 r_icache_cc_set = set; 1183 1184 m_conso_icache_dir_read++; 1185 1186 if ( hit and r_tgt_update.read() ) // hit update 1187 { 1188 r_icache_fsm = ICACHE_CC_UPDT; 1189 r_icache_update_word = r_tgt_word_min.read(); 1190 } 1191 else if ( hit and not r_tgt_update.read() ) // hit inval 1192 { 1193 r_icache_fsm = ICACHE_CC_INVAL; 1194 } 1195 else // miss can happen 1196 { 1197 r_tgt_icache_req = false; 1198 r_tgt_icache_rsp = r_tgt_update.read(); 1199 r_icache_fsm = r_icache_fsm_save.read(); 1200 } 1201 } 1202 break; 1203 } 1204 ///////////////////// 1205 case ICACHE_CC_INVAL: 1206 { 1207 vci_addr_t nline; 1208 r_icache->inval( r_icache_cc_way.read(), 1209 r_icache_cc_way.read(), 1210 &nline ); 1211 r_tgt_icache_req = false; 1212 r_tgt_icache_rsp = true; 1213 r_icache_fsm = r_icache_fsm_save.read(); 1214 break; 1215 } 1216 ///////////////////// 1217 case ICACHE_CC_UPDT: 1218 { 1219 size_t word = r_icache_update_word.read(); 1220 r_icache->write( r_icache_cc_way.read(), 1221 r_icache_cc_set.read(), 1222 word, 1223 r_tgt_buf[word].read(), 1224 r_tgt_be[word].read() ); 1225 r_icache_update_word = word+1; 1226 1227 if ( word == r_tgt_word_max.read() ) // last word 1228 { 1229 r_tgt_icache_req = false; 1230 r_tgt_icache_rsp = true; 1231 r_icache_fsm = r_icache_fsm_save.read(); 1232 } 1233 break; 1234 } 1235 } // end switch r_icache_fsm 1236 1237 // save the IREQ and IRSP fields for the print_trace() function 1238 m_ireq_valid = ireq.valid; 1239 m_ireq_addr = ireq.addr; 1240 m_ireq_mode = ireq.mode; 1241 1242 m_irsp_valid = irsp.valid; 1243 m_irsp_instruction = irsp.instruction; 1244 m_irsp_error = irsp.error; 1245 1246 //////////////////////////////////////////////////////////////////////:///////////// 1247 // The DCACHE FSM controls the following ressources: 1248 // - r_dcache_fsm 1249 // - r_dcache_fsm_save 1250 // - r_dcache (data cache access) 1251 // - r_dcache_addr_save 1252 // - r_dcache_wdata_save 1253 // - r_dcache_be_save 1254 // - r_dcache_way_save 1255 // - r_dcache_set_save 1256 // - r_dcache_word_save 1257 // - r_dcache_miss_req (set) 1258 // - r_dcache_unc_req (set) 1259 // - r_dcache_sc_req (set) 1260 // - r_dcache_cleanup_req (set) 1261 // - r_vci_rsp_data_error (reset) 1262 // - r_tgt_dcache_req (reset) 1263 // - r_wbuf write 1264 // - drsp structure 1265 // 1266 // 1/ Coherence requests : 1267 // There is a coherence request when the tgt_dcache_req flip-flop is set, 1268 // requesting a line invalidation or a line update. 1269 // Coherence requests are taken into account in IDLE, UNC_WAIT, MISS_WAIT states, 1270 // and have the highest priority. 1271 // The actions associated to the pre-empted state are not executed, the DCACHE FSM 1272 // goes to the CC_CHECK state to execute the requested action, and returns to the 1273 // pre-empted state. 1274 // 1275 // 2/ processor requests : 1276 // Processor READ requests are taken into account in IDLE state only. 1277 // In order to support WRITE bursts, write requests are taken into account 1278 // in the WRITE_UPDT state as well as in the IDLE state. 1279 // - The processor read requests cannot be satisfied if 1280 // there is a cached read miss, or an uncached read. 1281 // - The processor write requests cannot be satisfied when the write buffer is full. 1282 // 1283 // 3/ Atomic instructions LL/SC 1284 // The reservation registers (r_dcache_ll_valid, r_dcache_ll_addr and 1285 // r_dcache_ll_data are stored in the L1 cache controller, and not in the 1286 // memory controller. 1287 // - LL requests from the processor and are transmitted as standard 1288 // VCI read transactions (one word / one line, depending on the cacheability). 1289 // - SC requests from the processor are systematically transmitted to the 1290 // memory cache as compare&swap requests (both the data value stored in the 1291 // r_dcache_ll_data register and the new value). 1292 // The LL/SC address can be cacheable or not cacheable. 1293 // 1294 // 4/ Non cacheable access 1295 // This component implement a strong order between non cacheable access 1296 // (read or write) : A new non cacheable VCI transaction starts only when 1297 // the previous non cacheable transaction is completed. Both cacheable and 1298 // non cacheable transactions use the write buffer, but the DCACHE FSM registers 1299 // a non cacheable write transaction posted in the write buffer by setting the 1300 // r_dcache_pending_unc_write flip_flop. All other non cacheable requests 1301 // are stalled until this flip-flop is reset by the VCI_RSP_FSM (when the 1302 // pending non cacheable write transaction completes). 1303 // 1304 // 5/ Error handling : Read Bus Errors are synchronous events, but 1305 // Write Bus Errors are asynchronous events (processor is not frozen). 1306 // - If a Read Bus Error is detected, the VCI_RSP FSM sets the 1307 // r_vci_rsp_data_error flip-flop, without writing any data in the 1308 // r_vci_rsp_fifo_dcache FIFO, and the synchronous error is signaled 1309 // by the DCACHE FSM. 1310 // - If a Write Bus Error is detected, the VCI_RSP FSM signals 1311 // the asynchronous error using the setWriteBerr() method. 1312 /////////////////////////////////////////////////////////////////////////////////// 1313 1314 // The default value for drsp.valid is false 1315 typename iss_t::DataResponse drsp = ISS_DRSP_INITIALIZER; 1316 1317 switch ( r_dcache_fsm.read() ) 1318 { 1319 ///////////////// 1320 case DCACHE_IDLE: // waiting requests from processor 1321 { 1322 if ( r_tgt_dcache_req.read() ) // coherence request 1323 { 1324 r_dcache_fsm = DCACHE_CC_CHECK; 1325 r_dcache_fsm_save = r_dcache_fsm.read(); 1326 break; 1327 } 1328 if ( dreq.valid ) // processor request 1329 { 1330 bool cacheable = m_cacheability_table[dreq.addr]; 1331 vci_addr_t addr = (vci_addr_t)dreq.addr; 1332 1333 switch( dreq.type ) 1334 { 1335 case iss_t::DATA_LL: 1336 case iss_t::DATA_READ: 1337 { 1338 if ( cacheable ) // cacheable read 1339 { 1340 data_t rdata; 1341 bool hit = r_dcache->read(addr, &rdata); 1342 m_conso_dcache_dir_read++; 1343 m_conso_dcache_data_read++; 1344 if ( !hit ) // cacheable read miss 1345 { 1346 // in order to avoid a dead-lock with the mem_cache 1347 // (in case of simultaneous broadcast for example), 1348 // we check that the previous cleanup request is completed 1349 // if not the DCACHE_FSM is blocked in IDLE state until completion 1350 if ( not r_dcache_cleanup_req.read() ) 1351 { 1352 r_dcache_fsm = DCACHE_MISS_VICTIM; 1353 r_dcache_miss_req = true; 1354 r_dcache_addr_save = addr; 1355 m_cpt_data_read_miss++; 1356 m_cost_data_miss_frz++; 1357 } 1358 } 1359 else // cacheable read hit 1360 { 1361 m_cpt_data_read_cacheable++; 1362 drsp.valid = true; 1363 drsp.rdata = rdata; 1364 1365 // makes reservation in case of LL 1366 if( dreq.type == iss_t::DATA_LL ) 1367 { 1368 m_cpt_data_ll++; 1369 r_dcache_ll_valid = true; 1370 r_dcache_ll_data = rdata; 1371 r_dcache_ll_addr = addr; 1372 } 1373 } 1374 } 1375 else // non cacheable read 1376 { 1377 // non cacheable accesses must be strongly ordered 1378 // A non cacheable read must be delayed if there is 1379 // a pending uncacheable write in the write buffer 1380 if ( not r_dcache_pending_unc_write.read() ) 1381 { 1382 if ( r_dcache_unc_valid.read() and // hit 1383 (addr == r_dcache_addr_save.read()) ) 1384 { 1385 r_dcache_unc_valid = false; 1386 drsp.valid = true; 1387 drsp.rdata = r_dcache_unc_buf.read(); 1388 m_cpt_data_read_uncacheable++; 1389 1390 // makes reservation in case of uncacheable LL 1391 if( dreq.type == iss_t::DATA_LL ) 1392 { 1393 m_cpt_data_ll++; 1394 r_dcache_ll_valid = true; 1395 r_dcache_ll_data = r_dcache_unc_buf.read(); 1396 r_dcache_ll_addr = addr; 1397 } 1398 } 1399 else // miss 1400 { 1401 r_dcache_unc_valid = false; 1402 r_dcache_unc_req = true; 1403 r_dcache_fsm = DCACHE_UNC_WAIT; 1404 r_dcache_addr_save = addr; 1405 } 1406 } // end if pending_unc_write 1407 } 1408 break; 1409 } 1410 case iss_t::DATA_SC: 1411 { 1412 // - if a previous LL (with the same address) is registered, 1413 // we makes a SC transaction, that will store the response 1414 // in the r_dcache_unc_buf register (0 if success). 1415 // As for the non cacheable read, we must test the 1416 // r_dcache_unc_valid flip-flop to detect the SC completion, 1417 // return the value stored in r_dcache_unc_buf, and invalidate 1418 // the LL reservation. 1419 // - if there is no registerd LL, we just stay in IDLE state 1420 // and return 1 (atomic access failed) 1421 1422 if( r_dcache_ll_valid.read() and (r_dcache_ll_addr.read() == addr)) 1423 { 1424 if ( r_dcache_unc_valid.read() and // SC done 1425 (addr == r_dcache_addr_save.read()) ) 1426 { 1427 r_dcache_ll_valid = false; 1428 r_dcache_unc_valid = false; 1429 drsp.valid = true; 1430 drsp.rdata = r_dcache_unc_buf.read(); 1431 m_cpt_data_sc++; 1432 } 1433 else // SC to be done 1434 { 1435 r_dcache_sc_req = true; 1436 r_dcache_fsm = DCACHE_UNC_WAIT; 1437 r_dcache_addr_save = addr; 1438 r_dcache_wdata_save = dreq.wdata; 1439 } 1440 } 1441 else // no registered LL 1442 { 1443 drsp.valid = true; 1444 drsp.rdata = 1; 1445 r_dcache_ll_valid = false; 1446 } 1447 break; 1448 } 1449 case iss_t::XTN_READ: 1450 case iss_t::XTN_WRITE: 1451 { 1452 // only DCACHE INVALIDATE and SYNC requests are supported 1453 if ( dreq.addr>>2 == iss_t::XTN_DCACHE_INVAL ) 1454 { 1455 m_cpt_xtn_dcache_inval++; 1456 r_dcache_fsm = DCACHE_INVAL; 1457 r_dcache_wdata_save = dreq.wdata; 1458 } 1459 else if ( dreq.addr>>2 == iss_t::XTN_SYNC ) 1460 { 1461 m_cpt_xtn_sync++; 1462 // Test if write buffer is already empty 1463 if ( r_wbuf->empty() ) 1464 { 1465 drsp.valid = true; 1466 r_dcache_fsm = DCACHE_IDLE; 1467 } 1468 else 1469 { 1470 r_dcache_fsm = DCACHE_SYNC; 1471 } 1472 } 1473 else 1474 { 1475 std::cout << "Warning in VCI_CC_XCACHE_WRAPPER " 1476 << name() << std::endl; 1477 std::cout << "Unsupported external access : " 1478 << (dreq.addr>>2) << std::endl; 1479 drsp.valid = true; 1480 r_dcache_fsm = DCACHE_IDLE; 1481 } 1482 break; 1483 } 1484 case iss_t::DATA_WRITE: 1485 { 1486 if ( cacheable ) // cacheable write 1487 { 1488 bool hit; 1489 size_t way = 0; 1490 size_t set = 0; 1491 size_t word = 0; 1492 1493 m_conso_dcache_dir_read++; 1494 hit = r_dcache->hit(addr, &way, &set, &word); 1495 m_conso_wbuf_write++; 1496 bool wok = r_wbuf->write(addr, dreq.be, dreq.wdata, cacheable); 1497 if ( wok ) 1498 { 1499 m_cpt_data_write_cacheable++; 1500 drsp.valid = true; 1501 if (hit) // cached write 1502 { 1503 m_cpt_data_write_hit++; 1504 r_dcache_fsm = DCACHE_WRITE_UPDT; 1505 r_dcache_addr_save = addr; 1506 r_dcache_wdata_save = dreq.wdata; 1507 r_dcache_be_save = dreq.be; 1508 r_dcache_way_save = way; 1509 r_dcache_set_save = set; 1510 r_dcache_word_save = word; 1511 } 1512 else // non cached 1513 { 1514 r_dcache_fsm = DCACHE_IDLE; 1515 } 1516 } 1517 else // write miss into write buffer 1518 { 1519 r_dcache_fsm = DCACHE_IDLE; 1520 m_cost_write_frz++; 1521 } 1522 } 1523 else // non cacheable write 1524 { 1525 // non cacheable accesses must be strongly ordered 1526 // A non cacahble write must be delayed if there is 1527 // a pending uncacheable write in the write buffer 1528 if ( not r_dcache_pending_unc_write.read() ) 1529 { 1530 m_conso_wbuf_write++; 1531 bool wok = r_wbuf->write(addr, dreq.be, dreq.wdata, cacheable); 1532 if ( wok ) 1533 { 1534 m_cpt_data_write_uncacheable++; 1535 drsp.valid = true; 1536 } 1537 } 1538 r_dcache_fsm = DCACHE_IDLE; 1539 } 1540 1541 break; 1542 } 1543 } // end switch dreq.type 1544 } // end if dreq.valid 1545 break; 1546 } 1547 /////////////////////// 1548 case DCACHE_WRITE_UPDT: 1549 { 1550 // cache update (address, data & be from the previous cycle) 1551 m_conso_dcache_data_write++; 1552 r_dcache->write( r_dcache_way_save.read(), 1553 r_dcache_set_save.read(), 1554 r_dcache_word_save.read(), 1555 r_dcache_wdata_save.read(), 1556 r_dcache_be_save.read() ); 1557 1558 #if DEBUG_DCACHE 1559 if ( (m_cpt_total_cycles > DEBUG_START_CYCLE) and (m_srcid_d == DEBUG_ID) ) 1560 { 1561 std::cout << " <PROC.DCACHE_WRITE_UPDT> Writing one word :" << std::hex 1562 << " data = " << r_dcache_wdata_save.read() 1563 << " / be = " << r_dcache_be_save.read() 1564 << " / way = " << r_dcache_way_save.read() 1565 << " / set = " << r_dcache_set_save.read() 1566 << " / word = " << r_dcache_word_save.read() << std::endl; 1567 } 213 1568 #endif 214 m_nb_dcache(nb_dcache), 215 m_nb_cache((m_nb_dcache>m_nb_icache)?m_nb_dcache:m_nb_icache), 216 m_dcache_ways(dcache_ways), 217 m_dcache_words(dcache_words), 218 m_dcache_words_shift(uint32_log2(dcache_words)+uint32_log2(sizeof(data_t))), 219 m_dcache_yzmask((~0)<<m_dcache_words_shift), 220 m_icache_ways(icache_ways), 221 m_icache_words(icache_words), 222 m_icache_words_shift(uint32_log2(icache_words)+uint32_log2(sizeof(data_t))), 223 m_icache_yzmask((~0)<<m_icache_words_shift), 224 m_cache_words((dcache_words)?dcache_words:icache_words), 225 226 r_cpu_prior("r_cpu_prior"), 227 228 r_vci_cmd_fsm("r_vci_cmd_fsm"), 229 r_vci_cmd_min("r_vci_cmd_min"), 230 r_vci_cmd_max("r_vci_cmd_max"), 231 r_vci_cmd_cpt("r_vci_cmd_cpt"), 232 r_vci_cmd_dcache_prior("r_vci_cmd_dcache_prior"), 233 r_vci_cmd_num_icache_prior("r_vci_cmd_num_icache_prior"), 234 r_vci_cmd_num_dcache_prior("r_vci_cmd_num_dcache_prior"), 235 r_vci_cmd_num_cache("r_vci_cmd_num_cache"), 236 237 r_vci_rsp_fsm("r_vci_rsp_fsm"), 238 r_vci_rsp_cpt("r_vci_rsp_cpt"), 239 r_vci_rsp_num_cache("r_vci_rsp_num_cache"), 240 241 r_vci_rsp_fifo_icache_data ("r_vci_rsp_fifo_icache_data" ,2), 242 r_vci_rsp_fifo_icache_num_cache ("r_vci_rsp_fifo_icache_num_cache",2), 243 r_vci_rsp_fifo_dcache_data ("r_vci_rsp_fifo_dcache_data" ,2), 244 r_vci_rsp_fifo_dcache_num_cache ("r_vci_rsp_fifo_dcache_num_cache",2), 245 246 r_cache_word("r_cache_word"), 247 248 r_vci_tgt_fsm("r_vci_tgt_fsm"), 249 r_tgt_iaddr("r_tgt_iaddr"), 250 r_tgt_daddr("r_tgt_daddr"), 251 r_tgt_word("r_tgt_word"), 252 r_tgt_update("r_tgt_update"), 253 r_tgt_update_data("r_tgt_update_data"), 254 // r_tgt_brdcast("r_tgt_brdcast"), 255 r_tgt_srcid("r_tgt_srcid"), 256 r_tgt_pktid("r_tgt_pktid"), 257 r_tgt_trdid("r_tgt_trdid"), 258 // r_tgt_plen("r_tgt_plen"), 259 r_tgt_num_cache("r_tgt_num_cache"), 260 261 r_cleanup_fsm("r_cleanup_fsm"), 262 r_cleanup_num_cache("r_cleanup_num_cache"), 263 r_cleanup_icache("r_cleanup_icache"), 264 265 m_num_cache_LSB(uint32_log2(icache_words) + uint32_log2(sizeof(data_t))), 266 m_num_cache_MSB(uint32_log2(nb_dcache) + m_num_cache_LSB) 1569 1570 // possible write after write 1571 if ( dreq.valid and (dreq.type == iss_t::DATA_WRITE) ) 1572 { 1573 bool cacheable = m_cacheability_table[dreq.addr]; 1574 vci_addr_t addr = (vci_addr_t)dreq.addr; 1575 1576 if ( cacheable ) // cacheable write 1577 { 1578 bool hit; 1579 size_t way = 0; 1580 size_t set = 0; 1581 size_t word = 0; 1582 1583 m_conso_dcache_dir_read++; 1584 hit = r_dcache->hit(addr, &way, &set, &word); 1585 m_conso_wbuf_write++; 1586 bool wok = r_wbuf->write(addr, dreq.be, dreq.wdata, cacheable); 1587 if (wok) 1588 { 1589 m_cpt_data_write_cacheable++; 1590 drsp.valid = true; 1591 if (hit) // cached write 1592 { 1593 m_cpt_data_write_hit++; 1594 r_dcache_fsm = DCACHE_WRITE_UPDT; 1595 r_dcache_addr_save = addr; 1596 r_dcache_wdata_save = dreq.wdata; 1597 r_dcache_be_save = dreq.be; 1598 r_dcache_way_save = way; 1599 r_dcache_set_save = set; 1600 r_dcache_word_save = word; 1601 } 1602 else // uncached write 1603 { 1604 r_dcache_fsm = DCACHE_IDLE; 1605 } 1606 } 1607 else // write miss into write buffer 1608 { 1609 m_cost_write_frz++; 1610 r_dcache_fsm = DCACHE_IDLE; 1611 } 1612 } 1613 else // non cacheable write 1614 { 1615 // non cacheable accesses must be strongly ordered 1616 // A non cacahble write must be delayed if there is 1617 // a pending uncacheable write in the write buffer 1618 if ( not r_dcache_pending_unc_write.read() ) 1619 { 1620 m_conso_wbuf_write++; 1621 bool wok = r_wbuf->write(addr, dreq.be, dreq.wdata, cacheable); 1622 if ( wok ) 1623 { 1624 m_cpt_data_write_uncacheable++; 1625 drsp.valid = true; 1626 } 1627 } 1628 r_dcache_fsm = DCACHE_IDLE; 1629 } 1630 } 1631 else // no valid write request 1632 { 1633 r_dcache_fsm = DCACHE_IDLE; 1634 } 1635 break; 1636 } 1637 //////////////////////// 1638 case DCACHE_MISS_VICTIM: // Selects (and invalidates) a victim line 1639 { // Set the r_dcache_cleanup_req flip-flop 1640 // when the selected slot is not empty 1641 m_cost_data_miss_frz++; 1642 1643 size_t way; 1644 size_t set; 1645 vci_addr_t addr = r_dcache_addr_save.read(); 1646 vci_addr_t victim; 1647 1648 bool cleanup_requested = r_dcache->victim_select( addr, &victim, &way, &set ); 1649 1650 r_dcache_cleanup_line = victim; 1651 r_dcache_cleanup_way = way; 1652 r_dcache_cleanup_set = set; 1653 r_dcache_cleanup_req = cleanup_requested; 1654 r_dcache_fsm = DCACHE_MISS_WAIT; 1655 break; 1656 } 1657 ////////////////////// 1658 case DCACHE_MISS_WAIT: // Waiting the response to a miss request 1659 { // to test a bus error 1660 m_cost_data_miss_frz++; 1661 1662 if ( r_tgt_dcache_req.read() ) // coherence request 1663 { 1664 r_dcache_fsm = DCACHE_CC_CHECK; 1665 r_dcache_fsm_save = r_dcache_fsm.read(); 1666 break; 1667 } 1668 1669 if ( r_vci_rsp_data_error.read() ) 1670 { 1671 r_dcache_fsm = DCACHE_ERROR; 1672 } 1673 else if ( r_vci_rsp_fifo_dcache.rok() ) 1674 { 1675 r_dcache_update_word = 0; 1676 r_dcache_fsm = DCACHE_MISS_UPDT; 1677 } 1678 break; 1679 } 1680 ////////////////////// 1681 case DCACHE_MISS_UPDT: // Update the cache (one word per cycle) 1682 { 1683 m_cost_data_miss_frz++; 1684 1685 size_t word = r_dcache_update_word.read(); 1686 vci_addr_t addr = r_dcache_addr_save.read(); 1687 size_t way = r_dcache_cleanup_way.read(); 1688 size_t set = r_dcache_cleanup_set.read(); 1689 1690 if ( r_vci_rsp_fifo_dcache.rok() ) 1691 { 1692 if ( not r_dcache_miss_inval.read() ) // no matching coherence request 1693 { 1694 m_conso_dcache_data_write++; 1695 r_dcache->write( way, 1696 set, 1697 word, 1698 r_vci_rsp_fifo_dcache.read() ); 1699 1700 if ( word == m_cache_words-1 ) // last word 1701 { 1702 m_conso_dcache_dir_write++; 1703 r_dcache->victim_update_tag(addr, way, set); 1704 r_dcache_fsm = DCACHE_IDLE; 1705 } 1706 vci_rsp_fifo_dcache_get = true; 1707 r_dcache_update_word = word+1; 1708 } 1709 else // if there is a matching coherence request : 1710 // we pop the response FIFO, but we don't update the cache 1711 // when we receive the last word, we send a cleanup for the 1712 // missing line and return to the IDLE state 1713 { 1714 if ( word < m_cache_words-1 ) 1715 { 1716 vci_rsp_fifo_dcache_get = true; 1717 r_dcache_update_word = word+1; 1718 } 1719 else // last word 1720 { 1721 if ( not r_dcache_cleanup_req ) 1722 { 1723 vci_rsp_fifo_dcache_get = true; 1724 r_dcache_cleanup_req = true; 1725 r_dcache_cleanup_line = r_dcache_addr_save.read() >> m_cache_words_shift; 1726 r_dcache_miss_inval = false; 1727 r_dcache_fsm = DCACHE_IDLE; 1728 } 1729 } 1730 } 1731 1732 #if DEBUG_DCACHE 1733 if ( (m_cpt_total_cycles > DEBUG_START_CYCLE) and (m_srcid_d == DEBUG_ID) ) 1734 { 1735 if ( r_dcache_miss_inval.read() ) 267 1736 { 268 // Size of word is 32 bits 269 ASSERT((icache_words*vci_param::B) < (1<<vci_param::K), 270 "Need more PLEN bits."); 271 272 ASSERT((vci_param::T > 2) and ((1<<(vci_param::T-1)) >= (wbuf_nlines/m_nb_dcache)), 273 "Need more TRDID bits."); 274 275 ASSERT(uint32_log2(nb_dcache) <= (1<<vci_param::P), 276 "Need more PKTID bits."); 277 278 ASSERT(IS_POW_OF_2(m_nb_dcache), 279 "nb_dcache must be a power of 2."); 280 281 ASSERT(IS_POW_OF_2(m_nb_cpu) and (m_nb_cpu <= m_nb_dcache) and (m_nb_cpu > 0), 282 "nb cpu must be a multiple of nb cache."); 283 284 ASSERT(IS_POW_OF_2(m_icache_ways) and (m_nb_icache <= m_icache_ways), 285 "nb icache ways must be a multiple of nb cache."); 286 287 ASSERT(IS_POW_OF_2(m_dcache_ways) and (m_nb_dcache <= m_dcache_ways), 288 "nb dcache ways must be a multiple of nb cache."); 289 290 ASSERT(icache_words == dcache_words, 291 "icache_words must be equal at dcache_words."); 292 293 ASSERT(IS_POW_OF_2(wbuf_nlines) and (m_nb_dcache <= wbuf_nlines), 294 "wbuf_nlines must be a multiple of nb cache."); 295 296 // FIXME : s'adapter à la taille des requêtes XTN_READ/XTN_WRITE, car le type est fournit dans le champs l'adresse 297 ASSERT((m_nb_dcache == 1) or (dcache_words >= 16), 298 "When multi cache is activated, need 4 bits (16 word) to the cache set ."); 299 300 if (m_nb_cpu > 1) 301 ASSERT(CC_XCACHE_MULTI_CPU!=0, 302 "Macro CC_XCACHE_MULTI_CPU in wbuf must be set at 1."); 303 304 p_irq = new sc_in<bool> * [m_nb_cpu]; 305 for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) 306 p_irq [num_cpu] = new sc_in<bool> [iss_t::n_irq]; 307 308 m_iss = new iss_t * [m_nb_cpu]; 309 for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) 310 { 311 std::ostringstream iss_name(""); 312 iss_name << this->name() << "_" << num_cpu; 313 314 m_iss[num_cpu] = new iss_t (iss_name.str().c_str(), proc_id+num_cpu); 315 } 316 317 r_icache_lock = new sc_signal<uint32_t>[m_nb_icache]; 318 r_dcache_lock = new sc_signal<uint32_t>[m_nb_dcache]; 319 r_dcache_sync = new sc_signal<bool> [m_nb_dcache]; 320 321 r_icache_fsm = new sc_signal<int> [m_nb_icache]; 322 r_icache_fsm_save = new sc_signal<int> [m_nb_icache]; 323 r_icache_addr_save = new sc_signal<addr_40> [m_nb_icache]; 324 r_icache_miss_req = new sc_signal<bool> [m_nb_icache]; 325 r_icache_miss_way = new sc_signal<size_t> [m_nb_icache]; 326 r_icache_miss_set = new sc_signal<size_t> [m_nb_icache]; 327 r_icache_unc_req = new sc_signal<bool> [m_nb_icache]; 328 r_icache_cleanup_req = new sc_signal<bool> [m_nb_icache]; 329 r_icache_cleanup_line = new sc_signal<addr_40> [m_nb_icache]; 330 r_icache_inval_rsp = new sc_signal<bool> [m_nb_icache]; 331 r_icache_update_addr = new sc_signal<size_t> [m_nb_icache]; 332 r_icache_buf_unc_valid = new sc_signal<bool> [m_nb_icache]; 333 334 r_dcache_fsm = new sc_signal<int> [m_nb_dcache]; 335 r_dcache_fsm_save = new sc_signal<int> [m_nb_dcache]; 336 r_dcache_addr_save = new sc_signal<addr_40> [m_nb_dcache]; 337 r_dcache_wdata_save = new sc_signal<data_t> [m_nb_dcache]; 338 r_dcache_rdata_save = new sc_signal<data_t> [m_nb_dcache]; 339 r_dcache_type_save = new sc_signal<int> [m_nb_dcache]; 340 r_dcache_be_save = new sc_signal<be_t> [m_nb_dcache]; 341 r_dcache_cached_save = new sc_signal<bool> [m_nb_dcache]; 342 r_dcache_num_cpu_save = new sc_signal<uint32_t>[m_nb_dcache]; 343 r_dcache_cleanup_req = new sc_signal<bool> [m_nb_dcache]; 344 r_dcache_cleanup_line = new sc_signal<addr_40> [m_nb_dcache]; 345 r_dcache_miss_req = new sc_signal<bool> [m_nb_dcache]; 346 r_dcache_miss_way = new sc_signal<size_t> [m_nb_dcache]; 347 r_dcache_miss_set = new sc_signal<size_t> [m_nb_dcache]; 348 r_dcache_unc_req = new sc_signal<bool> [m_nb_dcache]; 349 r_dcache_sc_req = new sc_signal<bool> [m_nb_dcache]; 350 r_dcache_inval_rsp = new sc_signal<bool> [m_nb_dcache]; 351 r_dcache_update_addr = new sc_signal<size_t> [m_nb_dcache]; 352 r_dcache_previous_unc = new sc_signal<bool> [m_nb_dcache]; 353 354 r_dcache_ll_data = new sc_signal<data_t> * [m_nb_dcache]; 355 r_dcache_ll_addr = new sc_signal<addr_40> * [m_nb_dcache]; 356 r_dcache_ll_valid = new sc_signal<bool> * [m_nb_dcache]; 357 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 358 { 359 r_dcache_ll_data [num_cache] = new sc_signal<data_t> [m_nb_cpu]; 360 r_dcache_ll_addr [num_cache] = new sc_signal<addr_40> [m_nb_cpu]; 361 r_dcache_ll_valid [num_cache] = new sc_signal<bool> [m_nb_cpu]; 362 } 363 364 r_tgt_icache_req = new sc_signal<bool> [m_nb_icache]; 365 r_tgt_icache_rsp = new sc_signal<bool> [m_nb_icache]; 366 r_tgt_dcache_req = new sc_signal<bool> [m_nb_dcache]; 367 r_tgt_dcache_rsp = new sc_signal<bool> [m_nb_dcache]; 368 369 r_tgt_buf = new data_t [m_cache_words]; 370 r_tgt_be = new be_t [m_cache_words]; 371 372 r_vci_rsp_ins_error = new sc_signal<bool> [m_nb_icache]; 373 r_vci_rsp_data_error = new sc_signal<bool> [m_nb_dcache]; 374 375 ireq = new typename iss_t::InstructionRequest [m_nb_icache]; 376 irsp = new typename iss_t::InstructionResponse [m_nb_icache]; 377 ireq_cached = new bool [m_nb_icache]; 378 ireq_num_cpu = new uint32_t [m_nb_dcache]; 379 380 dreq = new typename iss_t::DataRequest [m_nb_dcache]; 381 drsp = new typename iss_t::DataResponse [m_nb_dcache]; 382 dreq_cached = new bool [m_nb_dcache]; 383 dreq_num_cpu = new uint32_t [m_nb_dcache]; 384 385 m_cpt_icache_access = new uint32_t [m_nb_icache]; 386 m_cpt_dcache_access = new uint32_t [m_nb_dcache]; 387 m_cpt_icache_miss_victim_wait = new uint32_t [m_nb_icache]; 388 m_cpt_dcache_miss_victim_wait = new uint32_t [m_nb_dcache]; 389 390 m_cpt_dcache_store_after_store = new uint32_t [m_nb_dcache]; 391 m_cpt_dcache_hit_after_miss_read = new uint32_t [m_nb_dcache]; 392 m_cpt_dcache_hit_after_miss_write = new uint32_t [m_nb_dcache]; 393 394 m_cpt_fsm_dcache = new uint32_t * [m_nb_dcache]; 395 m_cpt_fsm_icache = new uint32_t * [m_nb_icache]; 396 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 397 m_cpt_fsm_dcache[num_cache] = new uint32_t [soclib::common::size(dcache_fsm_state_str )]; 398 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 399 m_cpt_fsm_icache[num_cache] = new uint32_t [soclib::common::size(icache_fsm_state_str )]; 400 m_cpt_fsm_cmd = new uint32_t [soclib::common::size(cmd_fsm_state_str )]; 401 m_cpt_fsm_rsp = new uint32_t [soclib::common::size(rsp_fsm_state_str )]; 402 m_cpt_fsm_tgt = new uint32_t [soclib::common::size(tgt_fsm_state_str )]; 403 m_cpt_fsm_cleanup = new uint32_t [soclib::common::size(cleanup_fsm_state_str)]; 404 405 m_cpt_frz_cycles = new uint32_t [m_nb_cpu]; 406 // r_icache_fsm("r_icache_fsm"), 407 // r_icache_fsm_save("r_icache_fsm_save"), 408 // r_icache_addr_save("r_icache_addr_save"), 409 // r_icache_miss_req("r_icache_miss_req"), 410 // r_icache_miss_way("r_icache_miss_way"), 411 // r_icache_miss_set("r_icache_miss_set"), 412 // r_icache_unc_req("r_icache_unc_req"), 413 // r_icache_cleanup_req("r_icache_cleanup_req"), 414 // r_icache_cleanup_line("r_icache_cleanup_line"), 415 // r_icache_inval_rsp("r_icache_inval_rsp"), 416 // r_icache_update_addr("r_icache_update_addr"), 417 // r_icache_buf_unc_valid("r_icache_buf_unc_valid"), 418 419 // r_dcache_fsm("r_dcache_fsm"), 420 // r_dcache_fsm_save("r_dcache_fsm_save"), 421 // r_dcache_addr_save("r_dcache_addr_save"), 422 // r_dcache_wdata_save("r_dcache_wdata_save"), 423 // r_dcache_rdata_save("r_dcache_rdata_save"), 424 // r_dcache_type_save("r_dcache_type_save"), 425 // r_dcache_be_save("r_dcache_be_save"), 426 // r_dcache_cached_save("r_dcache_cached_save"), 427 // r_dcache_cleanup_req("r_dcache_cleanup_req"), 428 // r_dcache_cleanup_line("r_dcache_cleanup_line"), 429 // r_dcache_miss_req("r_dcache_miss_req"), 430 // r_dcache_miss_way("r_dcache_miss_way"), 431 // r_dcache_miss_set("r_dcache_miss_set"), 432 // r_dcache_unc_req("r_dcache_unc_req"), 433 // r_dcache_sc_req("r_dcache_sc_req"), 434 // r_dcache_inval_rsp("r_dcache_inval_rsp"), 435 // r_dcache_update_addr("r_dcache_update_addr"), 436 // r_dcache_ll_data("r_dcache_ll_data"), 437 // r_dcache_ll_addr("r_dcache_ll_addr"), 438 // r_dcache_ll_valid("r_dcache_ll_valid"), 439 // r_dcache_previous_unc("r_dcache_previous_unc"), 440 441 // r_tgt_icache_req("r_tgt_icache_req"), 442 // r_tgt_icache_rsp("r_tgt_icache_rsp"), 443 444 // r_tgt_dcache_req("r_tgt_dcache_req"), 445 // r_tgt_dcache_rsp("r_tgt_dcache_rsp"), 446 447 // r_vci_rsp_ins_error("r_vci_rsp_ins_error"), 448 // r_vci_rsp_data_error("r_vci_rsp_data_error"), 449 450 size_t _icache_ways = icache_ways /m_nb_icache; 451 size_t _icache_sets = icache_sets ; 452 size_t _dcache_ways = dcache_ways /m_nb_dcache; 453 size_t _dcache_sets = dcache_sets ; 454 size_t _icache_words = icache_words; 455 size_t _dcache_words = dcache_words; 456 457 size_t _wbuf_nwords = wbuf_nwords ; 458 size_t _wbuf_nlines = wbuf_nlines /m_nb_dcache; 459 460 r_icache = new GenericCache<vci_addr_t> * [m_nb_icache]; 461 r_dcache = new GenericCache<vci_addr_t> * [m_nb_dcache]; 462 r_wbuf = new MultiWriteBuffer<addr_40> * [m_nb_dcache]; 463 464 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 465 { 466 r_icache [num_cache] = new GenericCache<vci_addr_t> ("icache", _icache_ways, _icache_sets, _icache_words); 467 } 468 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 469 { 470 r_dcache [num_cache] = new GenericCache<vci_addr_t> ("dcache", _dcache_ways, _dcache_sets, _dcache_words); 471 r_wbuf [num_cache] = new MultiWriteBuffer<addr_40> ("r_wbuf", _wbuf_nwords, _wbuf_nlines, _dcache_words); 472 } 473 474 m_num_cache_LSB_mask = 0; 475 for (uint32_t i=0; i<m_num_cache_LSB; ++i) 476 { 477 m_num_cache_LSB_mask <<= 1; 478 m_num_cache_LSB_mask |= 1; 479 } 480 m_num_cache_mask = 0; 481 for (uint32_t i=0; i<(m_num_cache_MSB-m_num_cache_LSB); ++i) 482 { 483 m_num_cache_mask <<= 1; 484 m_num_cache_mask |= 1; 485 } 486 487 SC_METHOD(transition); 488 dont_initialize(); 489 sensitive << p_clk.pos(); 490 491 SC_METHOD(genMoore); 492 dont_initialize(); 493 sensitive << p_clk.neg(); 494 495 typename iss_t::CacheInfo cache_info; 496 cache_info.has_mmu = false; 497 cache_info.icache_line_size = icache_words*sizeof(data_t); 498 cache_info.icache_assoc = icache_ways; 499 cache_info.icache_n_lines = icache_sets; 500 cache_info.dcache_line_size = dcache_words*sizeof(data_t); 501 cache_info.dcache_assoc = dcache_ways; 502 cache_info.dcache_n_lines = dcache_sets; 503 504 for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) 505 m_iss[num_cpu]->setCacheInfo(cache_info); 506 507 #if CC_XCACHE_WRAPPER_STOP_SIMULATION 508 m_stop_simulation = false; 509 m_stop_simulation_nb_frz_cycles = new uint32_t [m_nb_cpu]; 510 for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) 511 m_stop_simulation_nb_frz_cycles [num_cpu] = 0; 512 #endif // CC_XCACHE_WRAPPER_STOP_SIMULATION 513 514 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 515 generate_log_transaction_file_icache = true; 516 generate_log_transaction_file_dcache = true; 517 generate_log_transaction_file_cmd = true; 518 generate_log_transaction_file_tgt = true; 519 generate_log_transaction_file_cleanup = true; 520 521 log_transaction_file_icache = new std::ofstream [m_nb_cpu]; 522 log_transaction_file_dcache = new std::ofstream [m_nb_cpu]; 523 for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) 524 { 525 { 526 std::ostringstream filename(""); 527 filename << CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION_PATH << "/Transaction_icache-" << proc_id << "_" << num_cpu << ".log"; 528 log_transaction_file_icache[num_cpu].open(filename.str().c_str() ,std::ios::out | std::ios::trunc); 529 } 530 { 531 std::ostringstream filename(""); 532 filename << CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION_PATH << "/Transaction_dcache-" << proc_id << "_" << num_cpu << ".log"; 533 log_transaction_file_dcache[num_cpu].open(filename.str().c_str() ,std::ios::out | std::ios::trunc); 534 } 535 } 536 537 { 538 std::ostringstream filename(""); 539 filename << CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION_PATH << "/Transaction_cmd-" << proc_id << ".log"; 540 log_transaction_file_cmd.open(filename.str().c_str() ,std::ios::out | std::ios::trunc); 541 } 542 { 543 std::ostringstream filename(""); 544 filename << CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION_PATH << "/Transaction_tgt-" << proc_id << ".log"; 545 log_transaction_file_tgt.open(filename.str().c_str() ,std::ios::out | std::ios::trunc); 546 } 547 { 548 std::ostringstream filename(""); 549 filename << CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION_PATH << "/Transaction_cleanup-" << proc_id << ".log"; 550 log_transaction_file_cleanup.open(filename.str().c_str() ,std::ios::out | std::ios::trunc); 551 } 1737 if ( word < m_cache_words-1 ) 1738 { 1739 std::cout << " <PROC.DCACHE_MISS_UPDT> Matching coherence request:" 1740 << " pop the FIFO, don't update the cache" << std::endl; 1741 } 1742 else 1743 { 1744 std::cout << " <PROC.DCACHE_MISS_UPDT> Matching coherence request:" 1745 << " last word : send a cleanup request " << std::endl; 1746 } 1747 } 1748 else 1749 { 1750 std::cout << " <PROC.DCACHE_MISS_UPDT> Write one word:" 1751 << " address = " << addr 1752 << " / data = " << r_vci_rsp_fifo_dcache.read() 1753 << " / way = " << way 1754 << " / set = " << set 1755 << " / word = " << word << std::endl; 1756 } 1757 } 552 1758 #endif 553 554 #if MWBUF_VHDL_TESTBENCH 555 simulation_started = false; 556 557 vhdl_testbench_mwbuf = new std::ofstream [m_nb_dcache]; 558 for (uint32_t num_dcache=0; num_dcache<m_nb_dcache; ++num_dcache) 559 { 560 std::ostringstream filename(""); 561 filename << "VHDL_testbench_mwbuf-" << proc_id << "_" << num_dcache << ".txt"; 562 vhdl_testbench_mwbuf[num_dcache].open(filename.str().c_str() ,std::ios::out | std::ios::trunc); 563 564 vhdl_testbench_mwbuf[num_dcache] 565 << _wbuf_nlines << " " // nb_lines 566 << _wbuf_nwords << " " // nb_words 567 << m_nb_cpu << " " // nb_cpu 568 << 32 << " " // size_data 569 << 40 << " " // size_addr 570 << _dcache_words << std::endl; // cache_nb_words 571 } 572 #endif 573 } // end constructor 574 575 /////////////////////////////////// 576 tmpl(/**/)::~VciCcXCacheWrapperV4() 577 /////////////////////////////////// 578 { 579 #if MWBUF_VHDL_TESTBENCH 580 for (uint32_t num_dcache=0; num_dcache<m_nb_dcache; ++num_dcache) 581 vhdl_testbench_mwbuf[num_dcache].close(); 582 delete [] vhdl_testbench_mwbuf; 583 #endif 584 585 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 586 for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) 587 { 588 log_transaction_file_dcache[num_cpu].close(); 589 log_transaction_file_icache[num_cpu].close(); 590 } 591 delete [] log_transaction_file_dcache; 592 delete [] log_transaction_file_icache; 593 594 log_transaction_file_cmd .close(); 595 log_transaction_file_tgt .close(); 596 log_transaction_file_cleanup.close(); 597 #endif 598 599 delete [] m_stop_simulation_nb_frz_cycles; 600 601 602 delete [] r_icache_lock ; 603 delete [] r_dcache_lock ; 604 delete [] r_dcache_sync ; 605 606 delete [] r_icache_fsm ; 607 delete [] r_icache_fsm_save ; 608 delete [] r_icache_addr_save ; 609 delete [] r_icache_miss_req ; 610 delete [] r_icache_miss_way ; 611 delete [] r_icache_miss_set ; 612 delete [] r_icache_unc_req ; 613 delete [] r_icache_cleanup_req ; 614 delete [] r_icache_cleanup_line ; 615 delete [] r_icache_inval_rsp ; 616 delete [] r_icache_update_addr ; 617 delete [] r_icache_buf_unc_valid; 618 619 delete [] r_dcache_fsm ; 620 delete [] r_dcache_fsm_save ; 621 delete [] r_dcache_addr_save ; 622 delete [] r_dcache_wdata_save ; 623 delete [] r_dcache_rdata_save ; 624 delete [] r_dcache_type_save ; 625 delete [] r_dcache_be_save ; 626 delete [] r_dcache_cached_save ; 627 delete [] r_dcache_cleanup_req ; 628 delete [] r_dcache_cleanup_line ; 629 delete [] r_dcache_miss_req ; 630 delete [] r_dcache_miss_way ; 631 delete [] r_dcache_miss_set ; 632 delete [] r_dcache_unc_req ; 633 delete [] r_dcache_sc_req ; 634 delete [] r_dcache_inval_rsp ; 635 delete [] r_dcache_update_addr ; 636 delete [] r_dcache_previous_unc ; 637 638 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 639 { 640 delete [] r_dcache_ll_data [num_cache]; 641 delete [] r_dcache_ll_addr [num_cache]; 642 delete [] r_dcache_ll_valid [num_cache]; 643 } 644 delete [] r_dcache_num_cpu_save ; 645 delete [] r_dcache_ll_data ; 646 delete [] r_dcache_ll_addr ; 647 delete [] r_dcache_ll_valid ; 648 649 delete [] r_tgt_icache_req ; 650 delete [] r_tgt_icache_rsp ; 651 delete [] r_tgt_dcache_req ; 652 delete [] r_tgt_dcache_rsp ; 653 654 delete [] r_tgt_be ; 655 delete [] r_tgt_buf; 656 657 delete [] r_vci_rsp_ins_error ; 658 delete [] r_vci_rsp_data_error ; 659 660 delete [] ireq ; 661 delete [] irsp ; 662 delete [] ireq_cached ; 663 delete [] ireq_num_cpu ; 664 delete [] dreq ; 665 delete [] drsp ; 666 delete [] dreq_cached ; 667 delete [] dreq_num_cpu ; 668 669 delete [] m_cpt_frz_cycles; 670 671 delete [] m_cpt_icache_access ; 672 delete [] m_cpt_dcache_access ; 673 delete [] m_cpt_icache_miss_victim_wait; 674 delete [] m_cpt_dcache_miss_victim_wait; 675 delete [] m_cpt_dcache_store_after_store; 676 delete [] m_cpt_dcache_hit_after_miss_read; 677 delete [] m_cpt_dcache_hit_after_miss_write; 678 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 679 delete [] m_cpt_fsm_dcache [num_cache]; 680 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 681 delete [] m_cpt_fsm_icache [num_cache]; 682 683 delete [] m_cpt_fsm_dcache ; 684 delete [] m_cpt_fsm_icache ; 685 delete [] m_cpt_fsm_cmd ; 686 delete [] m_cpt_fsm_rsp ; 687 delete [] m_cpt_fsm_tgt ; 688 delete [] m_cpt_fsm_cleanup; 689 690 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 691 { 692 delete r_icache [num_cache]; 693 } 694 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 695 { 696 delete r_wbuf [num_cache]; 697 delete r_dcache [num_cache]; 698 } 699 delete [] r_wbuf; 700 delete [] r_icache; 701 delete [] r_dcache; 702 703 for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) 704 { 705 delete m_iss [num_cpu]; 706 delete [] p_irq [num_cpu]; 707 } 708 delete [] m_iss; 709 delete [] p_irq; 710 } 711 712 //////////////////////// 713 tmpl(void)::print_cpi() 714 //////////////////////// 715 { 716 for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) 717 std::cout << "CPU " << m_srcid_rw << " : CPI = " 718 << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles[num_cpu]) << std::endl ; 719 } 720 //////////////////////// 721 tmpl(void)::print_stats(bool print_wbuf, bool print_fsm) 722 //////////////////////// 723 { 724 uint32_t m_cpt_data_read_cached = m_cpt_data_read-m_cpt_data_read_uncached; 725 uint32_t m_cpt_data_write_cached = m_cpt_data_write-m_cpt_data_write_uncached; 726 std::cout << "------------------------------------" << std:: dec << std::endl; 727 std::cout << "CPU " << m_srcid_rw << " / Time = " << m_cpt_total_cycles << std::endl; 728 for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) 729 { 730 float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles[num_cpu]); 731 732 std::cout << "- CPI : [" << num_cpu << "] "<< (float)m_cpt_total_cycles/run_cycles << std::endl ; 733 std::cout << "- IPC : [" << num_cpu << "] "<< (float)run_cycles/m_cpt_total_cycles << std::endl ; 734 } 735 std::cout << "- DATA READ * : " << m_cpt_data_read << std::endl ; 736 std::cout << " + Uncached : " << m_cpt_data_read_uncached << " (" << (float)m_cpt_data_read_uncached*100.0/(float)m_cpt_data_read << "%)" << std::endl ; 737 std::cout << " + Cached and miss : " << m_cpt_data_read_miss << " (" << (float)m_cpt_data_read_miss*100.0/(float)m_cpt_data_read_cached << "%)" << std::endl; 738 std::cout << "- DATA WRITE * : " << m_cpt_data_write << std::endl ; 739 std::cout << " + Uncached : " << m_cpt_data_write_uncached << " (" << (float)m_cpt_data_write_uncached*100.0/(float)m_cpt_data_write << "%)" << std::endl ; 740 std::cout << " + Cached and miss : " << m_cpt_data_write_miss << " (" << (float)m_cpt_data_write_miss*100.0/(float)m_cpt_data_write_cached << "%)" << std::endl; 741 // std::cout << "- WRITE RATE : " << (float)m_cpt_data_write/run_cycles << std::endl; 742 // std::cout << "- UNCACHED READ RATE : " << (float)m_cpt_data_read_uncached/m_cpt_data_read << std::endl ; 743 // std::cout << "- CACHED WRITE RATE : " << (float)m_cpt_data_write_cached/m_cpt_data_write << std::endl ; 744 // std::cout << "- IMISS_RATE : " << (float)m_cpt_ins_miss/run_cycles << std::endl; 745 // std::cout << "- DMISS RATE : " << (float)m_cpt_data_miss/(m_cpt_data_read-m_cpt_data_read_uncached) << std::endl ; 746 // std::cout << "- INS MISS COST : " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl; 747 // std::cout << "- IMISS TRANSACTION : " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl; 748 // std::cout << "- DMISS COST : " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl; 749 // std::cout << "- DMISS TRANSACTION : " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl; 750 // std::cout << "- UNC COST : " << (float)m_cost_unc_read_frz/m_cpt_data_read_uncached << std::endl; 751 // std::cout << "- UNC TRANSACTION : " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl; 752 // std::cout << "- WRITE COST : " << (float)m_cost_write_frz/m_cpt_data_write << std::endl; 753 // std::cout << "- WRITE TRANSACTION : " << (float)m_cost_write_transaction/m_cpt_data_write_transaction << std::endl; 754 // std::cout << "- WRITE LENGTH : " << (float)m_length_write_transaction/m_cpt_data_write_transaction << std::endl; 755 756 std::cout << "- CC_UPDATE_ICACHE : " << m_cpt_cc_update_icache << std::endl; 757 std::cout << " + AVERAGE WORD USEFUL : " << (float)m_cpt_cc_update_icache_word_useful/(float)m_cpt_cc_update_icache << " on " << m_icache_words << " words" << std::endl; 758 std::cout << "- CC_UPDATE_DCACHE : " << m_cpt_cc_update_dcache << std::endl; 759 std::cout << " + AVERAGE WORD USEFUL : " << (float)m_cpt_cc_update_dcache_word_useful/(float)m_cpt_cc_update_dcache << " on " << m_dcache_words << " words" << std::endl; 760 uint32_t m_cpt_cc_inval = m_cpt_cc_inval_broadcast+m_cpt_cc_inval_icache+m_cpt_cc_inval_dcache; 761 std::cout << "- CC_INVALID : " << m_cpt_cc_inval << std::endl; 762 std::cout << " + ICACHE Only : " << (float)m_cpt_cc_inval_icache *100.0/(float)m_cpt_cc_inval << "%" << std::endl; 763 std::cout << " + DCACHE Only : " << (float)m_cpt_cc_inval_dcache *100.0/(float)m_cpt_cc_inval << "%" << std::endl; 764 std::cout << " + BROADCAST : " << (float)m_cpt_cc_inval_broadcast*100.0/(float)m_cpt_cc_inval << "%" << std::endl; 765 766 uint32_t m_cpt_icache_access_all = 0; 767 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 768 m_cpt_icache_access_all += m_cpt_icache_access [num_cache]; 769 770 std::cout << "- ICACHE ACCESS : " << m_cpt_icache_access_all << std::endl; 771 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 772 std::cout << " + [" << num_cache << "] : " << m_cpt_icache_access [num_cache] << " (" << (float)m_cpt_icache_access [num_cache]*100.0/(float)m_cpt_icache_access_all << "%)" << std::endl; 773 774 uint32_t m_cpt_dcache_access_all = 0; 775 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 776 m_cpt_dcache_access_all += m_cpt_dcache_access [num_cache]; 777 778 std::cout << "- DCACHE ACCESS : " << m_cpt_dcache_access_all << std::endl; 779 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 780 { 781 std::cout << " + [" << num_cache << "] : " << m_cpt_dcache_access [num_cache] << " (" << (float)m_cpt_dcache_access [num_cache]*100.0/(float)m_cpt_dcache_access_all << "%)"; 782 783 std::cout << " - store after store : " << m_cpt_dcache_store_after_store [num_cache]; 784 std::cout << " - Hit after Miss : Read " << m_cpt_dcache_hit_after_miss_read [num_cache] << ", Write " << m_cpt_dcache_hit_after_miss_write [num_cache]; 785 std::cout << std::endl; 786 } 787 788 uint32_t m_cpt_icache_miss_victim_wait_all = 0; 789 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 790 m_cpt_icache_miss_victim_wait_all += m_cpt_icache_miss_victim_wait [num_cache]; 791 std::cout << "- ICACHE MISS VICTIM WAIT : " << m_cpt_icache_miss_victim_wait_all << std::endl; 792 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 793 std::cout << " + [" << num_cache << "] : " << m_cpt_icache_miss_victim_wait [num_cache] << std::endl; 794 795 uint32_t m_cpt_dcache_miss_victim_wait_all = 0; 796 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 797 m_cpt_dcache_miss_victim_wait_all += m_cpt_dcache_miss_victim_wait [num_cache]; 798 std::cout << "- DCACHE MISS VICTIM WAIT : " << m_cpt_dcache_miss_victim_wait_all << std::endl; 799 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 800 std::cout << " + [" << num_cache << "] : " << m_cpt_dcache_miss_victim_wait [num_cache] << std::endl; 801 802 if (print_fsm) 803 { 804 std::cout << "- DCACHE FSM" << std::endl; 805 for (uint32_t i=0; i<soclib::common::size(dcache_fsm_state_str ); ++i) 806 { 807 std::cout << " + " << dcache_fsm_state_str[i] << " :\t "; 808 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 809 std::cout << m_cpt_fsm_dcache [num_cache][i] << ", "; 810 std::cout << std::endl; 811 } 812 std::cout << "- ICACHE FSM" << std::endl; 813 for (uint32_t i=0; i<soclib::common::size(icache_fsm_state_str ); ++i) 814 { 815 std::cout << " + " << icache_fsm_state_str[i] << " :\t "; 816 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 817 std::cout << m_cpt_fsm_icache [num_cache][i] << ", "; 818 std::cout << std::endl; 819 } 820 std::cout << "- CMD FSM" << std::endl; 821 for (uint32_t i=0; i<soclib::common::size(cmd_fsm_state_str ); ++i) 822 std::cout << " + " << cmd_fsm_state_str[i] << " :\t " << m_cpt_fsm_cmd [i] << std::endl; 823 std::cout << "- RSP FSM" << std::endl; 824 for (uint32_t i=0; i<soclib::common::size(rsp_fsm_state_str ); ++i) 825 std::cout << " + " << rsp_fsm_state_str[i] << " :\t " << m_cpt_fsm_rsp [i] << std::endl; 826 std::cout << "- TGT FSM" << std::endl; 827 for (uint32_t i=0; i<soclib::common::size(tgt_fsm_state_str ); ++i) 828 std::cout << " + " << tgt_fsm_state_str[i] << " :\t " << m_cpt_fsm_tgt [i] << std::endl; 829 std::cout << "- CLEANUP FSM" << std::endl; 830 for (uint32_t i=0; i<soclib::common::size(cleanup_fsm_state_str ); ++i) 831 std::cout << " + " << cleanup_fsm_state_str[i] << " :\t " << m_cpt_fsm_cleanup [i] << std::endl; 832 } 833 834 std::cout << "* : accepted or not by the cache" << std::endl ; 835 836 if (print_wbuf) 837 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 838 r_wbuf[num_cache]->printStatistics(); 839 } 840 841 //////////////////////////////////// 842 tmpl(void)::print_trace(size_t mode) 843 //////////////////////////////////// 844 { 845 // b0 : write buffer print trace 846 // b1 : write buffer verbose 847 // b2 : dcache print trace 848 // b3 : icache print trace 849 850 typename iss_t::InstructionRequest ireq; 851 typename iss_t::DataRequest dreq; 852 853 std::cout << std::dec << "Proc \"" << name() << "\"" << std::endl; 854 855 for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) 856 { 857 m_iss[num_cpu]->getRequests( ireq, dreq ); 858 std::cout << ireq << std::endl; 859 std::cout << dreq << std::endl; 860 } 861 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 862 std::cout << " " << icache_fsm_state_str[r_icache_fsm[num_cache]] << std::endl; 863 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 864 std::cout << " " << dcache_fsm_state_str[r_dcache_fsm[num_cache]] << std::endl; 865 866 std::cout << " " << cmd_fsm_state_str[r_vci_cmd_fsm] 867 << " " << rsp_fsm_state_str[r_vci_rsp_fsm] 868 << " " << tgt_fsm_state_str[r_vci_tgt_fsm] 869 << " " << cleanup_fsm_state_str[r_cleanup_fsm] << std::endl; 870 871 if(mode & 0x1) 872 { 873 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 874 r_wbuf[num_cache]->printTrace((mode>>1)&1); 875 } 876 if(mode & 0x4) 877 { 878 std::cout << " Data cache" << std::endl; 879 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 880 r_dcache[num_cache]->printTrace(); 881 } 882 if(mode & 0x8) 883 { 884 std::cout << " Instruction cache" << std::endl; 885 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 886 r_icache[num_cache]->printTrace(); 887 } 888 } 889 890 ////////////////////////// 891 tmpl(void)::transition() 892 ////////////////////////// 893 { 894 895 ///////////////////////////////////////////////////////////////////// 896 // Reset 897 ///////////////////////////////////////////////////////////////////// 898 899 if ( not p_resetn.read() ) { 900 901 r_cpu_prior = 0; 902 903 for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) 904 m_iss[num_cpu]->reset(); 905 906 // FSM states 907 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 908 { 909 r_icache_fsm [num_cache] = ICACHE_IDLE; 910 911 r_icache_lock[num_cache] = m_nb_cpu; 912 } 913 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 914 { 915 r_dcache_fsm [num_cache] = DCACHE_IDLE; 916 917 r_dcache_lock[num_cache] = m_nb_cpu; 918 r_dcache_sync[num_cache] = false; 919 } 920 921 r_vci_cmd_fsm = CMD_IDLE; 922 r_vci_rsp_fsm = RSP_IDLE; 923 r_vci_tgt_fsm = TGT_IDLE; 924 r_cleanup_fsm = CLEANUP_IDLE; 925 926 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 927 { 928 // write buffer & caches 929 r_icache[num_cache]->reset(); 930 931 // synchronisation flip-flops from ICACHE & DCACHE FSMs to VCI FSMs 932 r_icache_miss_req [num_cache] = false; 933 r_icache_unc_req [num_cache] = false; 934 r_icache_cleanup_req [num_cache] = false; 935 936 // internal messages in DCACHE et ICACHE FSMs 937 r_icache_inval_rsp [num_cache] = false; 938 939 // error signals from the VCI RSP FSM to the ICACHE or DCACHE FSMs 940 r_icache_buf_unc_valid [num_cache] = false; 941 942 // synchronisation flip-flops from TGT FSM to ICACHE & DCACHE FSMs 943 r_tgt_icache_req [num_cache] = false; 944 r_tgt_icache_rsp [num_cache] = false; 945 946 r_vci_rsp_ins_error [num_cache] = false; 947 }// end for num_cache 948 949 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 950 { 951 // write buffer & caches 952 r_wbuf [num_cache]->reset(); 953 r_dcache[num_cache]->reset(); 954 955 // synchronisation flip-flops from ICACHE & DCACHE FSMs to VCI FSMs 956 r_dcache_miss_req [num_cache] = false; 957 r_dcache_unc_req [num_cache] = false; 958 r_dcache_sc_req [num_cache] = false; 959 r_dcache_cleanup_req [num_cache] = false; 960 r_dcache_previous_unc[num_cache] = false; 961 962 // internal messages in DCACHE et ICACHE FSMs 963 r_dcache_inval_rsp [num_cache] = false; 964 965 // error signals from the VCI RSP FSM to the ICACHE or DCACHE FSMs 966 for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) 967 r_dcache_ll_valid [num_cache][num_cpu] = false; 968 969 // synchronisation flip-flops from TGT FSM to ICACHE & DCACHE FSMs 970 r_tgt_dcache_req [num_cache] = false; 971 r_tgt_dcache_rsp [num_cache] = false; 972 973 r_vci_rsp_data_error [num_cache] = false; 974 }// end for num_cache 975 976 r_cache_word = 0; 977 978 r_vci_cmd_dcache_prior = false; 979 r_vci_cmd_num_icache_prior = 0; 980 r_vci_cmd_num_dcache_prior = 0; 981 982 r_vci_rsp_fifo_icache_data .init(); 983 r_vci_rsp_fifo_icache_num_cache .init(); 984 r_vci_rsp_fifo_dcache_data .init(); 985 r_vci_rsp_fifo_dcache_num_cache .init(); 986 987 // activity counters 988 m_cpt_dcache_data_read = 0; 989 m_cpt_dcache_data_write = 0; 990 m_cpt_dcache_dir_read = 0; 991 m_cpt_dcache_dir_write = 0; 992 m_cpt_icache_data_read = 0; 993 m_cpt_icache_data_write = 0; 994 m_cpt_icache_dir_read = 0; 995 m_cpt_icache_dir_write = 0; 996 997 m_cpt_cc_update_icache = 0; 998 m_cpt_cc_update_dcache = 0; 999 m_cpt_cc_inval_broadcast = 0; 1000 m_cpt_cc_inval_icache = 0; 1001 m_cpt_cc_inval_dcache = 0; 1002 m_cpt_cc_update_icache_word_useful = 0; 1003 m_cpt_cc_update_dcache_word_useful = 0; 1004 1005 for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) 1006 m_cpt_frz_cycles [num_cpu] = 0; 1007 m_cpt_total_cycles = 0; 1008 1009 m_cpt_data_read = 0; 1010 m_cpt_data_read_miss = 0; 1011 m_cpt_data_read_uncached = 0; 1012 m_cpt_data_write = 0; 1013 m_cpt_data_write_miss = 0; 1014 m_cpt_data_write_uncached = 0; 1015 1016 m_cpt_ins_miss = 0; 1017 1018 m_cost_write_frz = 0; 1019 m_cost_data_miss_frz = 0; 1020 m_cost_unc_read_frz = 0; 1021 m_cost_ins_miss_frz = 0; 1022 1023 m_cpt_imiss_transaction = 0; 1024 m_cpt_dmiss_transaction = 0; 1025 m_cpt_unc_transaction = 0; 1026 m_cpt_data_write_transaction = 0; 1027 1028 m_cost_imiss_transaction = 0; 1029 m_cost_dmiss_transaction = 0; 1030 m_cost_unc_transaction = 0; 1031 m_cost_write_transaction = 0; 1032 m_length_write_transaction = 0; 1033 1034 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 1035 { 1036 m_cpt_icache_access [num_cache] = 0; 1037 m_cpt_icache_miss_victim_wait [num_cache] = 0; 1038 1039 for (uint32_t i=0; i<soclib::common::size(icache_fsm_state_str ); ++i) 1040 m_cpt_fsm_icache [num_cache][i] = 0; 1041 } 1042 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 1043 { 1044 m_cpt_dcache_access [num_cache] = 0; 1045 m_cpt_dcache_miss_victim_wait [num_cache] = 0; 1046 m_cpt_dcache_store_after_store [num_cache] = 0; 1047 m_cpt_dcache_hit_after_miss_read [num_cache] = 0; 1048 m_cpt_dcache_hit_after_miss_write [num_cache] = 0; 1049 for (uint32_t i=0; i<soclib::common::size(dcache_fsm_state_str ); ++i) 1050 m_cpt_fsm_dcache [num_cache][i] = 0; 1051 } 1052 1053 for (uint32_t i=0; i<soclib::common::size(cmd_fsm_state_str ); ++i) 1054 m_cpt_fsm_cmd [i] = 0; 1055 for (uint32_t i=0; i<soclib::common::size(rsp_fsm_state_str ); ++i) 1056 m_cpt_fsm_rsp [i] = 0; 1057 for (uint32_t i=0; i<soclib::common::size(tgt_fsm_state_str ); ++i) 1058 m_cpt_fsm_tgt [i] = 0; 1059 for (uint32_t i=0; i<soclib::common::size(cleanup_fsm_state_str); ++i) 1060 m_cpt_fsm_cleanup [i] = 0; 1061 1062 return; // reset is finish, quit the transition fonction 1063 } 1064 1065 bool vci_rsp_fifo_icache_get = false; 1066 bool vci_rsp_fifo_icache_put = false; 1067 data_t vci_rsp_fifo_icache_data = 0; 1068 uint32_t vci_rsp_fifo_icache_num_cache = 0; 1069 1070 bool vci_rsp_fifo_dcache_get = false; 1071 bool vci_rsp_fifo_dcache_put = false; 1072 data_t vci_rsp_fifo_dcache_data = 0; 1073 uint32_t vci_rsp_fifo_dcache_num_cache = 0; 1074 1075 ///////////////////////////////////////////////////////////////////// 1076 // VHDL TESTBENCH 1077 // Create and initialize variable 1078 ///////////////////////////////////////////////////////////////////// 1079 1080 #if MWBUF_VHDL_TESTBENCH 1081 simulation_started = true; 1082 1083 vhdl_tb_t vhdl_mwbuf_test_empty [m_nb_dcache]; 1084 vhdl_tb_t vhdl_mwbuf_port_empty [m_nb_dcache]; 1085 vhdl_tb_t vhdl_mwbuf_port_flush [m_nb_dcache]; 1086 vhdl_tb_t vhdl_mwbuf_port_write_val [m_nb_dcache]; 1087 vhdl_tb_t vhdl_mwbuf_test_write_ack [m_nb_dcache]; 1088 vhdl_tb_t vhdl_mwbuf_port_write_ack [m_nb_dcache]; 1089 vhdl_tb_t vhdl_mwbuf_port_write_addr [m_nb_dcache]; 1090 vhdl_tb_t vhdl_mwbuf_port_write_data [m_nb_dcache]; 1091 vhdl_tb_t vhdl_mwbuf_port_write_be [m_nb_dcache]; 1092 vhdl_tb_t vhdl_mwbuf_port_write_cached [m_nb_dcache]; 1093 vhdl_tb_t vhdl_mwbuf_port_write_cpu_id [m_nb_dcache]; 1094 vhdl_tb_t vhdl_mwbuf_test_sent_val [m_nb_dcache]; 1095 vhdl_tb_t vhdl_mwbuf_port_sent_val [m_nb_dcache]; 1096 vhdl_tb_t vhdl_mwbuf_port_sent_ack [m_nb_dcache]; 1097 vhdl_tb_t vhdl_mwbuf_test_sent_word_min [m_nb_dcache]; 1098 vhdl_tb_t vhdl_mwbuf_port_sent_word_min [m_nb_dcache]; 1099 vhdl_tb_t vhdl_mwbuf_test_sent_word_max [m_nb_dcache]; 1100 vhdl_tb_t vhdl_mwbuf_port_sent_word_max [m_nb_dcache]; 1101 vhdl_tb_t vhdl_mwbuf_port_sent_word [m_nb_dcache]; 1102 vhdl_tb_t vhdl_mwbuf_test_sent_addr [m_nb_dcache]; 1103 vhdl_tb_t vhdl_mwbuf_port_sent_addr [m_nb_dcache]; 1104 vhdl_tb_t vhdl_mwbuf_test_sent_data [m_nb_dcache]; 1105 vhdl_tb_t vhdl_mwbuf_port_sent_data [m_nb_dcache]; 1106 vhdl_tb_t vhdl_mwbuf_test_sent_be [m_nb_dcache]; 1107 vhdl_tb_t vhdl_mwbuf_port_sent_be [m_nb_dcache]; 1108 vhdl_tb_t vhdl_mwbuf_test_sent_index [m_nb_dcache]; 1109 vhdl_tb_t vhdl_mwbuf_port_sent_index [m_nb_dcache]; 1110 vhdl_tb_t vhdl_mwbuf_port_raw_test [m_nb_dcache]; 1111 vhdl_tb_t vhdl_mwbuf_port_raw_addr [m_nb_dcache]; 1112 vhdl_tb_t vhdl_mwbuf_test_raw_miss [m_nb_dcache]; 1113 vhdl_tb_t vhdl_mwbuf_port_raw_miss [m_nb_dcache]; 1114 vhdl_tb_t vhdl_mwbuf_port_completed_val [m_nb_dcache]; 1115 vhdl_tb_t vhdl_mwbuf_port_completed_index [m_nb_dcache]; 1116 vhdl_tb_t vhdl_mwbuf_test_completed_cached [m_nb_dcache]; 1117 vhdl_tb_t vhdl_mwbuf_port_completed_cached [m_nb_dcache]; 1118 vhdl_tb_t vhdl_mwbuf_test_completed_cpu_id [m_nb_dcache]; 1119 vhdl_tb_t vhdl_mwbuf_port_completed_cpu_id [m_nb_dcache]; 1120 1121 for (uint32_t num_dcache=0; num_dcache<m_nb_dcache; ++num_dcache) 1122 { 1123 vhdl_mwbuf_test_empty [num_dcache] = 0; 1124 vhdl_mwbuf_port_empty [num_dcache] = 0; 1125 vhdl_mwbuf_port_flush [num_dcache] = 0; 1126 vhdl_mwbuf_port_write_val [num_dcache] = 0; 1127 vhdl_mwbuf_test_write_ack [num_dcache] = 0; 1128 vhdl_mwbuf_port_write_ack [num_dcache] = 0; 1129 vhdl_mwbuf_port_write_addr [num_dcache] = 0; 1130 vhdl_mwbuf_port_write_data [num_dcache] = 0; 1131 vhdl_mwbuf_port_write_be [num_dcache] = 0; 1132 vhdl_mwbuf_port_write_cached [num_dcache] = 0; 1133 vhdl_mwbuf_port_write_cpu_id [num_dcache] = 0; 1134 vhdl_mwbuf_test_sent_val [num_dcache] = 0; 1135 vhdl_mwbuf_port_sent_val [num_dcache] = 0; 1136 vhdl_mwbuf_port_sent_ack [num_dcache] = 0; 1137 vhdl_mwbuf_test_sent_word_min [num_dcache] = 0; 1138 vhdl_mwbuf_port_sent_word_min [num_dcache] = 0; 1139 vhdl_mwbuf_test_sent_word_max [num_dcache] = 0; 1140 vhdl_mwbuf_port_sent_word_max [num_dcache] = 0; 1141 vhdl_mwbuf_port_sent_word [num_dcache] = 0; 1142 vhdl_mwbuf_test_sent_addr [num_dcache] = 0; 1143 vhdl_mwbuf_port_sent_addr [num_dcache] = 0; 1144 vhdl_mwbuf_test_sent_data [num_dcache] = 0; 1145 vhdl_mwbuf_port_sent_data [num_dcache] = 0; 1146 vhdl_mwbuf_test_sent_be [num_dcache] = 0; 1147 vhdl_mwbuf_port_sent_be [num_dcache] = 0; 1148 vhdl_mwbuf_test_sent_index [num_dcache] = 0; 1149 vhdl_mwbuf_port_sent_index [num_dcache] = 0; 1150 vhdl_mwbuf_port_raw_test [num_dcache] = 0; 1151 vhdl_mwbuf_port_raw_addr [num_dcache] = 0; 1152 vhdl_mwbuf_test_raw_miss [num_dcache] = 0; 1153 vhdl_mwbuf_port_raw_miss [num_dcache] = 0; 1154 vhdl_mwbuf_port_completed_val [num_dcache] = 0; 1155 vhdl_mwbuf_port_completed_index [num_dcache] = 0; 1156 vhdl_mwbuf_test_completed_cached [num_dcache] = 0; 1157 vhdl_mwbuf_port_completed_cached [num_dcache] = 0; 1158 vhdl_mwbuf_test_completed_cpu_id [num_dcache] = 0; 1159 vhdl_mwbuf_port_completed_cpu_id [num_dcache] = 0; 1160 } 1161 #endif 1162 1163 ///////////////////////////////////////////////////////////////////// 1164 // DEBUG : 1165 // print state of all fsm and main register 1166 ///////////////////////////////////////////////////////////////////// 1167 1168 // printf("%d\n",(uint32_t)m_cpt_total_cycles); 1169 1170 PRINTF("--------------------------------------------\n"); 1171 PRINTF(" * CC_XCACHE_WRAPPER \"%s\" Transition - Time = %d\n",name().c_str(),(uint32_t)m_cpt_total_cycles); 1172 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 1173 PRINTF(" * fsm dcache = [%.2d] %s - (%.2d) %llx (%llx)\n",num_cache,dcache_fsm_state_str[r_dcache_fsm[num_cache]],r_dcache_lock[num_cache].read(),(blob_t)r_dcache_addr_save[num_cache].read(),(blob_t)set_num_dcache_only(r_dcache_addr_save[num_cache].read(),num_cache)); 1174 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 1175 PRINTF(" * fsm icache = [%.2d] %s - (%.2d) %llx (%llx)\n",num_cache,icache_fsm_state_str[r_icache_fsm[num_cache]],r_icache_lock[num_cache].read(),(blob_t)r_icache_addr_save[num_cache].read(),(blob_t)set_num_icache_only(r_icache_addr_save[num_cache].read(),num_cache)); 1176 PRINTF(" * fsm cmd = (%.2d) %s\n",r_vci_cmd_num_cache.read(), cmd_fsm_state_str[r_vci_cmd_fsm]); 1177 PRINTF(" * fsm rsp = (%.2d) %s\n",r_vci_rsp_num_cache.read(), rsp_fsm_state_str[r_vci_rsp_fsm]); 1178 PRINTF(" * fsm tgt = (%.2d) %s - i %llx d %llx\n",r_tgt_num_cache.read(), tgt_fsm_state_str[r_vci_tgt_fsm],(blob_t)r_tgt_iaddr.read(),(blob_t)r_tgt_daddr.read()); 1179 //PRINTF(" * fsm tgt = %s - %llx\n",tgt_fsm_state_str[r_vci_tgt_fsm],(blob_t)r_tgt_addr.read()); 1180 PRINTF(" * fsm cleanup = (%.2d) %s\n",r_cleanup_num_cache.read(), cleanup_fsm_state_str[r_cleanup_fsm]); 1181 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 1182 { 1183 for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) 1184 PRINTF(" * ll info : [%.2d][%.2d] %d %llx (%llx) %llx\n" 1185 ,num_cache 1186 ,num_cpu 1187 , r_dcache_ll_valid [num_cache][num_cpu].read() 1188 ,(blob_t)r_dcache_ll_addr [num_cache][num_cpu].read() 1189 ,(blob_t)set_num_dcache_only(r_dcache_ll_addr [num_cache][num_cpu].read(),num_cache) 1190 ,(blob_t)r_dcache_ll_data [num_cache][num_cpu].read()); 1191 1192 PRINTF(" * dcache_previous_unc : [%.2d] %d\n",num_cache,r_dcache_previous_unc[num_cache].read()); 1193 1194 #if CC_XCACHE_WRAPPER_DEBUG 1195 if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN) 1196 r_wbuf[num_cache]->printTrace(1); 1197 #endif 1198 1199 // VHDL debug 1200 // #if MWBUF_VHDL_TESTBENCH 1201 // printf("\nMWBUF[%d] - Time = %d\n\n",num_cache,(uint32_t)m_cpt_total_cycles); 1202 // r_wbuf[num_cache]->printTrace(1); 1203 // #endif 1204 } 1205 #if CC_XCACHE_WRAPPER_DEBUG 1206 if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN) 1207 { 1208 PRINTF(" * rsp_fifo_icache %s\n",name().c_str()); 1209 r_vci_rsp_fifo_icache_data .print(); 1210 r_vci_rsp_fifo_icache_num_cache.print(); 1211 PRINTF(" * rsp_fifo_dcache %s\n",name().c_str()); 1212 r_vci_rsp_fifo_dcache_data .print(); 1213 r_vci_rsp_fifo_dcache_num_cache.print(); 1214 } 1215 #endif 1216 1217 ///////////////////////////////////////////////////////////////////// 1218 // Statistics 1219 // Count state fsm activity 1220 ///////////////////////////////////////////////////////////////////// 1221 1222 1223 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 1224 m_cpt_fsm_dcache [num_cache][r_dcache_fsm[num_cache]] ++; 1225 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 1226 m_cpt_fsm_icache [num_cache][r_icache_fsm[num_cache]] ++; 1227 m_cpt_fsm_cmd [r_vci_cmd_fsm] ++; 1228 m_cpt_fsm_rsp [r_vci_rsp_fsm] ++; 1229 m_cpt_fsm_tgt [r_vci_tgt_fsm] ++; 1230 m_cpt_fsm_cleanup [r_cleanup_fsm] ++; 1231 1232 m_cpt_total_cycles++; 1233 1234 ///////////////////////////////////////////////////////////////////// 1235 // The TGT_FSM controls the following ressources: 1236 // - r_vci_tgt_fsm 1237 // - r_tgt_buf[nwords] 1238 // - r_tgt_be[nwords] 1239 // - r_tgt_update 1240 // - r_tgt_word 1241 // - r_tgt_addr 1242 // - r_tgt_srcid 1243 // - r_tgt_trdid 1244 // - r_tgt_pktid 1245 // All VCI commands must be CMD_WRITE. 1246 // If the VCI address offset is null, the command is an invalidate 1247 // request. It is an update request otherwise. 1248 // The VCI_TGT FSM stores the external request arguments in the 1249 // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req 1250 // & r_tgt_dcache_req flip-flops to signal the external request to 1251 // the ICACHE & DCACHE FSMs in the REQ state. It waits the completion 1252 // of the update or invalidate request in the RSP state. 1253 // - for an invalidate request the VCI packet length is 1 word. 1254 // The WDATA field contains the line index (i.e. the Z & Y fields). 1255 // - for an update request the VCI packet length is (n+2) words. 1256 // The WDATA field of the first VCI word contains the line number. 1257 // The WDATA field of the second VCI word contains the word index. 1258 // The WDATA field of the n following words contains the values. 1259 // - for both invalidate & update requests, the VCI response 1260 // is one single word. 1261 // In case of errors in the VCI command packet, the simulation 1262 // is stopped with an error message. 1263 ///////////////////////////////////////////////////////////////////// 1264 1265 switch(r_vci_tgt_fsm) { 1266 1267 case TGT_IDLE: 1268 if ( p_vci_tgt.cmdval.read() ) 1269 { 1270 PRINTF(" * <TGT> Request\n"); 1271 1272 addr_40 address = p_vci_tgt.address.read(); 1273 1274 if ( p_vci_tgt.cmd.read() != vci_param::CMD_WRITE) 1759 } 1760 break; 1761 } 1762 ///////////////////// 1763 case DCACHE_UNC_WAIT: // Waiting the response to an uncached request 1764 { 1765 if ( r_tgt_dcache_req ) // coherence request 1766 { 1767 r_dcache_fsm = DCACHE_CC_CHECK; 1768 r_dcache_fsm_save = r_dcache_fsm; 1769 break; 1770 } 1771 1772 if ( r_vci_rsp_data_error ) 1773 { 1774 r_dcache_fsm = DCACHE_ERROR; 1775 } 1776 else if ( r_vci_rsp_fifo_dcache.rok() ) 1777 { 1778 vci_rsp_fifo_dcache_get = true; 1779 r_dcache_unc_valid = true; 1780 r_dcache_unc_buf = r_vci_rsp_fifo_dcache.read(); 1781 r_dcache_fsm = DCACHE_IDLE; 1782 } 1783 break; 1784 } 1785 ////////////////// 1786 case DCACHE_ERROR: // signal a read bus error to the processor 1787 { 1788 r_dcache_fsm = DCACHE_IDLE; 1789 r_vci_rsp_data_error = false; 1790 drsp.error = true; 1791 drsp.valid = true; 1792 break; 1793 } 1794 ////////////////// 1795 case DCACHE_INVAL: // XTN inval is done in two cycles 1796 // In this state we test the cache hit 1797 { 1798 uint32_t data; // unused 1799 size_t word; // unused 1800 size_t way; 1801 size_t set; 1802 bool hit = r_dcache->read( r_dcache_wdata_save.read(), 1803 &data, 1804 &way, 1805 &set, 1806 &word ); 1807 if ( hit ) // inval to be done 1808 { 1809 r_dcache_way_save = way; 1810 r_dcache_set_save = set; 1811 r_dcache_fsm = DCACHE_INVAL_GO; 1812 } 1813 else // nothing to do 1814 { 1815 drsp.valid = true; 1816 r_dcache_fsm = DCACHE_IDLE; 1817 } 1818 break; 1819 } 1820 ///////////////////// 1821 case DCACHE_INVAL_GO: // XTN inval is done in two cycles 1822 // In this state we wait to post a cleanup request 1823 // and make the inval when cleanup is possible 1824 { 1825 1826 if ( r_tgt_dcache_req ) // coherence request 1827 { 1828 r_dcache_fsm = DCACHE_CC_CHECK; 1829 r_dcache_fsm_save = r_dcache_fsm; 1830 break; 1831 } 1832 1833 if ( not r_dcache_cleanup_req .read() ) 1834 { 1835 vci_addr_t nline; 1836 r_dcache_cleanup_req = r_dcache->inval( r_dcache_way_save.read(), 1837 r_dcache_set_save.read(), 1838 &nline ); 1839 1840 r_dcache_cleanup_line = r_dcache_wdata_save.read() >> m_cache_words_shift; 1841 r_dcache_fsm = DCACHE_IDLE; 1842 drsp.valid = true; 1843 } 1844 break; 1845 } 1846 ///////////////// 1847 case DCACHE_SYNC: // waiting until the write buffer is empty 1848 { 1849 if ( r_tgt_dcache_req ) // coherence request 1850 { 1851 r_dcache_fsm = DCACHE_CC_CHECK; 1852 r_dcache_fsm_save = r_dcache_fsm; 1853 break; 1854 } 1855 1856 if ( r_wbuf->empty() ); 1857 { 1858 drsp.valid = true; 1859 r_dcache_fsm = DCACHE_IDLE; 1860 } 1861 break; 1862 } 1863 ///////////////////// 1864 case DCACHE_CC_CHECK: // read directory in case of coherence request 1865 { 1866 vci_addr_t addr = r_tgt_addr.read(); 1867 vci_addr_t mask = ~((m_cache_words<<2)-1); 1868 1869 if( (r_dcache_fsm_save.read() == DCACHE_MISS_WAIT) and 1870 ((r_dcache_addr_save.read() & mask) == (addr & mask)) ) 1871 // The coherence request matches a pending miss 1872 { 1873 r_dcache_miss_inval = true; 1874 r_tgt_dcache_req = false; 1875 r_tgt_dcache_rsp = r_tgt_update.read(); 1876 r_dcache_fsm = r_dcache_fsm_save.read(); 1877 } 1878 else // no match for a pending miss 1879 { 1880 size_t way; 1881 size_t set; 1882 size_t word; 1883 bool hit = r_dcache->hit( addr, 1884 &way, 1885 &set, 1886 &word ); 1887 r_dcache_cc_way = way; 1888 r_dcache_cc_set = set; 1889 1890 m_conso_dcache_dir_read++; 1891 1892 if ( hit and r_tgt_update.read() ) // hit update 1893 { 1894 r_dcache_fsm = DCACHE_CC_UPDT; 1895 r_dcache_update_word = r_tgt_word_min.read(); 1896 } 1897 else if (hit and not r_tgt_update.read() ) // hit inval 1898 { 1899 r_dcache_fsm = DCACHE_CC_INVAL; 1900 } 1901 else // miss can happen 1902 { 1903 r_tgt_dcache_req = false; 1904 r_tgt_dcache_rsp = r_tgt_update.read(); 1905 r_dcache_fsm = r_dcache_fsm_save.read(); 1906 } 1907 } 1908 break; 1909 } 1910 ///////////////////// 1911 case DCACHE_CC_INVAL: 1912 { 1913 vci_addr_t nline; 1914 r_dcache->inval( r_dcache_cc_way.read(), 1915 r_dcache_cc_set.read(), 1916 &nline ); 1917 r_tgt_dcache_req = false; 1918 r_tgt_dcache_rsp = true; 1919 r_dcache_fsm = r_dcache_fsm_save.read(); 1920 break; 1921 } 1922 //////////////////// 1923 case DCACHE_CC_UPDT: 1924 { 1925 size_t word = r_dcache_update_word.read(); 1926 r_dcache->write( r_dcache_cc_way.read(), 1927 r_dcache_cc_set.read(), 1928 word, 1929 r_tgt_buf[ word].read(), 1930 r_tgt_be[word].read() ); 1931 1932 r_dcache_update_word = word+1; 1933 if ( word == r_tgt_word_max.read() ) // last word 1275 1934 { 1276 std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl; 1277 std::cout << "coherence request is not a write" << std::endl; 1278 std::cout << "address = " << std::hex << address << std::dec << std::endl; 1279 std::cout << "srcid = " << p_vci_tgt.srcid.read() << std::endl; 1280 exit(0); 1281 } 1282 1283 // multi-update or multi-invalidate for data type 1284 if ( ((address&0x3) != 0x3) and (not m_segment.contains(address)) ) 1285 { 1286 std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl; 1287 std::cout << "out of segment coherence request" << std::endl; 1288 std::cout << "address = " << std::hex << address << std::dec << std::endl; 1289 std::cout << "srcid = " << p_vci_tgt.srcid.read() << std::endl; 1290 exit(0); 1291 } 1292 1293 addr_40 tgt_addr = ((((addr_40)p_vci_tgt.be.read() & 0x3) << 32) | ((addr_40) p_vci_tgt.wdata.read())) << (addr_40)m_dcache_words_shift; 1294 // * m_dcache_words * 4; 1295 1296 addr_40 tgt_iaddr = tgt_addr; 1297 addr_40 tgt_daddr = tgt_addr; 1298 1299 PRINTF(" * <TGT> srcid : %d\n",(uint32_t)p_vci_tgt.srcid.read()); 1300 PRINTF(" * <TGT> trdid : %d\n",(uint32_t)p_vci_tgt.trdid.read()); 1301 PRINTF(" * <TGT> pktid : %d\n",(uint32_t)p_vci_tgt.pktid.read()); 1302 PRINTF(" * <TGT> address (before) : %llx\n",(blob_t)tgt_iaddr); 1303 1304 r_tgt_srcid = p_vci_tgt.srcid.read(); 1305 r_tgt_trdid = p_vci_tgt.trdid.read(); 1306 r_tgt_pktid = p_vci_tgt.pktid.read(); 1307 // r_tgt_plen = p_vci_tgt.plen.read(); 1308 1309 // BROADCAST 1310 if ( (address&0x3) == 0x3 ) // broadcast invalidate for data or instruction type 1311 { 1312 if ( not p_vci_tgt.eop.read() ) 1313 { 1314 std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl; 1315 std::cout << "the BROADCAST INVALIDATE command length must be one word" << std::endl; 1316 exit(0); 1317 } 1318 r_tgt_update = false; 1319 // r_tgt_brdcast= true; 1320 r_vci_tgt_fsm = TGT_REQ_BROADCAST; 1321 uint32_t tgt_num_cache; 1322 tgt_num_cache = get_num_icache(tgt_iaddr,0); // none effect (else CC_XCACHE_WRAPPER_MULTI_CACHE==1) 1323 tgt_num_cache = get_num_dcache(tgt_daddr); 1324 r_tgt_num_cache = tgt_num_cache; 1325 1326 PRINTF(" * <TGT> REQ_BROADCAST\n"); 1327 PRINTF(" * <TGT> num_cache (data) : %d\n",tgt_num_cache); 1328 1329 m_cpt_cc_inval_broadcast++ ; 1330 1331 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 1332 if (generate_log_transaction_file_tgt) 1333 { 1334 log_transaction_file_tgt 1335 << "[" << m_cpt_total_cycles << "] " 1336 << "BROADCAST " 1337 << std::hex 1338 << " L " << std::setw(10) << (blob_t)tgt_addr 1339 << std::dec 1340 << " - " << tgt_num_cache 1341 << std::endl; 1342 } 1343 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 1344 1345 } 1346 else // multi-update or multi-invalidate for data type 1347 { 1348 uint32_t cell = address - m_segment.baseAddress(); // addr_40 1349 // r_tgt_brdcast = false; 1350 1351 if (cell == 0) 1352 { // invalidate data 1353 if ( not p_vci_tgt.eop.read() ) 1354 { 1355 std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl; 1356 std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl; 1357 exit(0); 1358 } 1359 r_tgt_update = false; 1360 r_vci_tgt_fsm = TGT_REQ_DCACHE; 1361 uint32_t tgt_num_cache = get_num_dcache(tgt_daddr); // static partionnement 1362 r_tgt_num_cache = tgt_num_cache; 1363 1364 PRINTF(" * <TGT> REQ_DCACHE\n"); 1365 PRINTF(" * <TGT> num_cache : %d\n",tgt_num_cache); 1366 1367 m_cpt_cc_inval_dcache++ ; 1368 1369 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 1370 if (generate_log_transaction_file_tgt) 1371 { 1372 log_transaction_file_tgt 1373 << "[" << m_cpt_total_cycles << "] " 1374 << "INVAL DATA " 1375 << std::hex 1376 << " L " << std::setw(10) << (blob_t)tgt_addr 1377 << std::dec 1378 << " - " << tgt_num_cache 1379 << std::endl; 1380 } 1381 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 1382 1383 } 1384 else if (cell == 4) // invalidate instruction 1385 { 1386 if ( not p_vci_tgt.eop.read() ) 1387 { 1388 std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl; 1389 std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl; 1390 exit(0); 1391 } 1392 r_tgt_update = false; 1393 r_vci_tgt_fsm = TGT_REQ_ICACHE; 1394 uint32_t tgt_num_cpu = p_vci_tgt.pktid.read(); 1395 uint32_t tgt_num_cache = get_num_icache(tgt_iaddr,tgt_num_cpu); 1396 r_tgt_num_cache = tgt_num_cache; 1397 1398 PRINTF(" * <TGT> REQ_ICACHE\n"); 1399 PRINTF(" * <TGT> num_cache : %d\n",tgt_num_cache); 1400 1401 m_cpt_cc_inval_icache++ ; 1402 1403 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 1404 if (generate_log_transaction_file_tgt) 1405 { 1406 log_transaction_file_tgt 1407 << "[" << m_cpt_total_cycles << "] " 1408 << "INVAL INS " 1409 << std::hex 1410 << " L " << std::setw(10) << (blob_t)tgt_addr 1411 << std::dec 1412 << " - " << tgt_num_cache 1413 << std::endl; 1414 } 1415 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 1416 1417 } 1418 else if ( (cell == 8) or (cell==12) ) // update data or instruction 1419 { 1420 if ( p_vci_tgt.eop.read() ) 1421 { 1422 std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl; 1423 std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl; 1424 exit(0); 1425 } 1426 if(cell == 8) 1427 { 1428 m_cpt_cc_update_dcache++; 1429 r_tgt_update_data = true; 1430 1431 uint32_t tgt_num_cache = get_num_dcache(tgt_daddr); 1432 r_tgt_num_cache = tgt_num_cache; 1433 1434 PRINTF(" * <TGT> UPDT_WORD DATA\n"); 1435 PRINTF(" * <TGT> num_cache : %d\n",tgt_num_cache); 1436 1437 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 1438 if (generate_log_transaction_file_tgt) 1439 { 1440 log_transaction_file_tgt 1441 << "[" << m_cpt_total_cycles << "] " 1442 << "UPT DATA " 1443 << std::hex 1444 << " L " << std::setw(10) << (blob_t)tgt_addr 1445 << std::dec 1446 << " - " << tgt_num_cache 1447 << std::endl; 1448 } 1449 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 1450 } 1451 else 1452 { 1453 m_cpt_cc_update_icache++; 1454 r_tgt_update_data = false; 1455 1456 uint32_t tgt_num_cpu = p_vci_tgt.pktid.read(); 1457 uint32_t tgt_num_cache = get_num_icache(tgt_iaddr,tgt_num_cpu); 1458 r_tgt_num_cache = tgt_num_cache; 1459 1460 PRINTF(" * <TGT> UPDT_WORD INSTRUCTION\n"); 1461 PRINTF(" * <TGT> num_cache : %d\n",tgt_num_cache); 1462 1463 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 1464 if (generate_log_transaction_file_tgt) 1465 { 1466 log_transaction_file_tgt 1467 << "[" << m_cpt_total_cycles << "] " 1468 << "UPT INS " 1469 << std::hex 1470 << " L " << std::setw(10) << (blob_t)tgt_addr 1471 << std::dec 1472 << " - " << tgt_num_cache 1473 << std::endl; 1474 } 1475 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 1476 } 1477 r_tgt_update = true; 1478 r_vci_tgt_fsm = TGT_UPDT_WORD; 1479 } 1480 1481 } // end if address 1482 1483 r_tgt_iaddr = tgt_iaddr; 1484 r_tgt_daddr = tgt_daddr; 1485 PRINTF(" * <TGT> address (after) : i %llx, d %llx\n",(blob_t)tgt_iaddr,(blob_t)tgt_daddr); 1486 1487 } // end if cmdval 1488 break; 1489 1490 case TGT_UPDT_WORD: 1491 if (p_vci_tgt.cmdval.read()) 1492 { 1493 if ( p_vci_tgt.eop.read() ) 1494 { 1495 std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl; 1496 std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl; 1497 exit(0); 1498 } 1499 for ( size_t i=0 ; i<m_dcache_words ; i++ ) r_tgt_be[i] = 0; 1500 r_tgt_word = p_vci_tgt.wdata.read(); // the first modified word index 1501 r_vci_tgt_fsm = TGT_UPDT_DATA; 1502 } 1503 break; 1504 1505 case TGT_UPDT_DATA: 1506 if (p_vci_tgt.cmdval.read()) 1507 { 1508 size_t word = r_tgt_word.read(); 1509 if ( word >= m_cache_words ) 1510 { 1511 std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl; 1512 std::cout << "the reveived MULTI-UPDATE command length is wrong" << std::endl; 1513 exit(0); 1514 } 1515 1516 r_tgt_buf[word] = p_vci_tgt.wdata.read(); 1517 r_tgt_be [word] = p_vci_tgt.be.read(); 1518 1519 if (p_vci_tgt.be.read()) 1520 { 1521 if(r_tgt_update_data.read()) 1522 m_cpt_cc_update_dcache_word_useful++ ; 1523 else 1524 m_cpt_cc_update_icache_word_useful++ ; 1525 } 1526 1527 r_tgt_word = word + 1; 1528 if (p_vci_tgt.eop.read()){ 1529 1530 uint32_t word=0; 1531 for (; word<m_cache_words; ++word) 1532 if (r_tgt_be[word] != 0) 1533 break; 1534 r_cache_word = word; 1535 1536 if(r_tgt_update_data.read()){ 1537 r_vci_tgt_fsm = TGT_REQ_DCACHE; 1538 } else { 1539 r_vci_tgt_fsm = TGT_REQ_ICACHE; 1540 } 1541 } 1542 } 1543 break; 1544 1545 case TGT_REQ_BROADCAST: 1546 { 1547 bool tgt_icache_req; 1548 1549 #if (CC_XCACHE_WRAPPER_MULTI_CACHE==1) 1550 tgt_icache_req = r_tgt_icache_req[r_tgt_num_cache].read(); 1551 #elif (CC_XCACHE_WRAPPER_MULTI_CACHE==2) 1552 tgt_icache_req = false; 1553 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 1554 tgt_icache_req |= r_tgt_icache_req[num_cache].read(); 1555 #endif 1556 if (not tgt_icache_req and not r_tgt_dcache_req[r_tgt_num_cache].read()) 1557 { 1558 r_vci_tgt_fsm = TGT_RSP_BROADCAST; 1559 1560 #if (CC_XCACHE_WRAPPER_MULTI_CACHE==1) 1561 r_tgt_icache_req[r_tgt_num_cache] = true; 1562 #elif (CC_XCACHE_WRAPPER_MULTI_CACHE==2) 1563 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 1564 r_tgt_icache_req[ num_cache] = true; 1565 #endif 1566 1567 r_tgt_dcache_req[r_tgt_num_cache] = true; 1568 } 1569 } 1570 break; 1571 //////////////////// 1572 case TGT_REQ_ICACHE: 1573 { 1574 // Request treated by the icache 1575 if ( not r_tgt_icache_req[r_tgt_num_cache].read() ) 1576 { 1577 r_vci_tgt_fsm = TGT_RSP_ICACHE; 1578 r_tgt_icache_req[r_tgt_num_cache] = true; 1579 } 1580 break; 1581 } 1582 1583 case TGT_REQ_DCACHE: 1584 { 1585 // Request treated by the dcache 1586 1587 if ( not r_tgt_dcache_req[r_tgt_num_cache].read() ) 1588 { 1589 r_vci_tgt_fsm = TGT_RSP_DCACHE; 1590 r_tgt_dcache_req[r_tgt_num_cache] = true; 1591 } 1592 break; 1593 } 1594 case TGT_RSP_BROADCAST: 1595 { 1596 PRINTF(" * <TGT> dcache[%d] : %d - %d\n",(uint32_t)r_tgt_num_cache, (uint32_t)r_tgt_dcache_req[r_tgt_num_cache].read(),(uint32_t)r_tgt_dcache_rsp[r_tgt_num_cache].read()); 1597 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 1598 PRINTF(" * <TGT> icache[%d] : %d - %d\n",(uint32_t)num_cache, (uint32_t)r_tgt_icache_req[num_cache].read(),(uint32_t)r_tgt_icache_rsp[num_cache].read()); 1599 1600 bool tgt_icache_req; 1601 1602 #if (CC_XCACHE_WRAPPER_MULTI_CACHE==1) 1603 tgt_icache_req = r_tgt_icache_req[r_tgt_num_cache].read(); 1604 #elif (CC_XCACHE_WRAPPER_MULTI_CACHE==2) 1605 tgt_icache_req = false; 1606 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 1607 tgt_icache_req |= r_tgt_icache_req[num_cache].read(); 1608 #endif 1609 if (not tgt_icache_req and not r_tgt_dcache_req[r_tgt_num_cache].read()) 1610 { 1611 bool tgt_icache_rsp; 1612 uint32_t tgt_icache_rsp_num_cache; 1613 1614 #if (CC_XCACHE_WRAPPER_MULTI_CACHE==1) 1615 tgt_icache_rsp_num_cache = r_tgt_num_cache; 1616 tgt_icache_rsp = r_tgt_icache_rsp[r_tgt_num_cache].read(); 1617 #elif (CC_XCACHE_WRAPPER_MULTI_CACHE==2) 1618 tgt_icache_rsp_num_cache = 0; 1619 for (;tgt_icache_rsp_num_cache<m_nb_icache; ++tgt_icache_rsp_num_cache) 1620 { 1621 PRINTF(" * <TGT> icache[%d] : %d\n",(uint32_t)tgt_icache_rsp_num_cache, (uint32_t)r_tgt_icache_rsp[tgt_icache_rsp_num_cache].read()); 1622 1623 if (r_tgt_icache_rsp[tgt_icache_rsp_num_cache].read()) 1624 break; 1625 } 1626 1627 tgt_icache_rsp = (tgt_icache_rsp_num_cache<m_nb_icache); 1628 #endif 1629 1630 PRINTF(" * <TGT> icache_rsp [%d] : %d\n",tgt_icache_rsp_num_cache,(uint32_t) tgt_icache_rsp); 1631 PRINTF(" * <TGT> dcache_rsp [%d] : %d\n",(uint32_t)r_tgt_num_cache,(uint32_t) r_tgt_dcache_rsp[r_tgt_num_cache]); 1632 1633 if (tgt_icache_rsp or r_tgt_dcache_rsp[r_tgt_num_cache]) 1634 { 1635 // Have send one response 1636 if ( p_vci_tgt.rspack.read()) 1637 { 1638 // reset dcache if activated 1639 if (r_tgt_dcache_rsp[r_tgt_num_cache]) 1640 r_tgt_dcache_rsp[r_tgt_num_cache] = false; 1641 else 1642 // reset one icache 1643 r_tgt_icache_rsp[tgt_icache_rsp_num_cache] = false; 1644 } 1645 } 1646 1647 // // one response 1648 // if ( not r_tgt_icache_rsp[r_tgt_num_cache] or not r_tgt_dcache_rsp[r_tgt_num_cache] ) 1649 // { 1650 // if ( p_vci_tgt.rspack.read() ) 1651 // { 1652 // r_vci_tgt_fsm = TGT_IDLE; 1653 // r_tgt_icache_rsp[r_tgt_num_cache] = false; 1654 // r_tgt_dcache_rsp[r_tgt_num_cache] = false; 1655 // } 1656 // } 1657 1658 // // if data and instruction have the inval line, need two responses 1659 // if ( r_tgt_icache_rsp[r_tgt_num_cache] and r_tgt_dcache_rsp[r_tgt_num_cache] ) 1660 // { 1661 // if ( p_vci_tgt.rspack.read() ) 1662 // { 1663 // r_tgt_icache_rsp[r_tgt_num_cache] = false; // only reset one for respond the second time 1664 // } 1665 // } 1666 1667 PRINTF(" * <TGT> icache_rsp : %d\n",(uint32_t) r_tgt_icache_rsp[r_tgt_num_cache]); 1668 PRINTF(" * <TGT> dcache_rsp[%d] : %d\n",(uint32_t)r_tgt_num_cache,(uint32_t)r_tgt_dcache_rsp[r_tgt_num_cache].read()); 1669 // if there is no need for a response 1670 if (not tgt_icache_rsp and not r_tgt_dcache_rsp[r_tgt_num_cache] ) 1671 { 1672 r_vci_tgt_fsm = TGT_IDLE; 1673 } 1674 1675 } 1676 break; 1677 } 1678 //////////////////// 1679 case TGT_RSP_ICACHE: 1680 { 1681 bool transaction_rsp = (p_vci_tgt.rspack.read() or not r_tgt_icache_rsp[r_tgt_num_cache].read()) and not r_tgt_icache_req[r_tgt_num_cache].read(); 1682 1683 PRINTF(" * <TGT> RSP_ICACHE : transaction : %d ((%d or not %d) and not %d)\n",transaction_rsp 1684 ,(int)p_vci_tgt.rspack.read() 1685 ,(int)r_tgt_icache_rsp[r_tgt_num_cache].read() 1686 ,(int)r_tgt_icache_req[r_tgt_num_cache].read() 1687 ); 1688 1689 if (transaction_rsp) 1690 { 1691 r_vci_tgt_fsm = TGT_IDLE; 1692 r_tgt_icache_rsp[r_tgt_num_cache] = false; 1693 } 1694 break; 1695 } 1696 1697 case TGT_RSP_DCACHE: 1698 { 1699 bool transaction_rsp = (p_vci_tgt.rspack.read() or not r_tgt_dcache_rsp[r_tgt_num_cache].read()) and not r_tgt_dcache_req[r_tgt_num_cache].read(); 1700 1701 PRINTF(" * <TGT> RSP_DCACHE : transaction : %d\n",transaction_rsp); 1702 1703 if (transaction_rsp) 1704 { 1705 r_vci_tgt_fsm = TGT_IDLE; 1706 r_tgt_dcache_rsp[r_tgt_num_cache] = false; 1707 } 1708 break; 1709 } 1710 } // end switch TGT_FSM 1711 1712 ///////////////////////////////////////////////////////////////////// 1713 // Interface between CPU and CACHE FSM 1714 /////////////////////////////////////////////////////////////////////// 1715 1716 uint32_t ireq_num_cache [m_nb_cpu]; 1717 uint32_t dreq_num_cache [m_nb_cpu]; 1718 bool have_sync = false; 1719 1720 { 1721 typename iss_t::InstructionRequest _ireq = ISS_IREQ_INITIALIZER; 1722 typename iss_t::DataRequest _dreq = ISS_DREQ_INITIALIZER; 1723 1724 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 1725 { 1726 ireq [num_cache] = _ireq; 1727 //irsp [num_cache] = _irsp; 1728 } 1729 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 1730 { 1731 dreq [num_cache] = _dreq; 1732 //drsp [num_cache] = _drsp; 1733 1734 have_sync |= r_dcache_sync [num_cache]; 1735 } 1736 } 1737 1738 for (uint32_t _num_cpu=0; _num_cpu<m_nb_cpu; ++_num_cpu) 1739 { 1740 // round robin priority 1741 uint32_t num_cpu = (r_cpu_prior+_num_cpu)%m_nb_cpu; 1742 1743 typename iss_t::InstructionRequest _ireq = ISS_IREQ_INITIALIZER; 1744 typename iss_t::DataRequest _dreq = ISS_DREQ_INITIALIZER; 1745 1746 m_iss[num_cpu]->getRequests(_ireq, _dreq); 1747 1748 addr_40 addr; 1749 uint32_t num_cache; 1750 1751 addr = (addr_40)_ireq.addr; 1752 num_cache = get_num_icache(addr,num_cpu); 1753 1754 bool icache_req_valid = ((not ireq[num_cache].valid and // no previous request in this cycle 1755 (r_icache_lock [num_cache] == m_nb_cpu)) or // no previous request in previous cycle 1756 (r_icache_lock [num_cache] == num_cpu)); // previous request in previous cycle by this cpu 1757 1758 if (icache_req_valid) 1759 { 1760 bool valid = _ireq.valid; 1761 1762 if (valid) 1763 { 1764 PRINTF(" * <CPU2CACHE> ICACHE : Transaction between cpu %d and cache %d (lock)\n",num_cpu,num_cache); 1765 ireq_num_cache [num_cpu ] = num_cache; 1766 r_icache_lock [num_cache] = num_cpu; 1767 } 1768 else 1769 { 1770 PRINTF(" * <CPU2CACHE> ICACHE : No Transaction between cpu %d and cache %d : invalid\n",num_cpu,num_cache); 1771 ireq_num_cache [num_cpu] = m_nb_icache; 1772 } 1773 1774 ireq_cached [num_cache] = m_cacheability_table[(vci_addr_t)_ireq.addr]; 1775 ireq_num_cpu [num_cache] = num_cpu; 1776 ireq [num_cache] = _ireq; 1777 ireq [num_cache].addr = addr; 1778 } 1779 else 1780 { 1781 PRINTF(" * <CPU2CACHE> ICACHE : No transaction (cpu %d)\n",num_cpu); 1782 1783 ireq_num_cache [num_cpu] = m_nb_icache; 1784 } 1785 1786 addr = (addr_40)_dreq.addr; 1787 num_cache = get_num_dcache(addr); 1788 1789 1790 bool dcache_no_lock = (r_dcache_lock [num_cache] == m_nb_cpu); 1791 bool dcache_lock_owner = (r_dcache_lock [num_cache] == num_cpu); 1792 bool dcache_lock_no_owner= not dcache_no_lock and not dcache_lock_owner; 1793 bool dcache_req_valid; 1794 1795 // multi cache : hit after miss) 1796 if (m_nb_dcache > 0) 1797 { 1798 bool dcache_wait = ((r_dcache_fsm[num_cache] == DCACHE_MISS_WAIT)// or 1799 // (r_dcache_fsm[num_cache] == DCACHE_UNC_WAIT) or 1800 // (r_dcache_fsm[num_cache] == DCACHE_SC_WAIT) 1801 ); 1802 1803 dcache_req_valid = ((not dreq[num_cache].valid and // no previous request in this cycle 1804 not have_sync and // no sync instruction 1805 (dcache_no_lock or 1806 (dcache_lock_no_owner and dcache_wait))) or // no previous request in previous cycle 1807 (dcache_lock_owner and not dcache_wait)); // previous request in previous cycle by this cpu 1808 } 1809 else 1810 { 1811 dcache_req_valid = ((not dreq[num_cache].valid and // no previous request in this cycle 1812 not have_sync and // no sync instruction 1813 dcache_no_lock) or // no previous request in previous cycle 1814 dcache_lock_owner); // previous request in previous cycle by this cpu 1815 } 1816 1817 // test if already used 1818 if (dcache_req_valid) 1819 { 1820 bool valid = _dreq.valid; 1821 1822 if (valid) 1823 { 1824 PRINTF(" * <CPU2CACHE> DCACHE : Transaction between cpu %d and cache %d (lock)\n",num_cpu,num_cache); 1825 dreq_num_cache [num_cpu ] = num_cache; 1826 1827 // always lock if no multi cache 1828 if ((m_nb_dcache == 1) or (not dcache_lock_no_owner)) 1829 r_dcache_lock [num_cache] = num_cpu; 1830 } 1831 else 1832 { 1833 PRINTF(" * <CPU2CACHE> DCACHE : No Transaction between cpu %d and cache %d : invalid\n",num_cpu,num_cache); 1834 dreq_num_cache [num_cpu] = m_nb_dcache; 1835 } 1836 1837 dreq_cached [num_cache] = m_cacheability_table[(vci_addr_t)_dreq.addr]; 1838 dreq_num_cpu [num_cache] = num_cpu; 1839 dreq [num_cache] = _dreq; 1840 dreq [num_cache].addr = addr; 1841 } 1842 else 1843 { 1844 PRINTF(" * <CPU2CACHE> DCACHE : No transaction (cpu %d)\n",num_cpu); 1845 1846 dreq_num_cache [num_cpu] = m_nb_dcache; 1847 } 1848 1849 1850 #if CC_XCACHE_WRAPPER_DEBUG 1851 if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN) 1852 { 1853 std::cout << " * <CPU2CACHE> Instruction Request : " << ireq_num_cache[num_cpu] << " - " << _ireq << std::endl 1854 << " * <CPU2CACHE> Data Request : " << dreq_num_cache[num_cpu] << " - " << _dreq << std::endl; 1855 } 1856 #endif 1857 } 1858 1859 // round robin priority 1860 r_cpu_prior = (r_cpu_prior+1)%m_nb_cpu; 1861 1862 ///////////////////////////////////////////////////////////////////// 1863 // The ICACHE FSM controls the following ressources: 1864 // - r_icache_fsm 1865 // - r_icache_fsm_save 1866 // - r_icache instruction cache access 1867 // - r_icache_addr_save 1868 // - r_icache_miss_req set 1869 // - r_icache_unc_req set 1870 // - r_icache_buf_unc_valid set 1871 // - r_vci_rsp_icache_miss_ok reset 1872 // - r_vci_rsp_ins_error reset 1873 // - r_tgt_icache_req reset 1874 // - ireq & irsp structures for communication with the processor 1875 // 1876 // 1/ External requests (update or invalidate) have highest priority. 1877 // They are taken into account in the IDLE and WAIT states. 1878 // As external hit should be extremly rare on the ICACHE, 1879 // all external requests are handled as invalidate... 1880 // In case of external request the ICACHE FSM goes to the CC_CHECK 1881 // state to test the external hit, and returns in the 1882 // pre-empted state after completion. 1883 // 2/ Processor requests are taken into account only in the IDLE state. 1884 // In case of MISS, or in case of uncached instruction, the FSM 1885 // writes the missing address line in the r_icache_addr_save register 1886 // and sets the r_icache_miss_req or the r_icache_unc_req flip-flops. 1887 // These request flip-flops are reset by the VCI_RSP FSM 1888 // when the VCI transaction is completed and the r_icache_buf_unc_valid 1889 // is set in case of uncached access. 1890 // In case of bus error, the VCI_RSP FSM sets the r_vci_rsp_ins_error 1891 // flip-flop. It is reset by the ICACHE FSM. 1892 /////////////////////////////////////////////////////////////////////// 1893 1894 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 1895 { 1896 typename iss_t::InstructionRequest _ireq = ireq [num_cache]; 1897 typename iss_t::InstructionResponse _irsp = ISS_IRSP_INITIALIZER; 1898 1899 switch(r_icache_fsm[num_cache]) { 1900 ///////////////// 1901 case ICACHE_IDLE: 1902 { 1903 if ( r_tgt_icache_req[num_cache] ) { // external request 1904 // if ( _ireq.valid ) m_cost_ins_miss_frz++; 1905 r_icache_fsm [num_cache] = ICACHE_CC_CHECK; 1906 r_icache_fsm_save[num_cache] = r_icache_fsm[num_cache]; 1907 break; 1908 } 1909 if ( _ireq.valid ) { 1910 data_t icache_ins = 0; 1911 bool icache_hit = false; 1912 bool icache_cached = ireq_cached [num_cache]; 1913 // uint32_t icache_num_cpu = ireq_num_cpu [num_cache]; 1914 bool icache_cleanup_hit = r_icache_cleanup_req[num_cache] and (((addr_40)_ireq.addr >> (addr_40)m_icache_words_shift) == r_icache_cleanup_line[num_cache].read()); 1915 1916 // icache_hit & icache_ins evaluation 1917 if ( icache_cached ) { 1918 icache_hit = r_icache[num_cache]->read((vci_addr_t) _ireq.addr, &icache_ins); 1919 } else { 1920 // if uncache, again in the vci_rsp_fifo_icache 1921 icache_hit = (r_icache_buf_unc_valid[num_cache] and 1922 ((addr_40) _ireq.addr == (addr_40)r_icache_addr_save[num_cache])); 1923 1924 // Test if top of fifo_rsp is for this cache is in ICACHE_UNC_WAIT 1925 icache_ins = r_vci_rsp_fifo_icache_data.read(); 1926 1927 if (icache_hit) 1928 vci_rsp_fifo_icache_get = true; 1929 } 1930 1931 PRINTF(" * <ICACHE [%d]> hit %d - cached %d - cleanup_hit %d\n",num_cache, icache_hit, icache_cached, icache_cleanup_hit); 1932 1933 if (icache_hit and icache_cleanup_hit) 1934 { 1935 PRINTF(" * <ICACHE [%d]> Warning : icache hit and icache_cleanup_hit\n",num_cache); 1936 icache_hit = false; 1937 } 1938 else 1939 { 1940 if ( not icache_hit and not icache_cleanup_hit) 1941 { 1942 1943 m_cpt_ins_miss++; 1944 m_cost_ins_miss_frz++; 1945 1946 r_icache_addr_save[num_cache] = (addr_40) _ireq.addr; 1947 1948 if ( icache_cached ) 1949 { 1950 // to prevent deadlock, miss victim don't be block 1951 if (not r_icache_cleanup_req[num_cache]) 1952 { 1953 r_icache_fsm [num_cache] = ICACHE_MISS_VICTIM; 1954 r_icache_miss_req[num_cache] = true; 1955 } 1956 else 1957 m_cpt_icache_miss_victim_wait [num_cache] ++; 1958 } 1959 else 1960 { 1961 r_icache_addr_save[num_cache] = (addr_40) _ireq.addr; 1962 1963 r_icache_fsm [num_cache] = ICACHE_UNC_WAIT; 1964 r_icache_unc_req[num_cache] = true; 1965 } 1966 } 1967 else 1968 { 1969 // icache_hit and not icache_cleanup_hit 1970 // not icache_hit and icache_cleanup_hit 1971 1972 // request accepted, inval the buf unc 1973 1974 r_icache_buf_unc_valid[num_cache] = false; 1975 } 1976 m_cpt_icache_dir_read += m_icache_ways; 1977 m_cpt_icache_data_read += m_icache_ways; 1978 } 1979 1980 _irsp.valid = icache_hit; 1981 _irsp.instruction = icache_ins; 1935 r_tgt_dcache_req = false; 1936 r_tgt_dcache_rsp = true; 1937 r_dcache_fsm = r_dcache_fsm_save.read(); 1982 1938 } 1983 1939 break; 1984 } 1985 ////////////////////// 1986 case ICACHE_MISS_VICTIM: 1987 { 1988 // if (not r_icache_cleanup_req[num_cache]) 1989 { 1990 size_t way; 1991 size_t set; 1992 vci_addr_t addr = (vci_addr_t) r_icache_addr_save[num_cache].read(); 1993 vci_addr_t victim; 1994 1995 r_icache_cleanup_req [num_cache] = r_icache[num_cache]->victim_select(addr, &victim, &way, &set ); 1996 r_icache_cleanup_line[num_cache] = (addr_40) victim; 1997 r_icache_miss_way [num_cache] = way; 1998 r_icache_miss_set [num_cache] = set; 1999 2000 r_icache_fsm [num_cache] = ICACHE_MISS_WAIT; 2001 } 2002 break; 2003 } 2004 ////////////////////// 2005 case ICACHE_MISS_WAIT: 2006 { 2007 m_cost_ins_miss_frz++; 2008 if ( r_tgt_icache_req[num_cache] ) { // external request 2009 r_icache_fsm [num_cache] = ICACHE_CC_CHECK; 2010 r_icache_fsm_save [num_cache] = r_icache_fsm[num_cache].read(); 2011 break; 2012 } 2013 2014 bool val = (r_vci_rsp_fifo_icache_data.rok() and 2015 (r_vci_rsp_fifo_icache_num_cache.read() == num_cache)); 2016 2017 PRINTF(" * <ICACHE [%d]> val : %d\n",num_cache,val); 2018 2019 if (val) 2020 { 2021 PRINTF(" * <ICACHE [%d]> r_icache_inval_rsp : %d\n",num_cache,(int) r_icache_inval_rsp [num_cache]); 2022 PRINTF(" * <ICACHE [%d]> r_vci_rsp_ins_error : %d\n",num_cache,(int) r_vci_rsp_ins_error [num_cache]); 2023 PRINTF(" * <ICACHE [%d]> r_icache_cleanup_req : %d\n",num_cache,(int) r_icache_cleanup_req[num_cache]); 2024 2025 // Miss read response and no invalidation 2026 if ( r_vci_rsp_ins_error [num_cache]) { 2027 r_icache_fsm[num_cache] = ICACHE_ERROR; 2028 } else { 2029 r_icache_update_addr[num_cache] = 0; 2030 r_icache_fsm [num_cache] = ICACHE_MISS_UPDT; 2031 } 2032 } 2033 break; 2034 } 2035 ///////////////////// 2036 case ICACHE_UNC_WAIT: 2037 { 2038 m_cost_ins_miss_frz++; 2039 if ( r_tgt_icache_req[num_cache] ) { // external request 2040 r_icache_fsm [num_cache] = ICACHE_CC_CHECK; 2041 r_icache_fsm_save[num_cache] = r_icache_fsm[num_cache].read(); 2042 break; 2043 } 2044 2045 bool ok = (r_vci_rsp_fifo_icache_data.rok() and 2046 (r_vci_rsp_fifo_icache_num_cache.read() == num_cache)); 2047 2048 PRINTF(" * <ICACHE [%d]> ok : %d\n",num_cache,ok); 2049 PRINTF(" * <ICACHE [%d]> error : %d\n",num_cache,(uint32_t)r_vci_rsp_ins_error [num_cache]); 2050 2051 if (ok) 2052 { 2053 if ( r_vci_rsp_ins_error [num_cache]) { 2054 r_icache_fsm[num_cache] = ICACHE_ERROR; 2055 } else { 2056 r_icache_fsm [num_cache] = ICACHE_IDLE; 2057 r_icache_buf_unc_valid[num_cache] = true; 2058 } 2059 } 2060 break; 2061 } 2062 ////////////////// 2063 case ICACHE_ERROR: 2064 { 2065 if ( (addr_40)_ireq.addr == (addr_40)r_icache_addr_save[num_cache] ) { 2066 _irsp.error = true; 2067 _irsp.valid = true; 2068 } 2069 r_icache_fsm [num_cache] = ICACHE_IDLE; 2070 r_vci_rsp_ins_error [num_cache] = false; 2071 break; 2072 } 2073 ////////////////////// 2074 case ICACHE_MISS_UPDT: 2075 { 2076 size_t word = r_icache_update_addr[num_cache].read(); 2077 vci_addr_t addr = (vci_addr_t) r_icache_addr_save [num_cache].read(); 2078 size_t way = r_icache_miss_way[num_cache].read(); 2079 size_t set = r_icache_miss_set[num_cache].read(); 2080 2081 bool val = (r_vci_rsp_fifo_icache_data.rok() and 2082 (r_vci_rsp_fifo_icache_num_cache.read() == num_cache)); 2083 2084 if (val) 2085 { 2086 PRINTF(" * <ICACHE [%d]> rsp_val : %d/%d\n",num_cache,(int)r_icache_update_addr[num_cache],(int)m_icache_words); 2087 PRINTF(" * <ICACHE [%d]> r_icache_inval_rsp : %d\n" ,num_cache,(int)r_icache_inval_rsp[num_cache]); 2088 PRINTF(" * <ICACHE [%d]> ins : %x\n" ,num_cache,(int)r_vci_rsp_fifo_icache_data.read()); 2089 // m_cpt_icache_dir_write++; 2090 // m_cpt_icache_data_write++; 2091 // if ( _ireq.valid ) m_cost_ins_miss_frz++; 2092 2093 // if need invalid rsp, don't modify the cache, but pop the buf_rsp 2094 if (not r_icache_inval_rsp[num_cache]) 2095 r_icache[num_cache]->write(way, set, word, r_vci_rsp_fifo_icache_data.read()); 2096 2097 vci_rsp_fifo_icache_get = true; 2098 2099 r_icache_update_addr[num_cache] = ++word; 2100 2101 // if last word, finish the update 2102 if (word >= m_icache_words) 1940 } 1941 } // end switch r_dcache_fsm 1942 1943 // save the DREQ and DRSP fields for the print_trace() function 1944 m_dreq_valid = dreq.valid; 1945 m_dreq_addr = dreq.addr; 1946 m_dreq_mode = dreq.mode; 1947 m_dreq_type = dreq.type; 1948 m_dreq_wdata = dreq.wdata; 1949 m_dreq_be = dreq.be; 1950 1951 m_drsp_valid = drsp.valid; 1952 m_drsp_rdata = drsp.rdata; 1953 m_drsp_error = drsp.error; 1954 1955 ////////// write buffer state update //////////////////////////////////////////// 1956 // The update() method must be called at each cycle to update the internal state. 1957 1958 r_wbuf->update (); 1959 1960 /////////// test processor frozen ///////////////////////////////////////////// 1961 // The simulation exit if the number of consecutive frozen cycles 1962 // is larger than the m_max_frozen_cycles (constructor parameter) 1963 if ( (ireq.valid and not irsp.valid) or (dreq.valid and not drsp.valid) ) 1964 { 1965 m_cpt_frz_cycles++; // used for instrumentation 1966 m_cpt_stop_simulation++; // used for processor stop if frozen 1967 if ( m_cpt_stop_simulation > m_max_frozen_cycles ) 1968 { 1969 std::cout << std::dec << "ERROR in CC_XCACHE_WRAPPER " << name() 1970 << " frozen since cycle " << m_cpt_total_cycles - m_max_frozen_cycles 1971 << std::endl; 1972 exit(1); 1973 } 1974 } 1975 else 1976 { 1977 m_cpt_stop_simulation = 0; 1978 } 1979 1980 /////////// execute one iss cycle ///////////////////////////////////////////// 1981 1982 uint32_t it = 0; 1983 for (size_t i=0; i<(size_t)iss_t::n_irq; i++) if ( p_irq[i].read() ) it |= (1<<i); 1984 1985 r_iss->executeNCycles(1, irsp, drsp, it); 1986 1987 //////////////////////////////////////////////////////////////////////////////// 1988 // The CLEANUP FSM send the cleanup commands on the coherence network, 1989 // and supports simultaneous cleanup transactions, but two simultaneous 1990 // transactions mut address different cache lines. 1991 // Therefore, the line number is registered in an associative 1992 // registration buffer (Content Adressable Memory) by the CLEANUP FSM, 1993 // and the corresponding slot (identified by the VCI TRDID field) is cleared 1994 // when the cleanup transaction response is received. 1995 // It handles cleanup requests from both the DCACHE FSM & ICACHE FSM 1996 // with a round robin priority, and can support up to 16 simultaneous 1997 // cleanup transactions (16 slots in the registration buffer). 1998 // The r_dcache_cleanup_req (or r_icache_cleanup_req) flip-flops are reset 1999 // when the command has been sent. 2000 // The VCI TRDID field is used to distinguish data/instruction cleanups: 2001 // - if data cleanup : TRDID = 2*index + 0 2002 // - if instruction cleanup : TRDID = 2*index + 1 2003 //////////////////////////////////////////////////////////////////////////// 2004 2005 switch ( r_cleanup_fsm.read() ) 2006 { 2007 /////////////////////// 2008 case CLEANUP_DATA_IDLE: // dcache has highest priority 2009 { 2010 size_t index = 0; 2011 bool ok; 2012 if ( r_dcache_cleanup_req.read() ) // dcache request 2013 { 2014 ok = r_cleanup_buffer.register_value( r_dcache_cleanup_line.read(), 2015 &index ); 2016 if ( ok ) // successful registration 2017 { 2018 r_cleanup_fsm = CLEANUP_DATA_GO; 2019 r_cleanup_trdid = index<<1; 2020 } 2021 } 2022 else if ( r_icache_cleanup_req.read() ) // icache request 2023 { 2024 ok = r_cleanup_buffer.register_value( r_icache_cleanup_line.read(), 2025 &index ); 2026 if ( ok ) // successful registration 2027 { 2028 r_cleanup_fsm = CLEANUP_INS_GO; 2029 r_cleanup_trdid = index<<1 + 1; 2030 } 2031 } 2032 break; 2033 } 2034 ////////////////////// 2035 case CLEANUP_INS_IDLE: // icache has highest priority 2036 { 2037 size_t index = 0; 2038 bool ok; 2039 if ( r_icache_cleanup_req.read() ) // icache request 2040 { 2041 ok = r_cleanup_buffer.register_value( r_icache_cleanup_line.read(), 2042 &index ); 2043 if ( ok ) // successful registration 2044 { 2045 r_cleanup_fsm = CLEANUP_INS_GO; 2046 r_cleanup_trdid = index<<1 + 1; 2047 } 2048 } 2049 else if ( r_dcache_cleanup_req.read() ) // dcache request 2050 { 2051 ok = r_cleanup_buffer.register_value( r_dcache_cleanup_line.read(), 2052 &index ); 2053 if ( ok ) // successful registration 2054 { 2055 r_cleanup_fsm = CLEANUP_DATA_GO; 2056 r_cleanup_trdid = index<<1; 2057 } 2058 } 2059 break; 2060 } 2061 ///////////////////// 2062 case CLEANUP_DATA_GO: 2063 { 2064 if ( p_vci_ini_c.cmdack.read() ) 2065 { 2066 r_dcache_cleanup_req = false; 2067 r_cleanup_fsm = CLEANUP_INS_IDLE; 2068 } 2069 } 2070 //////////////////////// 2071 case CLEANUP_INS_GO: 2072 { 2073 if ( p_vci_ini_c.cmdack.read() ) 2074 { 2075 r_icache_cleanup_req = false; 2076 r_cleanup_fsm = CLEANUP_DATA_IDLE; 2077 } 2078 } 2079 } // end switch CLEANUP FSM 2080 2081 //////////////// Handling cleanup responses ////////////////// 2082 if ( p_vci_ini_c.rspval.read() ) // valid response 2083 { 2084 r_cleanup_buffer.cancel_index( p_vci_ini_c.rtrdid.read() >> 1); 2085 } 2086 2087 //////////////////////////////////////////////////////////////////////////// 2088 // The VCI_CMD FSM controls the following ressources: 2089 // - r_vci_cmd_fsm 2090 // - r_vci_cmd_min 2091 // - r_vci_cmd_max 2092 // - r_vci_cmd_cpt 2093 // - r_vci_cmd_imiss_prio 2094 // - wbuf (reset) 2095 // - r_icache_miss_req (reset) 2096 // - r_icache_unc_req (reset) 2097 // - r_dcache_miss_req (reset) 2098 // - r_dcache_unc_req (reset) 2099 // - r_dcache_sc_req (reset) 2100 // 2101 // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM. 2102 // There is 6 request types, with the following priorities : 2103 // 1 - Data Read Miss : r_dcache_miss_req and miss in the write buffer 2104 // 2 - Data Read Uncacheable : r_dcache_unc_req 2105 // 3 - Instruction Miss : r_icache_miss_req and miss in the write buffer 2106 // 4 - Instruction Uncacheable : r_icache_unc_req 2107 // 5 - Data Write : r_wbuf.rok() 2108 // 6 - Data Store Conditionnal: r_dcache_sc_req 2109 // 2110 // As we want to support several simultaneous VCI transactions, the VCI_CMD_FSM 2111 // and the VCI_RSP_FSM are fully desynchronized. 2112 // 2113 // VCI formats: 2114 // According to the VCI advanced specification, all read requests packets 2115 // (data Uncached, Miss data, instruction Uncached, Miss instruction) 2116 // are one word packets. 2117 // For write burst packets, all words are in the same cache line, 2118 // and addresses must be contiguous (the BE field is 0 in case of "holes"). 2119 // The sc command packet implements actually a compare-and-swap mechanism 2120 // and the packet contains two flits. 2121 ////////////////////////////////////////////////////////////////////////////// 2122 2123 switch ( r_vci_cmd_fsm.read() ) 2124 { 2125 ////////////// 2126 case CMD_IDLE: 2127 { 2128 // r_dcache_miss_req and r_icache_miss_req require both a write_buffer access 2129 // to check a possible pending write on the same cache line. 2130 // As there is only one possible access per cycle to write buffer, we implement 2131 // a round-robin priority for this access, using the r_vci_cmd_imiss_prio flip-flop. 2132 2133 size_t wbuf_min; 2134 size_t wbuf_max; 2135 2136 bool dcache_miss_req = r_dcache_miss_req.read() 2137 and ( not r_icache_miss_req.read() or not r_vci_cmd_imiss_prio.read() ); 2138 bool icache_miss_req = r_icache_miss_req.read() 2139 and ( not r_dcache_miss_req.read() or r_vci_cmd_imiss_prio.read() ); 2140 2141 // 1 - Data Read Miss 2142 if ( dcache_miss_req and r_wbuf->miss(r_dcache_addr_save.read()) ) 2143 { 2144 r_vci_cmd_fsm = CMD_DATA_MISS; 2145 r_dcache_miss_req = false; 2146 r_vci_cmd_imiss_prio = true; 2147 m_cpt_dmiss_transaction++; 2148 } 2149 // 2 - Data Read Uncacheable 2150 else if ( r_dcache_unc_req.read() ) 2151 { 2152 r_vci_cmd_fsm = CMD_DATA_UNC; 2153 r_dcache_unc_req = false; 2154 m_cpt_dunc_transaction++; 2155 } 2156 // 3 - Instruction Miss 2157 else if ( icache_miss_req and r_wbuf->miss(r_icache_addr_save.read()) ) 2158 { 2159 r_vci_cmd_fsm = CMD_INS_MISS; 2160 r_icache_miss_req = false; 2161 r_vci_cmd_imiss_prio = false; 2162 m_cpt_imiss_transaction++; 2163 } 2164 // 4 - Instruction Uncacheable 2165 else if ( r_icache_unc_req.read() ) 2166 { 2167 r_vci_cmd_fsm = CMD_INS_UNC; 2168 r_icache_unc_req = false; 2169 m_cpt_iunc_transaction++; 2170 } 2171 // 5 - Data Write 2172 else if ( r_wbuf->rok(&wbuf_min, &wbuf_max) ) 2173 { 2174 r_vci_cmd_fsm = CMD_DATA_WRITE; 2175 r_vci_cmd_cpt = wbuf_min; 2176 r_vci_cmd_min = wbuf_min; 2177 r_vci_cmd_max = wbuf_max; 2178 m_cpt_write_transaction++; 2179 m_length_write_transaction += (wbuf_max-wbuf_min+1); 2180 } 2181 // 6 - Data Store Conditionnal 2182 else if ( r_dcache_sc_req.read() ) 2183 { 2184 r_vci_cmd_fsm = CMD_DATA_SC; 2185 r_dcache_sc_req = false; 2186 r_vci_cmd_cpt = 0; 2187 m_cpt_sc_transaction++; 2188 } 2189 break; 2190 } 2191 //////////////////// 2192 case CMD_DATA_WRITE: 2193 { 2194 if ( p_vci_ini_d.cmdack.read() ) 2195 { 2196 m_conso_wbuf_read++; 2197 r_vci_cmd_cpt = r_vci_cmd_cpt + 1; 2198 if (r_vci_cmd_cpt == r_vci_cmd_max) // last flit sent 2199 { 2200 r_vci_cmd_fsm = CMD_IDLE ; 2201 r_wbuf->sent() ; 2202 } 2203 } 2204 break; 2205 } 2206 ///////////////// 2207 case CMD_DATA_SC: 2208 { 2209 // The SC VCI command contains two flits 2210 if ( p_vci_ini_d.cmdack.read() ) 2211 { 2212 r_vci_cmd_cpt = r_vci_cmd_cpt + 1; 2213 if (r_vci_cmd_cpt == 1) r_vci_cmd_fsm = CMD_IDLE ; 2214 } 2215 break; 2216 } 2217 ////////////////// 2218 case CMD_INS_MISS: 2219 case CMD_INS_UNC: 2220 case CMD_DATA_MISS: 2221 case CMD_DATA_UNC: 2222 { 2223 // all read VCI commands contain one single flit 2224 if ( p_vci_ini_d.cmdack.read() ) r_vci_cmd_fsm = CMD_IDLE; 2225 break; 2226 } 2227 2228 } // end switch r_vci_cmd_fsm 2229 2230 /////////////////////////////////////////////////////////////////////////////// 2231 // The VCI_RSP FSM controls the following ressources: 2232 // - r_vci_rsp_fsm: 2233 // - r_vci_rsp_fifo_icache (push) 2234 // - r_vci_rsp_fifo_dcache (push) 2235 // - r_vci_rsp_data_error (set) 2236 // - r_vci_rsp_ins_error (set) 2237 // - r_vci_rsp_cpt 2238 // 2239 // As we support several simultaneous transactions, this FSM uses 2240 // the VCI TRDID field to identify the transactions. 2241 // 2242 // VCI vormat: 2243 // This component Rcheks the response packet length and accepts only 2244 // single word packets for write response packets. 2245 // 2246 // Error handling: 2247 // This FSM analyzes the VCI error code and signals directly the Write Bus Error. 2248 // In case of Read Data Error, the VCI_RSP FSM sets the r_vci_rsp_data_error 2249 // flip_flop and the error is signaled by the DCACHE FSM. 2250 // In case of Instruction Error, the VCI_RSP FSM sets the r_vci_rsp_ins_error 2251 // flip_flop and the error is signaled by the DCACHE FSM. 2252 // In case of Cleanup Error, the simulation stops with an error message... 2253 ///////////////////////////////////////////////////////////////////////////////// 2254 2255 switch ( r_vci_rsp_fsm.read() ) 2256 { 2257 ////////////// 2258 case RSP_IDLE: 2259 { 2260 if( p_vci_ini_d.rspval.read() ) 2261 { 2262 r_vci_rsp_cpt = 0; 2263 2264 if ( (p_vci_ini_d.rtrdid.read()>>(vci_param::T-1)) != 0 ) 2265 { 2266 r_vci_rsp_fsm = RSP_DATA_WRITE; 2267 } 2268 else if ( p_vci_ini_d.rtrdid.read() == TYPE_INS_MISS ) 2269 { 2270 r_vci_rsp_fsm = RSP_INS_MISS; 2271 } 2272 else if ( p_vci_ini_d.rtrdid.read() == TYPE_INS_UNC ) 2273 { 2274 r_vci_rsp_fsm = RSP_INS_UNC; 2275 } 2276 else if ( p_vci_ini_d.rtrdid.read() == TYPE_DATA_MISS ) 2277 { 2278 r_vci_rsp_fsm = RSP_DATA_MISS; 2279 } 2280 else if ( p_vci_ini_d.rtrdid.read() == TYPE_DATA_UNC ) 2281 { 2282 r_vci_rsp_fsm = RSP_DATA_UNC; 2283 } 2284 else 2285 { 2286 assert(false and "Unexpected response"); 2287 } 2288 } 2289 break; 2290 } 2291 ////////////////// 2292 case RSP_INS_MISS: 2293 { 2294 if ( p_vci_ini_d.rspval.read() ) 2295 { 2296 if ( (p_vci_ini_d.rerror.read()&0x1) != 0 ) // error reported 2297 { 2298 r_vci_rsp_ins_error = true; 2299 if ( p_vci_ini_d.reop.read() ) r_vci_rsp_fsm = RSP_IDLE; 2300 } 2301 else // no error reported 2302 { 2303 if ( r_vci_rsp_fifo_icache.wok() ) 2103 2304 { 2104 // in all case (inval_rsp or not), update the victim tag 2105 r_icache[num_cache]->victim_update_tag(addr, way, set); 2106 2107 // Last word : if previous invalid_rsp, can cleanup, else update the TAG 2108 if (r_icache_inval_rsp[num_cache]) 2305 assert( (r_vci_rsp_cpt.read() < m_cache_words) and 2306 "The VCI response packet for instruction miss is too long" ); 2307 2308 r_vci_rsp_cpt = r_vci_rsp_cpt.read() + 1; 2309 vci_rsp_fifo_icache_put = true, 2310 vci_rsp_fifo_icache_data = p_vci_ini_d.rdata.read(); 2311 if ( p_vci_ini_d.reop.read() ) 2109 2312 { 2110 r_icache_inval_rsp[num_cache] = false; 2111 r_icache_fsm [num_cache] = ICACHE_CC_CLEANUP; 2112 } 2113 else 2114 { 2115 r_icache_fsm [num_cache] = ICACHE_IDLE; 2313 assert( (r_vci_rsp_cpt.read() == m_cache_words - 1) and 2314 "The VCI response packet for instruction miss is too short"); 2315 2316 r_vci_rsp_fsm = RSP_IDLE; 2116 2317 } 2117 2318 } 2118 2319 } 2119 2120 break; 2121 } 2122 //////////////////// 2123 case ICACHE_CC_CLEANUP: 2124 { 2125 // cleanup 2126 if(not r_icache_cleanup_req[num_cache]){ 2127 r_icache_cleanup_req [num_cache] = true; 2128 r_icache_cleanup_line[num_cache] = r_icache_addr_save[num_cache].read() >> m_icache_words_shift; 2129 r_icache_fsm [num_cache] = ICACHE_IDLE; 2130 2131 m_cpt_icache_dir_read += m_icache_ways; 2132 r_icache[num_cache]->inval((addr_40)r_icache_addr_save[num_cache]); 2133 } 2134 break; 2135 } 2136 ///////////////////// 2137 case ICACHE_CC_CHECK: // read directory in case of invalidate or update request 2138 { 2139 2140 m_cpt_icache_dir_read += m_icache_ways; 2141 m_cpt_icache_data_read += m_icache_ways; 2142 addr_40 ad = r_tgt_iaddr; 2143 2144 PRINTF(" * <ICACHE [%d]> CC_CHECK\n",num_cache); 2145 2146 if((r_icache_fsm_save[num_cache] == ICACHE_MISS_WAIT) and 2147 ((r_icache_addr_save[num_cache].read() & ~((m_icache_words<<2)-1)) == (ad & ~((m_icache_words<<2)-1)))) { 2148 PRINTF(" * <ICACHE [%d]> have request, need inval rsp\n",num_cache); 2149 2150 r_icache_inval_rsp[num_cache] = true; 2151 r_tgt_icache_req [num_cache] = false; 2152 if(r_tgt_update){ // Also send a cleanup and answer 2153 PRINTF(" * <ICACHE [%d]> send a cleanup and answer\n",num_cache); 2154 r_tgt_icache_rsp[num_cache] = true; 2155 } else { // Also send a cleanup but don't answer 2156 PRINTF(" * <ICACHE [%d]> send a cleanup and but don't answer\n",num_cache); 2157 r_tgt_icache_rsp[num_cache] = false; 2158 } 2159 r_icache_fsm[num_cache] = r_icache_fsm_save[num_cache]; 2160 } else { 2161 uint32_t word = r_cache_word; 2162 data_t mask = vci_param::be2mask(r_tgt_be[word]); 2163 data_t rdata = 0; 2164 bool icache_hit = r_icache[num_cache]->read(ad+word*4,&rdata); 2165 2166 PRINTF(" * <ICACHE [%d]> have no request, hit cache : %d\n",num_cache,icache_hit); 2167 2168 if ( icache_hit and r_tgt_update) 2169 { 2170 // Assumption : We have RAM for icache with write enable on byte. 2171 // Consequence : icache_read is only consultation of directory 2172 2173 //if(r_tgt_be[word]) 2174 r_icache[num_cache]->write(ad+word*4, (mask & r_tgt_buf[word]) | (~mask & rdata)); 2175 2176 word ++; 2177 2178 // Find next valid word 2179 for (; word<m_icache_words; ++word) 2180 if (r_tgt_be[word] != 0) 2181 break; 2182 2183 if (word==m_icache_words) 2184 { 2185 r_tgt_icache_req[num_cache] = false; 2186 r_tgt_icache_rsp[num_cache] = true; 2187 r_icache_fsm [num_cache] = r_icache_fsm_save[num_cache].read(); 2188 word = 0; 2189 } 2190 r_cache_word = word; 2191 2192 } else if ( icache_hit and not r_tgt_update) { 2193 r_icache_fsm[num_cache] = ICACHE_CC_INVAL; 2194 } else { // instruction not found (can happen) 2195 r_tgt_icache_req[num_cache] = false; 2196 if(r_tgt_update){ 2197 r_tgt_icache_rsp[num_cache] = true; 2198 } else { 2199 r_tgt_icache_rsp[num_cache] = false; 2200 } 2201 r_icache_fsm[num_cache] = r_icache_fsm_save[num_cache]; 2202 } 2203 } 2204 break; 2205 } 2206 ///////////////////// 2207 case ICACHE_CC_INVAL: 2208 { 2209 addr_40 ad = r_tgt_iaddr; 2210 // if ( _ireq.valid ) m_cost_ins_miss_frz++; 2211 m_cpt_icache_dir_read += m_icache_ways; 2212 r_tgt_icache_rsp[num_cache] = true; 2213 r_icache[num_cache]->inval(ad); 2214 r_tgt_icache_req[num_cache] = false; 2215 r_icache_fsm [num_cache] = r_icache_fsm_save[num_cache]; 2216 break; 2217 } 2218 }// end switch r_icache_fsm 2219 2220 irsp [num_cache] = _irsp; 2221 if (_ireq.valid and _irsp.valid) 2222 { 2223 PRINTF(" * <CPU2CACHE> Transaction between cpu %d and Icache %d (unlock)\n",r_icache_lock [num_cache].read(),num_cache); 2224 2225 r_icache_lock [num_cache] = m_nb_cpu; 2226 m_cpt_icache_access [num_cache] ++; 2227 } 2228 2229 }// end for num_cache 2230 2231 //////////////////////////////////////////////////////////////////////:///////////// 2232 // The DCACHE FSM controls the following ressources: 2233 // - r_dcache_fsm 2234 // - r_dcache_fsm_save 2235 // - r_dcache (data cache access) 2236 // - r_dcache_addr_save 2237 // - r_dcache_wdata_save 2238 // - r_dcache_rdata_save 2239 // - r_dcache_type_save 2240 // - r_dcache_be_save 2241 // - r_dcache_cached_save 2242 // - r_dcache_miss_req set 2243 // - r_dcache_unc_req set 2244 // - r_dcache_cleanup_req set 2245 // - r_vci_rsp_data_error reset 2246 // - r_tgt_dcache_req reset 2247 // - r_wbuf write 2248 // - dreq & drsp structures for communication with the processor 2249 // 2250 // 1/ EXTERNAL REQUEST : 2251 // There is an external request when the tgt_dcache req flip-flop is set, 2252 // requesting a line invalidation or a line update. 2253 // External requests are taken into account in the states IDLE, WRITE_REQ, 2254 // UNC_WAIT, MISS_WAIT, and have the highest priority : 2255 // The actions associated to the pre-empted state are not executed, the DCACHE FSM 2256 // goes to the CC_CHECK state to execute the requested action, and returns to the 2257 // pre-empted state. 2258 // 2/ PROCESSOR REQUEST : 2259 // In order to support VCI write burst, the processor requests are taken into account 2260 // in the WRITE_REQ state as well as in the IDLE state. 2261 // - In the IDLE state, the processor request cannot be satisfied if 2262 // there is a cached read miss, or an uncached read. 2263 // - In the WRITE_REQ state, the request cannot be satisfied if 2264 // there is a cached read miss, or an uncached read, 2265 // or when the write buffer is full. 2266 // - In all other states, the processor request is not satisfied. 2267 // 2268 // The cache access takes into account the cacheability_table. 2269 // In case of processor request, there is five conditions to exit the IDLE state: 2270 // - CACHED READ MISS => to the MISS_WAIT state (waiting the r_miss_ok signal), 2271 // then to the MISS_UPDT state, and finally to the IDLE state. 2272 // - UNCACHED READ => to the UNC_WAIT state (waiting the r_miss_ok signal), 2273 // and to the IDLE state. 2274 // - CACHE INVALIDATE HIT => to the INVAL state for one cycle, then to IDLE state. 2275 // - WRITE MISS => directly to the WRITE_REQ state to access the write buffer. 2276 // - WRITE HIT => to the WRITE_UPDT state, then to the WRITE_REQ state. 2277 // 2278 // Error handling : Read Bus Errors are synchronous events, but 2279 // Write Bus Errors are asynchronous events (processor is not frozen). 2280 // - If a Read Bus Error is detected, the VCI_RSP FSM sets the 2281 // r_vci_rsp_data_error flip-flop, and the synchronous error is signaled 2282 // by the DCACHE FSM. 2283 // - If a Write Bus Error is detected, the VCI_RSP FSM signals 2284 // the asynchronous error using the setWriteBerr() method. 2285 /////////////////////////////////////////////////////////////////////////////////// 2286 2287 for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) 2288 { 2289 typename iss_t::DataRequest _dreq = dreq [num_cache]; 2290 typename iss_t::DataResponse _drsp = ISS_DRSP_INITIALIZER; 2291 2292 switch ( r_dcache_fsm[num_cache]) { 2293 2294 ///////////////// 2295 case DCACHE_IDLE: 2296 { 2297 if ( r_tgt_dcache_req[num_cache]) { // external request 2298 r_dcache_fsm [num_cache] = DCACHE_CC_CHECK; 2299 r_dcache_fsm_save[num_cache] = r_dcache_fsm[num_cache]; 2300 break; 2301 } 2302 2303 if ( _dreq.valid ) { 2304 PRINTF(" * <DCACHE [%d]> Have dreq\n",num_cache); 2305 2306 data_t dcache_rdata = 0; 2307 // dcache_cached and dcache_hit don't used with _dreq.type == {DATA_SC, XTN_READ, XTN_WRITE} 2308 bool dcache_cached = dreq_cached [num_cache]; 2309 uint32_t dcache_num_cpu = dreq_num_cpu [num_cache]; 2310 bool dcache_hit = r_dcache[num_cache]->read((vci_addr_t) _dreq.addr, &dcache_rdata); 2311 bool dcache_cleanup_hit = r_dcache_cleanup_req[num_cache] and (((addr_40)_dreq.addr >> (addr_40)m_dcache_words_shift) == r_dcache_cleanup_line[num_cache].read()); 2312 2313 PRINTF(" * <DCACHE [%d]> hit %d - cached %d - cleanup_hit %d\n",num_cache,dcache_hit, dcache_cached, dcache_cleanup_hit); 2314 2315 m_cpt_dcache_data_read += m_dcache_ways; 2316 m_cpt_dcache_dir_read += m_dcache_ways; 2317 2318 switch( _dreq.type ) { 2319 case iss_t::DATA_READ: 2320 case iss_t::DATA_LL: 2321 { 2322 m_cpt_data_read++; // new dcache read 2323 2324 if (dcache_hit) // no special test for uncached read, because it's always miss 2325 { 2326 // address is in the cache : return the word 2327 r_dcache_fsm [num_cache] = DCACHE_IDLE; 2328 2329 _drsp.valid = true; 2330 _drsp.rdata = dcache_rdata; // return read data (cf dcache_hit) 2331 2332 // if the request is a Load Linked instruction, save request information 2333 if(_dreq.type == iss_t::DATA_LL) 2334 { 2335 PRINTF(" * <DCACHE [%d]> ll_valid = true\n",num_cache); 2336 2337 r_dcache_ll_valid [num_cache][dcache_num_cpu] = true; 2338 r_dcache_ll_data [num_cache][dcache_num_cpu] = dcache_rdata; 2339 r_dcache_ll_addr [num_cache][dcache_num_cpu] = (vci_addr_t) _dreq.addr; 2340 } 2341 } 2342 else 2343 { 2344 if (not dcache_cleanup_hit) 2345 { 2346 2347 // Miss : send signal at the CMD_FSM (via r_dcache_miss_req or r_dcache_unc_req) 2348 if ( dcache_cached ) { 2349 // to prevent deadlock, miss victim don't be block 2350 if (not r_dcache_cleanup_req[num_cache].read()) 2351 { 2352 m_cpt_data_read_miss++; 2353 m_cost_data_miss_frz++; 2354 r_dcache_miss_req [num_cache] = true; 2355 r_dcache_fsm [num_cache] = DCACHE_MISS_VICTIM; 2356 } 2357 else 2358 m_cpt_icache_miss_victim_wait [num_cache] ++; 2359 } else { 2360 if (not r_dcache_previous_unc[num_cache].read()) // strongly order to the uncached access 2361 { 2362 r_dcache_previous_unc[num_cache] = true; 2363 2364 m_cpt_data_read_uncached++; 2365 m_cost_unc_read_frz++; 2366 r_dcache_unc_req[num_cache] = true; 2367 r_dcache_fsm [num_cache] = DCACHE_UNC_WAIT; 2368 } 2369 } 2370 } 2371 } 2372 } 2373 break; 2374 case iss_t::DATA_SC: 2375 { 2376 PRINTF(" * <DCACHE [%d]> DATA_SC - ll_valid = %d, num_cpu = %d\n",num_cache,r_dcache_ll_valid[num_cache][dcache_num_cpu].read(),dcache_num_cpu); 2377 2378 if (not r_dcache_previous_unc[num_cache].read() and not dcache_cleanup_hit) // strongly order to the uncached access 2379 { 2380 //m_cpt_data_read_unc++; // instruction must read the memory in uncached mode 2381 m_cost_unc_read_frz++; 2382 2383 // if previous load linked (with the same address), make a transaction 2384 // else, keep in IDLE state and return 1 (no OK) 2385 if( r_dcache_ll_valid[num_cache][dcache_num_cpu].read() and 2386 (r_dcache_ll_addr [num_cache][dcache_num_cpu].read() == (vci_addr_t)_dreq.addr)){ 2387 PRINTF(" * <DCACHE [%d]> have previous load linked\n",num_cache); 2388 2389 r_dcache_previous_unc[num_cache] = true; 2390 r_dcache_sc_req [num_cache] = true; 2391 2392 r_dcache_fsm [num_cache] = DCACHE_SC_WAIT; 2393 } else { 2394 PRINTF(" * <DCACHE [%d]> don't have previous load linked\n",num_cache); 2395 2396 _drsp.valid = true; 2397 _drsp.rdata = 1; // SC rsp NOK 2398 r_dcache_ll_valid[num_cache][dcache_num_cpu] = false; 2399 } 2400 } 2401 2402 break; 2403 } 2404 case iss_t::XTN_READ: 2405 case iss_t::XTN_WRITE: 2406 { 2407 bool valid = false; 2408 // only DCACHE INVALIDATE and SYNC request are supported 2409 switch (_dreq.addr>>2) 2410 { 2411 case iss_t::XTN_DCACHE_INVAL : 2320 } 2321 break; 2322 } 2323 ///////////////// 2324 case RSP_INS_UNC: 2325 { 2326 if (p_vci_ini_d.rspval.read() ) 2327 { 2328 assert( p_vci_ini_d.reop.read() and 2329 "illegal VCI response packet for uncacheable instruction"); 2330 2331 if ( (p_vci_ini_d.rerror.read()&0x1) != 0 ) // error reported 2332 { 2333 r_vci_rsp_ins_error = true; 2334 r_vci_rsp_fsm = RSP_IDLE; 2335 } 2336 else // no error reported 2337 { 2338 if ( r_vci_rsp_fifo_icache.wok()) 2339 { 2340 vci_rsp_fifo_icache_put = true; 2341 vci_rsp_fifo_icache_data = p_vci_ini_d.rdata.read(); 2342 r_vci_rsp_fsm = RSP_IDLE; 2343 } 2344 } 2345 } 2346 break; 2347 } 2348 /////////////////// 2349 case RSP_DATA_MISS: 2350 { 2351 if ( p_vci_ini_d.rspval.read() ) 2352 { 2353 if ( (p_vci_ini_d.rerror.read()&0x1) != 0 ) // error reported 2354 { 2355 r_vci_rsp_data_error = true; 2356 if ( p_vci_ini_d.reop.read() ) r_vci_rsp_fsm = RSP_IDLE; 2357 } 2358 else // no error reported 2359 { 2360 if ( r_vci_rsp_fifo_dcache.wok() ) 2361 { 2362 assert( (r_vci_rsp_cpt.read() < m_cache_words) and 2363 "The VCI response packet for data miss is too long"); 2364 2365 r_vci_rsp_cpt = r_vci_rsp_cpt.read() + 1; 2366 vci_rsp_fifo_dcache_put = true, 2367 vci_rsp_fifo_dcache_data = p_vci_ini_d.rdata.read(); 2368 if ( p_vci_ini_d.reop.read() ) 2412 2369 { 2413 valid = true; 2414 r_dcache_fsm[num_cache] = DCACHE_INVAL; 2415 break; 2416 } 2417 case iss_t::XTN_SYNC : 2418 { 2419 // Test if write buffer is already empty 2420 // * gain : 1 cycle 2421 // * cost : can be on the critical path 2422 2423 bool empty=true; 2424 for (uint32_t i=0; i<m_nb_dcache; ++i) 2425 empty &= r_wbuf[i]->empty(); 2426 2427 if (empty) 2428 { 2429 valid = true; 2430 r_dcache_fsm [num_cache] = DCACHE_IDLE; 2431 } 2432 else 2433 { 2434 valid = false; 2435 r_dcache_fsm [num_cache] = DCACHE_SYNC; 2436 r_dcache_sync[num_cache] = true; 2437 } 2438 break; 2439 } 2440 default : 2441 { 2442 // std::cout << "Warning in VCI_CC_XCACHE_WRAPPER " << name() << std::endl; 2443 // std::cout << "Unsupported external access : " << (_dreq.addr>>2) << std::endl; 2444 2445 r_dcache_fsm [num_cache] = DCACHE_IDLE; 2446 } 2447 }//end switch (_dreq.addr>>2) 2448 2449 _drsp.valid = valid; 2450 _drsp.rdata = 0; 2451 break; 2452 } 2453 case iss_t::DATA_WRITE: 2454 2455 PRINTF(" * <DCACHE [%d]> r_dcache_previous_unc : %d\n",num_cache,r_dcache_previous_unc[num_cache].read()); 2456 2457 if (dcache_cached or not r_dcache_previous_unc[num_cache].read()) // strongly order to the uncached access 2458 { 2459 bool valid; 2460 addr_40 addr = _dreq.addr; 2461 set_num_dcache(addr,num_cache); 2462 2463 // FIXME : 2464 // * dans le wbuf, ne pas mettre l'adresse au complet (economie de surface) 2465 // * pour cela, virer le set_num_dcache ! 2466 valid = r_wbuf[num_cache]->write(addr, _dreq.be, _dreq.wdata, dcache_cached, dcache_num_cpu); 2467 2468 #if MWBUF_VHDL_TESTBENCH 2469 vhdl_mwbuf_port_write_val [num_cache] = (vhdl_tb_t)1; 2470 vhdl_mwbuf_test_write_ack [num_cache] = (vhdl_tb_t)1; 2471 vhdl_mwbuf_port_write_ack [num_cache] = (vhdl_tb_t)valid; 2472 vhdl_mwbuf_port_write_addr [num_cache] = (vhdl_tb_t)addr; 2473 vhdl_mwbuf_port_write_data [num_cache] = (vhdl_tb_t)_dreq.wdata; 2474 vhdl_mwbuf_port_write_be [num_cache] = (vhdl_tb_t)_dreq.be; 2475 vhdl_mwbuf_port_write_cached [num_cache] = (vhdl_tb_t)dcache_cached; 2476 vhdl_mwbuf_port_write_cpu_id [num_cache] = (vhdl_tb_t)dcache_num_cpu; 2477 #endif 2478 2479 2480 PRINTF(" * <DCACHE [%d]> r_wbuf valid : %d\n",num_cache,valid); 2481 2482 if (valid) 2483 { 2484 m_cpt_data_write++; 2485 2486 if (not dcache_cached) 2487 { 2488 ASSERT(not dcache_hit, 2489 "Request is uncached, but hit in dcache!"); 2490 2491 r_dcache_previous_unc[num_cache] = true; 2492 m_cpt_data_write_uncached++; 2493 } 2494 else if (not dcache_hit) 2495 m_cpt_data_write_miss++; 2496 2497 if (dcache_hit) { 2498 // update data cache 2499 r_dcache_fsm[num_cache] = DCACHE_WRITE_UPDT; 2500 } else { 2501 // write accepted 2502 r_dcache_fsm [num_cache] = DCACHE_IDLE; 2503 } 2504 } 2505 2506 _drsp.valid = valid; 2507 _drsp.rdata = 0; 2508 } 2509 break; 2510 } // end switch _dreq.type 2511 2512 r_dcache_addr_save [num_cache] = (addr_40) _dreq.addr; 2513 r_dcache_type_save [num_cache] = _dreq.type; 2514 r_dcache_wdata_save [num_cache] = _dreq.wdata; 2515 r_dcache_be_save [num_cache] = _dreq.be; 2516 r_dcache_rdata_save [num_cache] = dcache_rdata; 2517 r_dcache_cached_save [num_cache] = dcache_cached; 2518 r_dcache_num_cpu_save[num_cache] = dcache_num_cpu; 2519 2520 } else { // end if _dreq.valid 2521 r_dcache_fsm [num_cache] = DCACHE_IDLE; 2522 } 2523 2524 break; 2525 } 2526 /////////////////////// 2527 case DCACHE_WRITE_UPDT: 2528 { 2529 m_cpt_dcache_data_write++; 2530 data_t mask = vci_param::be2mask(r_dcache_be_save[num_cache]); 2531 data_t wdata = (mask & r_dcache_wdata_save[num_cache]) | (~mask & r_dcache_rdata_save[num_cache]); 2532 vci_addr_t ad = r_dcache_addr_save[num_cache].read(); 2533 r_dcache[num_cache]->write(ad, wdata); 2534 2535 int dcache_fsm_next = DCACHE_IDLE; // default 2536 2537 // Test if write after write 2538 2539 if (_dreq.valid and (_dreq.type == iss_t::DATA_WRITE)) 2540 { 2541 PRINTF(" * <DCACHE [%d]> Have dreq (Write after Write)\n",num_cache); 2542 2543 data_t dcache_rdata = 0; 2544 // dcache_cached and dcache_hit don't used with _dreq.type == {DATA_SC, XTN_READ, XTN_WRITE} 2545 bool dcache_cached = dreq_cached [num_cache]; 2546 uint32_t dcache_num_cpu = dreq_num_cpu [num_cache]; 2547 bool dcache_hit = r_dcache[num_cache]->read((vci_addr_t) _dreq.addr, &dcache_rdata); 2548 2549 m_cpt_dcache_data_read += m_dcache_ways; 2550 m_cpt_dcache_dir_read += m_dcache_ways; 2551 2552 PRINTF(" * <DCACHE [%d]> r_dcache_previous_unc : %d\n",num_cache,r_dcache_previous_unc[num_cache].read()); 2553 2554 if (dcache_cached or not r_dcache_previous_unc[num_cache].read()) // strongly order to the uncached access 2555 { 2556 bool valid; 2557 addr_40 addr = _dreq.addr; 2558 set_num_dcache(addr,num_cache); 2559 2560 // FIXME : 2561 // * dans le wbuf, ne pas mettre l'adresse au complet (economie de surface) 2562 // * pour cela, virer le set_num_dcache ! 2563 valid = r_wbuf[num_cache]->write(addr, _dreq.be, _dreq.wdata, dcache_cached, dcache_num_cpu); 2564 2565 #if MWBUF_VHDL_TESTBENCH 2566 vhdl_mwbuf_port_write_val [num_cache] = (vhdl_tb_t)1; 2567 vhdl_mwbuf_test_write_ack [num_cache] = (vhdl_tb_t)1; 2568 vhdl_mwbuf_port_write_ack [num_cache] = (vhdl_tb_t)valid; 2569 vhdl_mwbuf_port_write_addr [num_cache] = (vhdl_tb_t)addr; 2570 vhdl_mwbuf_port_write_data [num_cache] = (vhdl_tb_t)_dreq.wdata; 2571 vhdl_mwbuf_port_write_be [num_cache] = (vhdl_tb_t)_dreq.be; 2572 vhdl_mwbuf_port_write_cached [num_cache] = (vhdl_tb_t)dcache_cached; 2573 vhdl_mwbuf_port_write_cpu_id [num_cache] = (vhdl_tb_t)dcache_num_cpu; 2574 #endif 2575 2576 PRINTF(" * <DCACHE [%d]> r_wbuf valid : %d\n",num_cache,valid); 2577 2578 if (valid) 2579 { 2580 m_cpt_dcache_store_after_store [num_cache] ++; 2581 2582 m_cpt_data_write++; 2583 2584 if (not dcache_cached) 2585 { 2586 r_dcache_previous_unc[num_cache] = true; 2587 m_cpt_data_write_uncached++; 2588 } 2589 else if (not dcache_hit) 2590 m_cpt_data_write_miss++; 2591 2592 if (dcache_hit) { 2593 // update data cache 2594 dcache_fsm_next = DCACHE_WRITE_UPDT; 2595 } else { 2596 // write accepted 2597 dcache_fsm_next = DCACHE_IDLE; 2598 } 2599 } 2600 2601 _drsp.valid = valid; 2602 _drsp.rdata = 0; 2603 } 2604 2605 r_dcache_addr_save [num_cache] = (addr_40) _dreq.addr; 2606 // r_dcache_type_save [num_cache] = _dreq.type; 2607 r_dcache_wdata_save [num_cache] = _dreq.wdata; 2608 r_dcache_be_save [num_cache] = _dreq.be; 2609 r_dcache_rdata_save [num_cache] = dcache_rdata; 2610 // r_dcache_cached_save [num_cache] = dcache_cached; 2611 // r_dcache_num_cpu_save[num_cache] = dcache_num_cpu; 2612 } 2613 2614 r_dcache_fsm [num_cache] = dcache_fsm_next; // default 2615 2616 break; 2617 } 2618 ////////////////////// 2619 case DCACHE_MISS_VICTIM: 2620 { 2621 // if (not r_dcache_cleanup_req[num_cache].read()) 2622 { 2623 size_t way; 2624 size_t set; 2625 vci_addr_t addr = (vci_addr_t) r_dcache_addr_save[num_cache].read(); 2626 vci_addr_t victim; 2627 bool victim_val = r_dcache[num_cache]->victim_select(addr, &victim, &way, &set ); 2628 2629 r_dcache_cleanup_req [num_cache] = victim_val; 2630 r_dcache_cleanup_line [num_cache] = (addr_40) victim; 2631 r_dcache_miss_way [num_cache] = way; 2632 r_dcache_miss_set [num_cache] = set; 2633 2634 PRINTF(" * <DCACHE [%d]> MISS_VICTIM : Victim %d - %llx (way %d, set %d)\n",num_cache,victim_val, (blob_t)victim, (int)way, (int)set); 2635 2636 r_dcache_fsm [num_cache] = DCACHE_MISS_WAIT; 2637 } 2638 2639 break; 2640 } 2641 ////////////////////// 2642 case DCACHE_MISS_WAIT: 2643 { 2644 // Multi_cache ; Hit after Miss 2645 if (m_nb_dcache>0) 2646 { 2647 data_t dcache_rdata = 0; 2648 bool dcache_hit = r_dcache[num_cache]->read((vci_addr_t) _dreq.addr, &dcache_rdata); 2649 // bool dcache_cached = dreq_cached [num_cache]; 2650 // uint32_t dcache_num_cpu = dreq_num_cpu [num_cache]; 2651 2652 m_cpt_dcache_data_read += m_dcache_ways; 2653 m_cpt_dcache_dir_read += m_dcache_ways; 2654 2655 if (_dreq.valid) 2656 switch (_dreq.type) 2657 { 2658 case iss_t::DATA_READ : // accept only hit dcache load 2659 { 2660 m_cpt_data_read++; // new dcache read 2661 2662 if (dcache_hit) // no special test for uncached read, because it's always miss 2663 { 2664 m_cpt_dcache_hit_after_miss_read [num_cache] ++; 2665 2666 // address is in the cache : return the word 2667 _drsp.valid = true; 2668 _drsp.rdata = dcache_rdata; // return read data (cf dcache_hit) 2669 } 2670 break; 2671 } 2672 // case iss_t::DATA_WRITE : // accept only cached write and miss in dcache (else need update dcache) 2673 // { 2674 // if (dcache_cached and not dcache_hit) 2675 // { 2676 // bool valid; 2677 // addr_40 addr = _dreq.addr; 2678 // set_num_dcache(addr,num_cache); 2679 2680 // // FIXME : 2681 // // * dans le wbuf, ne pas mettre l'adresse au complet (economie de surface) 2682 // // * pour cela, virer le set_num_dcache ! 2683 // valid = r_wbuf[num_cache]->write(addr, _dreq.be, _dreq.wdata, dcache_cached, dcache_num_cpu); 2684 // PRINTF(" * <DCACHE [%d]> r_wbuf valid : %d\n",num_cache,valid); 2685 2686 // if (valid) 2687 // { 2688 // m_cpt_dcache_hit_after_miss_write [num_cache] ++; 2689 2690 // m_cpt_data_write++; 2691 // m_cpt_data_write_miss++; 2692 // } 2693 2694 // _drsp.valid = valid; 2695 // _drsp.rdata = 0; 2696 // } 2697 // break; 2698 // } 2699 default : 2700 { 2701 break; 2702 } 2703 } 2704 } // end multi cache hit after miss 2705 2706 // if ( _dreq.valid ) m_cost_data_miss_frz++; 2707 if ( r_tgt_dcache_req[num_cache].read() ) { // external request 2708 r_dcache_fsm [num_cache] = DCACHE_CC_CHECK; 2709 r_dcache_fsm_save [num_cache] = r_dcache_fsm[num_cache]; 2710 break; 2711 } 2712 2713 bool val = (r_vci_rsp_fifo_dcache_data.rok() and 2714 (r_vci_rsp_fifo_dcache_num_cache.read() == num_cache)); 2715 2716 if (val) 2717 { 2718 // Miss read response and no invalidation 2719 if (r_vci_rsp_data_error[num_cache]) 2720 { 2721 r_dcache_fsm [num_cache] = DCACHE_ERROR; 2722 } 2723 else 2724 { 2725 r_dcache_update_addr[num_cache] = 0; 2726 r_dcache_fsm [num_cache] = DCACHE_MISS_UPDT; 2727 } 2728 } 2729 break; 2730 } 2731 ////////////////////// 2732 case DCACHE_MISS_UPDT: 2733 { 2734 size_t word = r_dcache_update_addr[num_cache].read(); 2735 vci_addr_t addr = (vci_addr_t) r_dcache_addr_save[num_cache].read(); 2736 size_t way = r_dcache_miss_way[num_cache].read(); 2737 size_t set = r_dcache_miss_set[num_cache].read(); 2738 2739 PRINTF(" * <DCACHE [%d]> MISS_UPDT : Victim way %d, set %d\n",num_cache, (int)way, (int)set); 2740 2741 bool val = (r_vci_rsp_fifo_dcache_data.rok() and 2742 (r_vci_rsp_fifo_dcache_num_cache.read() == num_cache)); 2743 2744 if (val) 2745 { 2746 // m_cpt_dcache_dir_write++; 2747 // if ( _dreq.valid ) m_cost_data_miss_frz++; 2748 2749 // if need invalid rsp, don't modify the cache, but pop the buf_rsp 2750 // (power save) 2751 if (not r_dcache_inval_rsp[num_cache]) 2752 { 2753 r_dcache[num_cache]->write(way, set, word, r_vci_rsp_fifo_dcache_data.read()); 2754 m_cpt_dcache_data_write++; 2755 } 2756 2757 vci_rsp_fifo_dcache_get = true; 2758 2759 r_dcache_update_addr[num_cache] = ++word; 2760 2761 // if last word, finish the update 2762 if (word >= m_dcache_words) 2763 { 2764 // in all case (inval_rsp or not), update the victim tag 2765 // because victim is already cleanup 2766 r_dcache[num_cache]->victim_update_tag(addr, way, set); 2767 2768 // Last word : if previous invalid_rsp, can cleanup, else update the TAG 2769 if (r_dcache_inval_rsp[num_cache]) 2770 { 2771 r_dcache_inval_rsp[num_cache] = false; 2772 r_dcache_fsm [num_cache] = DCACHE_CC_CLEANUP; 2773 } 2774 else 2775 { 2776 r_dcache_fsm [num_cache] = DCACHE_IDLE; 2370 assert( (r_vci_rsp_cpt.read() == m_cache_words - 1) and 2371 "The VCI response packet for data miss is too short"); 2372 2373 r_vci_rsp_fsm = RSP_IDLE; 2777 2374 } 2778 2375 } 2779 2376 } 2780 2781 break; 2782 } 2783 //////////////////// 2784 case DCACHE_UNC_WAIT: 2785 { 2786 // if ( _dreq.valid ) m_cost_unc_read_frz++; 2787 if ( r_tgt_dcache_req[num_cache] ) { // external request 2788 r_dcache_fsm [num_cache] = DCACHE_CC_CHECK; 2789 r_dcache_fsm_save[num_cache] = r_dcache_fsm[num_cache]; 2790 break; 2791 } 2792 2793 bool ok = (r_vci_rsp_fifo_dcache_data.rok() and 2794 (r_vci_rsp_fifo_dcache_num_cache.read() == num_cache)); 2795 2796 if (ok) { 2797 if (r_vci_rsp_data_error[num_cache]) { 2798 r_dcache_fsm[num_cache] = DCACHE_ERROR; 2799 } else { 2800 data_t rdata = r_vci_rsp_fifo_dcache_data.read(); 2801 vci_rsp_fifo_dcache_get = true; 2802 2803 if(_dreq.type == iss_t::DATA_LL){ 2804 PRINTF(" * <DCACHE [%d]> ll_valid = true\n",num_cache); 2805 2806 r_dcache_ll_valid [num_cache][r_dcache_num_cpu_save[num_cache]] = true; 2807 r_dcache_ll_data [num_cache][r_dcache_num_cpu_save[num_cache]] = rdata; 2808 r_dcache_ll_addr [num_cache][r_dcache_num_cpu_save[num_cache]] = (vci_addr_t) _dreq.addr; 2809 } 2810 r_dcache_fsm [num_cache] = DCACHE_IDLE; 2811 2812 _drsp.valid = true; 2813 _drsp.rdata = rdata; 2814 } 2815 } 2816 break; 2817 } 2818 //////////////////// 2819 case DCACHE_SC_WAIT: 2820 { 2821 // if ( _dreq.valid ) m_cost_unc_read_frz++; 2822 if ( r_tgt_dcache_req[num_cache] ) { // external request 2823 r_dcache_fsm [num_cache] = DCACHE_CC_CHECK; 2824 r_dcache_fsm_save [num_cache] = r_dcache_fsm [num_cache]; 2825 break; 2826 } 2827 2828 bool ok = (r_vci_rsp_fifo_dcache_data.rok() and 2829 (r_vci_rsp_fifo_dcache_num_cache.read() == num_cache)); 2830 2831 if (ok) { 2832 if (r_vci_rsp_data_error[num_cache]) { 2833 r_dcache_fsm [num_cache] = DCACHE_ERROR; 2834 } else { 2835 r_dcache_fsm [num_cache] = DCACHE_IDLE; 2836 2837 _drsp.valid = true; 2838 _drsp.rdata = r_vci_rsp_fifo_dcache_data.read(); 2839 vci_rsp_fifo_dcache_get = true; 2840 r_dcache_ll_valid [num_cache][r_dcache_num_cpu_save[num_cache]] = false; 2841 } 2842 } 2843 break; 2844 } 2845 2846 ////////////////// 2847 case DCACHE_ERROR: 2848 { 2849 r_dcache_fsm [num_cache] = DCACHE_IDLE; 2850 2851 r_vci_rsp_data_error[num_cache] = false; 2852 _drsp.error = true; 2853 _drsp.valid = true; 2854 break; 2855 } 2856 ///////////////// 2857 case DCACHE_INVAL: 2858 { 2859 if ( r_tgt_dcache_req[num_cache].read() ) { // external request 2860 r_dcache_fsm [num_cache] = DCACHE_CC_CHECK; 2861 r_dcache_fsm_save [num_cache] = r_dcache_fsm [num_cache]; 2862 break; 2863 } 2864 if( not r_dcache_cleanup_req [num_cache].read() ){ 2865 m_cpt_dcache_dir_read += m_dcache_ways; 2866 vci_addr_t ad = r_dcache_addr_save [num_cache].read(); 2867 r_dcache_cleanup_req [num_cache] = r_dcache[num_cache]->inval(ad); 2868 r_dcache_cleanup_line [num_cache] = r_dcache_addr_save [num_cache].read() >> m_dcache_words_shift; 2869 2870 r_dcache_fsm [num_cache] = DCACHE_IDLE; 2871 } 2872 break; 2873 } 2874 case DCACHE_SYNC : 2875 { 2876 if ( r_tgt_dcache_req[num_cache] ) { // external request 2877 r_dcache_fsm [num_cache] = DCACHE_CC_CHECK; 2878 r_dcache_fsm_save[num_cache] = r_dcache_fsm[num_cache]; 2879 break; 2880 } 2881 2882 bool empty=true; 2883 for (uint32_t i=0; i<m_nb_dcache; ++i) 2884 empty &= r_wbuf[i]->empty(); 2885 2886 if (empty) 2887 { 2888 _drsp.valid = true; // end, can accept the sync request 2889 r_dcache_fsm [num_cache] = DCACHE_IDLE; 2890 r_dcache_sync[num_cache] = false; 2891 } 2892 break; 2893 } 2894 ///////////////////// 2895 case DCACHE_CC_CHECK: // read directory in case of invalidate or update request 2896 { 2897 addr_40 ad = r_tgt_daddr; 2898 2899 PRINTF(" * <DCACHE [%d]> CC_CHECK\n",num_cache); 2900 2901 // 2902 if((r_dcache_fsm_save[num_cache] == DCACHE_MISS_WAIT) and 2903 ((r_dcache_addr_save[num_cache].read() & ~((m_dcache_words<<2)-1)) == (ad & ~((m_dcache_words<<2)-1)))) { 2904 PRINTF(" * <DCACHE [%d]> have request, need inval rsp\n",num_cache); 2905 2906 r_dcache_inval_rsp[num_cache] = true; 2907 r_tgt_dcache_req [num_cache] = false; 2908 if(r_tgt_update){ // Also send a cleanup and answer 2909 PRINTF(" * <DCACHE [%d]> send a cleanup and answer\n",num_cache); 2910 r_tgt_dcache_rsp[num_cache] = true; 2911 } else { // Also send a cleanup but don't answer 2912 PRINTF(" * <DCACHE [%d]> send a cleanup and but don't answer\n",num_cache); 2913 r_tgt_dcache_rsp[num_cache] = false; 2914 } 2915 r_dcache_fsm[num_cache] = r_dcache_fsm_save[num_cache]; 2916 } else { 2917 uint32_t word = r_cache_word; 2918 data_t mask = vci_param::be2mask(r_tgt_be[word]); 2919 data_t rdata = 0; 2920 bool dcache_hit = r_dcache[num_cache]->read(ad+word*4,&rdata); 2921 2922 PRINTF(" * <DCACHE [%d]> have no request, hit cache : %d, update : %d\n",num_cache,dcache_hit,(uint32_t)r_tgt_update); 2923 2924 m_cpt_dcache_data_write+= m_dcache_ways; 2925 m_cpt_dcache_dir_read += m_dcache_ways; 2926 2927 if ( dcache_hit and r_tgt_update ) 2928 { 2929 // Assumption : We have RAM for dcache with write enable on byte. 2930 // Consequence : dcache_read is only consultation of directory 2931 2932 //if(r_tgt_be[word]) 2933 r_dcache[num_cache]->write(ad+word*4, (mask & r_tgt_buf[word]) | (~mask & rdata)); 2934 2935 word ++; 2936 2937 // find next valid word 2938 for (; word<m_dcache_words; ++word) 2939 if (r_tgt_be[word] != 0) 2940 break; 2941 2942 if (word==m_dcache_words) 2943 { 2944 r_tgt_dcache_req[num_cache] = false; 2945 r_tgt_dcache_rsp[num_cache] = true; 2946 r_dcache_fsm [num_cache] = r_dcache_fsm_save[num_cache]; 2947 word = 0; 2948 } 2949 r_cache_word = word; 2950 2951 } else if ( dcache_hit and not r_tgt_update ) { 2952 r_dcache_fsm[num_cache] = DCACHE_CC_INVAL; 2953 } else { 2954 if(r_tgt_update){ 2955 r_tgt_dcache_rsp[num_cache] = true; 2956 } else { 2957 r_tgt_dcache_rsp[num_cache] = false; 2958 } 2959 r_tgt_dcache_req[num_cache] = false; 2960 r_dcache_fsm [num_cache] = r_dcache_fsm_save[num_cache]; 2961 } 2962 } 2963 break; 2964 } 2965 ///////////////////// 2966 case DCACHE_CC_INVAL: // invalidate a cache line 2967 { 2968 addr_40 ad = r_tgt_daddr; 2969 r_tgt_dcache_rsp[num_cache] = true; 2970 r_dcache [num_cache]->inval(ad); 2971 r_tgt_dcache_req[num_cache] = false; 2972 r_dcache_fsm [num_cache] = r_dcache_fsm_save[num_cache]; 2973 break; 2974 } 2975 /////////////////// 2976 case DCACHE_CC_CLEANUP: 2977 { 2978 // cleanup 2979 if(not r_dcache_cleanup_req[num_cache]){ 2980 r_dcache_cleanup_req [num_cache] = true; 2981 r_dcache_cleanup_line [num_cache] = r_dcache_addr_save[num_cache].read() >> m_dcache_words_shift; 2982 r_dcache_fsm [num_cache] = DCACHE_IDLE; 2983 2984 m_cpt_dcache_dir_read += m_dcache_ways; 2985 r_dcache[num_cache]->inval((addr_40)r_dcache_addr_save[num_cache]); 2986 } 2987 break; 2988 } 2989 2990 } // end switch r_dcache_fsm 2991 2992 ////////// write buffer state update ///////////// 2993 // The update() method must be called at each cycle to update the internal state. 2994 // All pending write requests must be locked in case of SYNC 2995 2996 r_wbuf[num_cache]->update (have_sync); 2997 2998 #if MWBUF_VHDL_TESTBENCH 2999 vhdl_mwbuf_port_flush [num_cache] = (vhdl_tb_t)have_sync; 3000 #endif 3001 3002 drsp [num_cache] = _drsp; 3003 if (_dreq.valid and _drsp.valid) 3004 { 3005 PRINTF(" * <CPU2CACHE> Transaction between cpu %d and Dcache %d (unlock)\n",r_dcache_lock [num_cache].read(),num_cache); 3006 3007 r_dcache_lock [num_cache] = m_nb_cpu; 3008 m_cpt_dcache_access [num_cache] ++; 3009 } 3010 3011 }// end for num_cache 3012 3013 /////////// execute one iss cycle ///////////////////////////////////////////// 3014 3015 for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) 3016 { 3017 // Test if the resquest is accepted 3018 typename iss_t::InstructionResponse _irsp = ISS_IRSP_INITIALIZER; 3019 typename iss_t::DataResponse _drsp = ISS_DRSP_INITIALIZER; 3020 3021 if (ireq_num_cache[num_cpu]<m_nb_icache) 3022 _irsp = irsp[ireq_num_cache[num_cpu]]; 3023 if (dreq_num_cache[num_cpu]<m_nb_dcache) 3024 _drsp = drsp[dreq_num_cache[num_cpu]]; 3025 3026 #if CC_XCACHE_WRAPPER_STOP_SIMULATION or CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3027 typename iss_t::InstructionRequest _ireq = ISS_IREQ_INITIALIZER; 3028 typename iss_t::DataRequest _dreq = ISS_DREQ_INITIALIZER; 3029 3030 if (ireq_num_cache[num_cpu]<m_nb_icache) 3031 _ireq = ireq[ireq_num_cache[num_cpu]]; 3032 if (dreq_num_cache[num_cpu]<m_nb_dcache) 3033 _dreq = dreq[dreq_num_cache[num_cpu]]; 3034 #endif 3035 3036 #if CC_XCACHE_WRAPPER_DEBUG 3037 if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN) 3038 { 3039 3040 std::cout << " * CPU : " << num_cpu << std::endl 3041 << " * Instruction Cache : " << ireq_num_cache[num_cpu] << ", valid : " << (ireq_num_cache[num_cpu]<m_nb_icache) << std::endl 3042 << " * Instruction Request : " << _ireq << std::endl 3043 << " * Instruction Response : " << _irsp << std::endl 3044 << " * Data Cache : " << dreq_num_cache[num_cpu] << ", valid : " << (dreq_num_cache[num_cpu]<m_nb_dcache) << std::endl 3045 << " * Data Request : " << _dreq << std::endl 3046 << " * Data Response : " << _drsp << std::endl; 3047 } 3048 #endif 3049 3050 if ((_ireq.valid and not _irsp.valid) or 3051 (_dreq.valid and not _drsp.valid)) 3052 { 3053 m_cpt_frz_cycles [num_cpu]++; 3054 #if CC_XCACHE_WRAPPER_STOP_SIMULATION 3055 m_stop_simulation_nb_frz_cycles [num_cpu]++; 3056 3057 if (m_stop_simulation and (m_stop_simulation_nb_frz_cycles [num_cpu]>= m_stop_simulation_nb_frz_cycles_max)) 3058 { 3059 std::cout << std::dec << "CC_XCACHE_WRAPPER \"" << name() << "\" (" << num_cpu << ") : cycle " << m_cpt_total_cycles << ", the cpu is frozen since " << m_stop_simulation_nb_frz_cycles [num_cpu]<< " cycles." << std::endl; 3060 ASSERT(false,"CPU : anormal activity"); // exit 3061 } 3062 } 3063 else 3064 { 3065 m_stop_simulation_nb_frz_cycles [num_cpu] = 0; // reinit counter 3066 #endif //CC_XCACHE_WRAPPER_STOP_SIMULATION 3067 } 3068 3069 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3070 if (generate_log_transaction_file_icache and _ireq.valid and _irsp.valid) 3071 { 3072 log_transaction_file_icache [num_cpu] 3073 << "[" << m_cpt_total_cycles << "]" 3074 << std::hex 3075 << " @ " << std::setw(8) << (uint32_t)_ireq.addr 3076 << " (" << std::setw(8) << (uint32_t)set_num_icache_only(_ireq.addr,ireq_num_cache[num_cpu]) 3077 << " - L " << std::setw(8) <<((uint32_t)set_num_icache_only(_ireq.addr,ireq_num_cache[num_cpu])&m_icache_yzmask) << ")" 3078 << " I " << std::setw(8) << (uint32_t)_irsp.instruction 3079 << " error " << (uint32_t)_irsp.error 3080 << std::dec 3081 << std::endl; 3082 } 3083 3084 if (generate_log_transaction_file_dcache and _dreq.valid and _drsp.valid) 3085 { 3086 log_transaction_file_dcache [num_cpu] 3087 << "[" << m_cpt_total_cycles << "]" 3088 << std::hex 3089 << " @ " << std::setw(8) << (uint32_t)_dreq.addr 3090 << " (" << std::setw(8) << (uint32_t)set_num_dcache_only(_dreq.addr,dreq_num_cache[num_cpu]) 3091 << " - L " << std::setw(8) <<((uint32_t)set_num_dcache_only(_dreq.addr,dreq_num_cache[num_cpu])&m_dcache_yzmask) << ")" 3092 << " be " << std::setw(1) << (uint32_t)_dreq.be 3093 << " W " << std::setw(8) << (uint32_t)_dreq.wdata 3094 << " R " << std::setw(8) << (uint32_t)_drsp.rdata 3095 << " error " << (uint32_t)_drsp.error 3096 << std::dec 3097 << " " << type_str(_dreq.type); 3098 3099 if ((_dreq.type == iss_t::XTN_READ) or 3100 (_dreq.type == iss_t::XTN_WRITE)) 3101 //log_transaction_file_dcache [num_cpu] << xtn_str(_dreq.addr>>2); 3102 switch (_dreq.addr>>2) 3103 { 3104 case iss_t::XTN_DCACHE_INVAL : log_transaction_file_dcache [num_cpu]<< " INVAL"; break; 3105 case iss_t::XTN_SYNC : log_transaction_file_dcache [num_cpu]<< " SYNC"; break; 3106 default : log_transaction_file_dcache [num_cpu]<< " invalid"; break; 3107 } 3108 3109 log_transaction_file_dcache [num_cpu]<< std::endl; 3110 } 3111 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3112 3113 { 3114 uint32_t it = 0; 3115 for (size_t i=0; i<(size_t)iss_t::n_irq; i++) 3116 if(p_irq[num_cpu][i].read()) it |= (1<<i); 3117 3118 m_iss[num_cpu]->executeNCycles(1, _irsp, _drsp, it); 3119 } 3120 }//end num_cpu 3121 3122 //////////////////////////////////////////////////////////////////////////// 3123 // This CLEANUP FSM controls the transmission of the cleanup transactions 3124 // on the coherence network. It controls the following ressources: 3125 // - r_cleanup_fsm 3126 // - r_dcache_cleanup_req (reset) 3127 // - r_icache_cleanup_req (reset) 3128 // 3129 // This FSM handles cleanup requests from both the DCACHE FSM & ICACHE FSM 3130 // - Instruction Cleanup : r_icache_cleanup_req 3131 // - Data Cleanup : r_dcache_cleanup_req 3132 // In case of simultaneous requests, the data request have highest priority. 3133 // There is only one cleanup transaction at a given time (sequencial behavior) 3134 // because the same FSM controls both command & response. 3135 // The the r_icache_cleanup_req & r_dcache_cleanup_req are reset only 3136 // when the response packet is received. 3137 // Error handling : 3138 // As the coherence trafic is controled by hardware, errors are not reported 3139 // to software : In case of errors, the simulation stops. 3140 //////////////////////////////////////////////////////////////////////////// 3141 3142 switch (r_cleanup_fsm) { 3143 3144 case CLEANUP_IDLE: 3145 { 3146 uint32_t num_cache = 0; 3147 bool cleanup_dcache_req = false; 3148 bool cleanup_icache_req = false; 3149 3150 // dcache is prior 3151 for (uint32_t i=0; i<m_nb_dcache; ++i) 3152 { 3153 PRINTF(" * <CLEANUP> dcache_cleanup_req : [%d] %d\n",i,(int)r_dcache_cleanup_req[i]); 3154 cleanup_dcache_req |= r_dcache_cleanup_req[i]; 3155 if (cleanup_dcache_req) 3156 { 3157 PRINTF(" * <CLEANUP> ... find\n"); 3158 num_cache=i; 3159 break; 3160 } 3161 } 3162 3163 if (not cleanup_dcache_req) 3164 for (uint32_t i=0; i<m_nb_icache; ++i) 3165 { 3166 PRINTF(" * <CLEANUP> icache_cleanup_req : [%d] %d\n",i,(int)r_icache_cleanup_req[i]); 3167 3168 cleanup_icache_req |= r_icache_cleanup_req[i]; 3169 if (cleanup_icache_req) 3170 { 3171 PRINTF(" * <CLEANUP> ... find\n"); 3172 num_cache=i; 3173 break; 3174 } 3175 } 3176 3177 PRINTF(" * <CLEANUP> cleanup_icache_req : %d\n",cleanup_icache_req); 3178 PRINTF(" * <CLEANUP> cleanup_dcache_req : %d\n",cleanup_dcache_req); 3179 PRINTF(" * <CLEANUP> num_cache : %d\n",num_cache); 3180 3181 if (cleanup_icache_req or cleanup_dcache_req) 3182 { 3183 r_cleanup_fsm = CLEANUP_REQ; 3184 r_cleanup_icache = cleanup_icache_req; 3185 r_cleanup_num_cache = num_cache; 3186 3187 PRINTF(" * <CLEANUP> address : %llx\n",((cleanup_icache_req)?((blob_t)set_num_icache_only(r_icache_cleanup_line[num_cache].read()<<m_icache_words_shift,num_cache)):((blob_t)set_num_dcache_only(r_dcache_cleanup_line[num_cache].read()<<m_dcache_words_shift,num_cache)))); 3188 3189 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3190 if (generate_log_transaction_file_cleanup) 3191 { 3192 log_transaction_file_cleanup 3193 << "[" << m_cpt_total_cycles << "] " 3194 << ((cleanup_icache_req)?("icache "):("dcache ")) 3195 << num_cache << " : " 3196 << std::hex 3197 << " L " << std::setw(10) << ((cleanup_icache_req)?((blob_t)set_num_icache_only(r_icache_cleanup_line[num_cache].read()<<m_icache_words_shift,num_cache)):((blob_t)set_num_dcache_only(r_dcache_cleanup_line[num_cache].read()<<m_dcache_words_shift,num_cache))) 3198 // << " (" << std::setw(10) << addr << ")" 3199 << std::dec 3200 << std::endl; 3201 } 3202 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3203 3204 } 3205 break; 3206 } 3207 case CLEANUP_REQ: 3208 { 3209 if ( p_vci_ini_c.cmdack ) 3210 { 3211 if (r_cleanup_icache) 3212 r_cleanup_fsm = CLEANUP_RSP_ICACHE; 3213 else 3214 r_cleanup_fsm = CLEANUP_RSP_DCACHE; 3215 } 3216 break; 3217 } 3218 case CLEANUP_RSP_DCACHE: 3219 { 3220 if ( p_vci_ini_c.rspval ) 3221 { 3222 PRINTF(" * <CLEANUP> rerror : %d (%d)\n",(uint32_t)p_vci_ini_c.rerror.read(),0x2 & ( (1 << vci_param::E) - 1)); 3223 PRINTF(" * <CLEANUP> rpktid : %d, r_cleanup_num_cache : %d\n",(uint32_t)p_vci_ini_c.rpktid.read(), (uint32_t)r_cleanup_num_cache); 3224 3225 ASSERT(p_vci_ini_c.reop and (p_vci_ini_c.rtrdid.read() == TYPE_DATA_CLEANUP), 3226 "illegal response packet received for a cleanup transaction"); 3227 ASSERT((p_vci_ini_c.rerror.read()&1) == vci_param::ERR_NORMAL, 3228 "error signaled in a cleanup response" ); 3229 ASSERT(p_vci_ini_c.rpktid.read() == (sc_dt::sc_uint<vci_param::P>)r_cleanup_num_cache, 3230 "invalid pktid in a cleanup response"); 3231 3232 r_cleanup_fsm = CLEANUP_IDLE; 3233 r_dcache_cleanup_req[r_cleanup_num_cache] = false; 3234 // m_cpt_cc_cleanup_data++; 3235 } 3236 break; 3237 } 3238 case CLEANUP_RSP_ICACHE: 3239 { 3240 if ( p_vci_ini_c.rspval ) 3241 { 3242 PRINTF(" * <CLEANUP> rerror : %d (%d)\n",(uint32_t)p_vci_ini_c.rerror.read(),0x2 & ( (1 << vci_param::E) - 1)); 3243 3244 ASSERT(p_vci_ini_c.reop and (p_vci_ini_c.rtrdid.read() == TYPE_INS_CLEANUP), 3245 "illegal response packet received for a cleanup transaction"); 3246 ASSERT((p_vci_ini_c.rerror.read()&1) == vci_param::ERR_NORMAL, 3247 "error signaled in a cleanup response" ); 3248 3249 r_cleanup_fsm = CLEANUP_IDLE; 3250 r_icache_cleanup_req[r_cleanup_num_cache] = false; 3251 // m_cpt_cc_cleanup_ins++; 3252 } 3253 break; 3254 } 3255 } // end switch r_cleanup_fsm 3256 3257 //////////////////////////////////////////////////////////////////////////// 3258 // The VCI_CMD FSM controls the following ressources: 3259 // - r_vci_cmd_fsm 3260 // - r_vci_cmd_min 3261 // - r_vci_cmd_max 3262 // - r_vci_cmd_cpt 3263 // - wbuf (reset) 3264 // - r_icache_miss_req (reset) 3265 // - r_icache_unc_req (reset) 3266 // - r_dcache_miss_req (reset) 3267 // - r_dcache_sc_req (reset) 3268 // 3269 // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM. 3270 // There is 7 request types, with the following priorities : 3271 // 1 - Data Read Miss : r_dcache_miss_req and miss in the write buffer 3272 // 2 - Data Read Uncachable : r_dcache_unc_req and miss in the write buffer 3273 // 3 - Instruction Miss : r_icache_miss_req and miss in the write buffer 3274 // 4 - Instruction Uncachable : r_icache_unc_req and miss in the write buffer 3275 // 5 - Data Write : r_wbuf.rok() 3276 // 6 - Data Store Conditionnal: r_dcache_sc_req 3277 // There is at most one (CMD/RSP) VCI transaction, as both CMD_FSM 3278 // and RSP_FSM exit simultaneously the IDLE state. 3279 // 3280 // VCI formats: 3281 // According to the VCI advanced specification, all read requests packets 3282 // (read Uncached, Miss data, Miss instruction) are one word packets. 3283 // For write burst packets, all words must be in the same cache line, 3284 // and addresses must be contiguous (the BE field is 0 in case of "holes"). 3285 ////////////////////////////////////////////////////////////////////////////// 3286 3287 // reverse priority 3288 r_vci_cmd_dcache_prior = not r_vci_cmd_dcache_prior; 3289 r_vci_cmd_num_icache_prior = (r_vci_cmd_num_icache_prior+1)%m_nb_icache; 3290 r_vci_cmd_num_dcache_prior = (r_vci_cmd_num_dcache_prior+1)%m_nb_dcache; 3291 3292 size_t wbuf_min = 0; 3293 size_t wbuf_max = 0; 3294 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3295 addr_40 wbuf_addr = 0; 3296 size_t wbuf_index = 0; 3297 #endif 3298 3299 uint32_t dcache_write_num_cache = m_nb_dcache; 3300 3301 for (uint32_t i=0; i<m_nb_dcache; ++i) 3302 { 3303 uint32_t num_cache=(r_vci_cmd_num_dcache_prior+i)%m_nb_dcache; 3304 bool find = false; 3305 3306 size_t _wbuf_min = 0; 3307 size_t _wbuf_max = 0; 3308 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3309 addr_40 _wbuf_addr = 0; 3310 size_t _wbuf_index = 0; 3311 #endif 3312 3313 if ( 3314 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3315 (r_wbuf[num_cache]->rok_info(&_wbuf_min, &_wbuf_max, &_wbuf_addr, &_wbuf_index)) and 3316 #else 3317 (r_wbuf[num_cache]->rok (&_wbuf_min, &_wbuf_max)) and 3318 #endif 3319 (dcache_write_num_cache == m_nb_dcache)) 3320 { 3321 find = true; 3322 dcache_write_num_cache = num_cache; 3323 3324 PRINTF(" * <CMD> wbuf min, max : %d, %d\n",(int)_wbuf_min,(int)_wbuf_max); 3325 3326 wbuf_min = _wbuf_min ; 3327 wbuf_max = _wbuf_max ; 3328 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3329 wbuf_addr = _wbuf_addr ; 3330 wbuf_index = _wbuf_index; 3331 3332 PRINTF(" * <CMD> wbuf index : %d\n",(int)_wbuf_index); 3333 PRINTF(" * <CMD> wbuf address : %llx\n",(blob_t)_wbuf_addr); 3334 #endif 3335 } 3336 3337 PRINTF(" * <CMD> Test read after miss : cache : %d, find : %d\n",dcache_write_num_cache, find); 3338 3339 #if MWBUF_VHDL_TESTBENCH 3340 vhdl_mwbuf_test_sent_val [dcache_write_num_cache] = (vhdl_tb_t)1; 3341 vhdl_mwbuf_port_sent_val [dcache_write_num_cache] = (vhdl_tb_t)find; 3342 vhdl_mwbuf_test_sent_word_min [dcache_write_num_cache] = (vhdl_tb_t)find; 3343 vhdl_mwbuf_port_sent_word_min [dcache_write_num_cache] = (vhdl_tb_t)wbuf_min; 3344 vhdl_mwbuf_test_sent_word_max [dcache_write_num_cache] = (vhdl_tb_t)find; 3345 vhdl_mwbuf_port_sent_word_max [dcache_write_num_cache] = (vhdl_tb_t)wbuf_max; 3346 #endif 3347 } 3348 3349 switch (r_vci_cmd_fsm) { 3350 3351 case CMD_IDLE: 3352 { 3353 // if (r_vci_rsp_fsm != RSP_IDLE) break; 3354 3355 3356 // Requests : 3357 3358 // multi_write_buffer access is conditionnal with dcache_miss_req and icache_miss_req 3359 3360 bool dcache_miss_req = false; 3361 bool icache_miss_req = false; 3362 uint32_t dcache_miss_num_cache = m_nb_dcache; 3363 uint32_t icache_miss_num_cache = m_nb_icache; 3364 addr_40 addr = 0; 3365 3366 bool wbuf_imiss = false; 3367 bool wbuf_dmiss = false; 2377 } 2378 break; 2379 } 2380 ////////////////// 2381 case RSP_DATA_UNC: 2382 { 2383 if (p_vci_ini_d.rspval.read() ) 2384 { 2385 assert( p_vci_ini_d.reop.read() and 2386 "illegal VCI response packet for uncacheable read data"); 2387 2388 if ( (p_vci_ini_d.rerror.read()&0x1) != 0 ) // error reported 2389 { 2390 r_vci_rsp_data_error = true; 2391 r_vci_rsp_fsm = RSP_IDLE; 2392 } 2393 else // no error reported 2394 { 2395 if ( r_vci_rsp_fifo_dcache.wok()) 2396 { 2397 vci_rsp_fifo_dcache_put = true; 2398 vci_rsp_fifo_dcache_data = p_vci_ini_d.rdata.read(); 2399 r_vci_rsp_fsm = RSP_IDLE; 2400 } 2401 } 2402 } 2403 break; 2404 } 2405 //////////////////// 2406 case RSP_DATA_WRITE: 2407 { 2408 if (p_vci_ini_d.rspval.read()) 2409 { 2410 assert( p_vci_ini_d.reop.read() and 2411 "a VCI response packet must contain one flit for a write transaction"); 2412 2413 r_vci_rsp_fsm = RSP_IDLE; 2414 uint32_t wbuf_index = p_vci_ini_d.rtrdid.read() - (1<<(vci_param::T-1)); 2415 bool cacheable = r_wbuf->completed(wbuf_index); 2416 if ( not cacheable ) r_dcache_pending_unc_write = false; 2417 if ( (p_vci_ini_d.rerror.read()&0x1) != 0 ) r_iss->setWriteBerr(); 2418 } 2419 break; 2420 } 2421 } // end switch r_vci_rsp_fsm 2422 2423 // FIFO_RSP update 2424 2425 r_vci_rsp_fifo_icache.update(vci_rsp_fifo_icache_get, 2426 vci_rsp_fifo_icache_put, 2427 vci_rsp_fifo_icache_data); 3368 2428 3369 { 3370 for (uint32_t i=0; i<m_nb_dcache; ++i) 3371 { 3372 uint32_t num_cache=(r_vci_cmd_num_dcache_prior+i)%m_nb_dcache; 3373 3374 dcache_miss_req = r_dcache_miss_req[num_cache]; 3375 if (dcache_miss_req) 3376 { 3377 dcache_miss_num_cache = num_cache; 3378 break; 3379 } 3380 } 3381 for (uint32_t i=0; i<m_nb_icache; ++i) 3382 { 3383 uint32_t num_cache=(r_vci_cmd_num_icache_prior+i)%m_nb_icache; 3384 3385 icache_miss_req = r_icache_miss_req[num_cache]; 3386 if (icache_miss_req) 3387 { 3388 icache_miss_num_cache = num_cache; 3389 break; 3390 } 3391 } 3392 3393 PRINTF(" * <CMD> icache_miss_req (before) : %d\n",icache_miss_req); 3394 PRINTF(" * <CMD> dcache_miss_req (before) : %d\n",dcache_miss_req); 3395 3396 // one access with round robin priority 3397 dcache_miss_req = ((dcache_miss_req and not icache_miss_req) or // only dcache 3398 (dcache_miss_req and r_vci_cmd_dcache_prior)); // dcache prior 3399 icache_miss_req &= not dcache_miss_req; 3400 3401 PRINTF(" * <CMD> icache_miss_req (after ) : %d\n",icache_miss_req); 3402 PRINTF(" * <CMD> dcache_miss_req (after ) : %d\n",dcache_miss_req); 3403 3404 PRINTF(" * <CMD> icache_miss_num_cache : %d\n",icache_miss_num_cache); 3405 PRINTF(" * <CMD> dcache_miss_num_cache : %d\n",dcache_miss_num_cache); 3406 3407 if (icache_miss_req or dcache_miss_req) 3408 { 3409 addr = (icache_miss_req)?r_icache_addr_save[icache_miss_num_cache].read():r_dcache_addr_save[dcache_miss_num_cache].read(); 3410 3411 PRINTF(" * <CMD> addr : %llx\n",(blob_t)addr); 3412 3413 if (icache_miss_req) 3414 { 3415 // FIXME : 3416 // si wbuf contient des addresses partionné, set_num_icache puis get_num_dcache 3417 // dcache_miss_num_cache = icache_miss_num_cache; 3418 set_num_icache(addr,icache_miss_num_cache); 3419 // get_num_dcache(addr,dcache_miss_num_cache); 3420 } 3421 else 3422 set_num_dcache(addr,dcache_miss_num_cache); 3423 3424 PRINTF(" * <CMD> addr : %llx\n",(blob_t)addr); 3425 3426 uint32_t num_cache = get_num_dcache_only(addr); 3427 3428 wbuf_imiss = (icache_miss_req)?r_wbuf[num_cache]->miss(addr):false; 3429 wbuf_dmiss = (dcache_miss_req)?r_wbuf[num_cache]->miss(addr):false; 3430 3431 #if MWBUF_VHDL_TESTBENCH 3432 vhdl_mwbuf_port_raw_test [num_cache] = (vhdl_tb_t)1; 3433 vhdl_mwbuf_port_raw_addr [num_cache] = (vhdl_tb_t)addr; 3434 vhdl_mwbuf_test_raw_miss [num_cache] = (vhdl_tb_t)1; 3435 vhdl_mwbuf_port_raw_miss [num_cache] = (dcache_miss_req)?(vhdl_tb_t)wbuf_dmiss:(vhdl_tb_t)wbuf_imiss; 3436 #endif 3437 } 3438 } 3439 3440 uint32_t dcache_unc_num_cache = m_nb_dcache; 3441 for (uint32_t i=0; i<m_nb_dcache; ++i) 3442 { 3443 uint32_t num_cache=(r_vci_cmd_num_dcache_prior+i)%m_nb_dcache; 3444 if (r_dcache_unc_req[num_cache]) 3445 { 3446 dcache_unc_num_cache = num_cache; 3447 break; 3448 } 3449 } 3450 uint32_t icache_unc_num_cache = m_nb_icache; 3451 for (uint32_t i=0; i<m_nb_icache; ++i) 3452 { 3453 uint32_t num_cache=(r_vci_cmd_num_icache_prior+i)%m_nb_icache; 3454 if (r_icache_unc_req[num_cache]) 3455 { 3456 icache_unc_num_cache = num_cache; 3457 break; 3458 } 3459 } 3460 uint32_t dcache_sc_num_cache = m_nb_dcache; 3461 for (uint32_t i=0; i<m_nb_dcache; ++i) 3462 { 3463 uint32_t num_cache=(r_vci_cmd_num_dcache_prior+i)%m_nb_dcache; 3464 if (r_dcache_sc_req[num_cache]) 3465 { 3466 dcache_sc_num_cache = num_cache; 3467 break; 3468 } 3469 } 3470 3471 // 1 - Data Read 3472 if (wbuf_dmiss) 3473 // (dcache_miss_req and r_wbuf[dcache_miss_num_cache]->miss(addr)) 3474 { 3475 r_vci_cmd_fsm = CMD_DATA_MISS; 3476 r_vci_cmd_num_cache = dcache_miss_num_cache; 3477 r_dcache_miss_req[dcache_miss_num_cache] = false; 3478 m_cpt_dmiss_transaction++; 3479 3480 3481 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3482 if (generate_log_transaction_file_cmd) 3483 { 3484 log_transaction_file_cmd 3485 << "[" << m_cpt_total_cycles << "] " 3486 << "CMD DATA MISS " 3487 << "(" << dcache_miss_num_cache << ") " 3488 << std::hex 3489 << " @ " << std::setw(10) << (blob_t)addr 3490 << " (L " << std::setw(10) << ((blob_t)addr&(blob_t)m_dcache_yzmask) << ")" 3491 << std::dec 3492 << std::endl; 3493 } 3494 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3495 3496 } 3497 3498 // 2 - Data Read Uncachable 3499 else if (dcache_unc_num_cache < m_nb_dcache) // have r_dcache_unc_req 3500 { 3501 r_vci_cmd_fsm = CMD_DATA_UNC; 3502 r_vci_cmd_num_cache = dcache_unc_num_cache; 3503 r_dcache_unc_req[dcache_unc_num_cache] = false; 3504 // m_cpt_data_unc_transaction++; 3505 3506 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3507 if (generate_log_transaction_file_cmd) 3508 { 3509 addr_40 addr = (addr_40) r_dcache_addr_save[dcache_unc_num_cache].read() & ~0x3; 3510 set_num_dcache(addr,dcache_unc_num_cache); 3511 3512 log_transaction_file_cmd 3513 << "[" << m_cpt_total_cycles << "] " 3514 << "CMD DATA UNC " 3515 << "(" << dcache_unc_num_cache << ") " 3516 << std::hex 3517 << " @ " << std::setw(10) << (blob_t)addr 3518 << " (L " << std::setw(10) << ((blob_t)addr&(blob_t)m_dcache_yzmask) << ")" 3519 << std::dec 3520 << std::endl; 3521 } 3522 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3523 } 3524 3525 // 3 - Instruction Miss 3526 else if (wbuf_imiss) 3527 //else if (icache_miss_req and r_wbuf[icache_miss_num_cache]->miss(addr)) 3528 { 3529 r_vci_cmd_fsm = CMD_INS_MISS; 3530 r_vci_cmd_num_cache = icache_miss_num_cache; 3531 r_icache_miss_req[icache_miss_num_cache] = false; 3532 m_cpt_imiss_transaction++; 3533 3534 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3535 if (generate_log_transaction_file_cmd) 3536 { 3537 log_transaction_file_cmd 3538 << "[" << m_cpt_total_cycles << "] " 3539 << "CMD INS MISS " 3540 << "(" << icache_miss_num_cache << ") " 3541 << std::hex 3542 << " @ " << std::setw(10) << (blob_t)addr 3543 << " (L " << std::setw(10) << ((blob_t)addr&(blob_t)m_icache_yzmask) << ")" 3544 << std::dec 3545 << std::endl; 3546 } 3547 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3548 } 3549 3550 // 4 - Instruction Uncachable 3551 else if (icache_unc_num_cache < m_nb_icache) // have r_icache_unc_req 3552 { 3553 r_vci_cmd_fsm = CMD_INS_UNC; 3554 r_vci_cmd_num_cache = icache_unc_num_cache; 3555 r_icache_unc_req[icache_unc_num_cache] = false; 3556 // m_cpt_ins_unc_transaction++; 3557 3558 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3559 if (generate_log_transaction_file_cmd) 3560 { 3561 addr_40 addr = (addr_40) r_icache_addr_save[icache_unc_num_cache].read() & ~0x3; 3562 set_num_dcache(addr,icache_unc_num_cache); 3563 3564 log_transaction_file_cmd 3565 << "[" << m_cpt_total_cycles << "] " 3566 << "CMD INS UNC " 3567 << "(" << icache_unc_num_cache << ") " 3568 << std::hex 3569 << " @ " << std::setw(10) << (blob_t)addr 3570 << " (L " << std::setw(10) << ((blob_t)addr&(blob_t)m_icache_yzmask) << ")" 3571 << std::dec 3572 << std::endl; 3573 } 3574 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3575 } 3576 3577 // 5 - Data Write 3578 else if (dcache_write_num_cache < m_nb_dcache) // have r_wbuf.rok(&wbuf_min, &wbuf_max) 3579 { 3580 r_vci_cmd_num_cache = dcache_write_num_cache; 3581 r_vci_cmd_fsm = CMD_DATA_WRITE; 3582 r_vci_cmd_cpt = wbuf_min; 3583 r_vci_cmd_min = wbuf_min; 3584 r_vci_cmd_max = wbuf_max; 3585 m_cpt_data_write_transaction++; 3586 m_length_write_transaction += (wbuf_max-wbuf_min+1); 3587 3588 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3589 if (generate_log_transaction_file_cmd) 3590 { 3591 addr_40 addr = (addr_40) wbuf_addr&~0x3; 3592 3593 log_transaction_file_cmd 3594 << "[" << m_cpt_total_cycles << "] " 3595 << "CMD DATA WRITE " 3596 << "(" << dcache_write_num_cache << ") " 3597 << std::hex 3598 << " @ " << std::setw(10) << (blob_t)addr 3599 << " (L " << std::setw(10) << ((blob_t)addr&(blob_t)m_dcache_yzmask) << ")" 3600 << " [" << wbuf_min << ":" << wbuf_max << "]" 3601 << " {" << wbuf_index << "}" 3602 << std::dec 3603 << std::endl; 3604 } 3605 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3606 } 3607 3608 // 6 - Data Store Conditionnal 3609 else if (dcache_sc_num_cache < m_nb_dcache) // have r_dcache_sc_req 3610 { 3611 r_vci_cmd_fsm = CMD_DATA_SC; 3612 r_vci_cmd_num_cache = dcache_sc_num_cache; 3613 r_vci_cmd_cpt = 0; 3614 r_vci_cmd_min = 0; 3615 r_vci_cmd_max = 1; 3616 m_cpt_unc_transaction++; 3617 r_dcache_sc_req[dcache_sc_num_cache] = false; 3618 3619 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3620 if (generate_log_transaction_file_cmd) 3621 { 3622 addr_40 addr = (addr_40) r_dcache_addr_save[dcache_sc_num_cache].read() & ~0x3; 3623 set_num_dcache(addr,dcache_sc_num_cache); 3624 3625 log_transaction_file_cmd 3626 << "[" << m_cpt_total_cycles << "] " 3627 << "CMD DATA SC " 3628 << "(" << dcache_sc_num_cache << ") " 3629 << std::hex 3630 << " @ " << std::setw(10) << (blob_t)addr 3631 << " (L " << std::setw(10) << ((blob_t)addr&(blob_t)m_dcache_yzmask) << ")" 3632 << std::dec 3633 << std::endl; 3634 } 3635 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3636 } 3637 3638 break; 3639 } 3640 case CMD_DATA_WRITE: 3641 if ( p_vci_ini_rw.cmdack.read() ) { 3642 3643 #if MWBUF_VHDL_TESTBENCH 3644 vhdl_mwbuf_port_sent_word [r_vci_cmd_num_cache] = (vhdl_tb_t)r_vci_cmd_cpt; 3645 vhdl_mwbuf_test_sent_addr [r_vci_cmd_num_cache] = (vhdl_tb_t)1; 3646 vhdl_mwbuf_port_sent_addr [r_vci_cmd_num_cache] = (vhdl_tb_t)r_wbuf[r_vci_cmd_num_cache]->getAddress(r_vci_cmd_cpt); 3647 vhdl_mwbuf_test_sent_data [r_vci_cmd_num_cache] = (vhdl_tb_t)1; 3648 vhdl_mwbuf_port_sent_data [r_vci_cmd_num_cache] = (vhdl_tb_t)r_wbuf[r_vci_cmd_num_cache]->getData(r_vci_cmd_cpt); 3649 vhdl_mwbuf_test_sent_be [r_vci_cmd_num_cache] = (vhdl_tb_t)1; 3650 vhdl_mwbuf_port_sent_be [r_vci_cmd_num_cache] = (vhdl_tb_t)r_wbuf[r_vci_cmd_num_cache]->getBe(r_vci_cmd_cpt); 3651 vhdl_mwbuf_test_sent_index [r_vci_cmd_num_cache] = (vhdl_tb_t)1; 3652 vhdl_mwbuf_port_sent_index [r_vci_cmd_num_cache] = (vhdl_tb_t)r_wbuf[r_vci_cmd_num_cache]->getIndex(); 3653 #endif 3654 3655 r_vci_cmd_cpt = r_vci_cmd_cpt + 1; 3656 if (r_vci_cmd_cpt == r_vci_cmd_max) { 3657 r_vci_cmd_fsm = CMD_IDLE ; 3658 r_wbuf[r_vci_cmd_num_cache]->sent() ; 3659 #if MWBUF_VHDL_TESTBENCH 3660 vhdl_mwbuf_port_sent_ack [r_vci_cmd_num_cache] = (vhdl_tb_t)1; 3661 #endif 3662 } 3663 } 3664 break; 3665 3666 case CMD_DATA_SC: 3667 if ( p_vci_ini_rw.cmdack.read() ) { 3668 r_vci_cmd_cpt = r_vci_cmd_cpt + 1; 3669 if (r_vci_cmd_cpt == r_vci_cmd_max) { 3670 r_vci_cmd_fsm = CMD_IDLE ; 3671 } 3672 } 3673 break; 3674 case CMD_INS_MISS: 3675 case CMD_INS_UNC: 3676 case CMD_DATA_MISS: 3677 case CMD_DATA_UNC: 3678 if ( p_vci_ini_rw.cmdack.read() ) { 3679 r_vci_cmd_fsm = CMD_IDLE; 3680 } 3681 break; 3682 3683 } // end switch r_vci_cmd_fsm 3684 3685 ////////////////////////////////////////////////////////////////////////// 3686 // The VCI_RSP FSM controls the following ressources: 3687 // - r_vci_rsp_fsm: 3688 // - r_vci_rsp_fifo_icache[m_icache_words] 3689 // - r_vci_rsp_fifo_dcache[m_dcache_words] 3690 // - r_vci_rsp_data_error set 3691 // - r_vci_rsp_ins_error set 3692 // - r_vci_rsp_cpt 3693 // In order to have only one active VCI transaction, this VCI_RSP_FSM 3694 // is synchronized with the VCI_CMD FSM, and both FSMs exit the 3695 // IDLE state simultaneously. 3696 // 3697 // VCI formats: 3698 // This component accepts single word or multi-word response packets for 3699 // write response packets. 3700 // 3701 // Error handling: 3702 // This FSM analyzes the VCI error code and signals directly the 3703 // Write Bus Error. 3704 // In case of Read Data Error, the VCI_RSP FSM sets the r_vci_rsp_data_error 3705 // flip_flop and the error is signaled by the DCACHE FSM. 3706 // In case of Instruction Error, the VCI_RSP FSM sets the r_vci_rsp_ins_error 3707 // flip_flop and the error is signaled by the DCACHE FSM. 3708 // In case of Cleanup Error, the simulation stops with an error message... 3709 ////////////////////////////////////////////////////////////////////////// 3710 3711 switch (r_vci_rsp_fsm) { 3712 3713 case RSP_IDLE: 3714 3715 if( p_vci_ini_rw.rspval.read() ) 3716 { 3717 PRINTF(" * <RSP> have rsp - trdid : %x - num_cache : %d\n",(uint32_t)p_vci_ini_rw.rtrdid.read(),(uint32_t)p_vci_ini_rw.rpktid.read()); 3718 3719 ASSERT(p_vci_ini_rw.rpktid.read() <= (1<<vci_param::P), 3720 "invalid pktid in a cleanup response"); 3721 3722 r_vci_rsp_cpt = 0; 3723 3724 if ((p_vci_ini_rw.rtrdid.read()>>(vci_param::T-1)) != 0 ) 3725 { 3726 r_vci_rsp_fsm = RSP_DATA_WRITE; 3727 3728 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3729 if (generate_log_transaction_file_cmd) 3730 { 3731 log_transaction_file_cmd 3732 << "[" << m_cpt_total_cycles << "] " 3733 << "RSP DATA WRITE " 3734 << "(" << p_vci_ini_rw.rpktid.read() << ") " 3735 << "{" << (p_vci_ini_rw.rtrdid.read() - (1<<(vci_param::T-1))) << "}" 3736 << std::endl; 3737 } 3738 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3739 } 3740 else 3741 { 3742 switch (p_vci_ini_rw.rtrdid.read()) 3743 { 3744 case TYPE_INS_MISS : 3745 { 3746 r_vci_rsp_fsm = RSP_INS_MISS; 3747 3748 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3749 if (generate_log_transaction_file_cmd) 3750 { 3751 log_transaction_file_cmd 3752 << "[" << m_cpt_total_cycles << "] " 3753 << "RSP INS MISS " 3754 << "(" << p_vci_ini_rw.rpktid.read() << ") " 3755 << std::endl; 3756 } 3757 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3758 3759 break; 3760 } 3761 case TYPE_INS_UNC : 3762 { 3763 r_vci_rsp_fsm = RSP_INS_UNC; 3764 3765 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3766 if (generate_log_transaction_file_cmd) 3767 { 3768 log_transaction_file_cmd 3769 << "[" << m_cpt_total_cycles << "] " 3770 << "RSP INS UNC " 3771 << "(" << p_vci_ini_rw.rpktid.read() << ") " 3772 << std::endl; 3773 } 3774 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3775 3776 break; 3777 } 3778 case TYPE_DATA_MISS : 3779 { 3780 r_vci_rsp_fsm = RSP_DATA_MISS; 3781 3782 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3783 if (generate_log_transaction_file_cmd) 3784 { 3785 log_transaction_file_cmd 3786 << "[" << m_cpt_total_cycles << "] " 3787 << "RSP DATA MISS " 3788 << "(" << p_vci_ini_rw.rpktid.read() << ") " 3789 << std::endl; 3790 } 3791 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3792 3793 break; 3794 } 3795 case TYPE_DATA_UNC : 3796 { 3797 r_vci_rsp_fsm = RSP_DATA_UNC; 3798 3799 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3800 if (generate_log_transaction_file_cmd) 3801 { 3802 log_transaction_file_cmd 3803 << "[" << m_cpt_total_cycles << "] " 3804 << "RSP DATA UNC " 3805 << "(" << p_vci_ini_rw.rpktid.read() << ") " 3806 << std::endl; 3807 } 3808 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3809 3810 break; 3811 } 3812 case TYPE_DATA_SC : 3813 { 3814 r_vci_rsp_fsm = RSP_DATA_SC; 3815 3816 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3817 if (generate_log_transaction_file_cmd) 3818 { 3819 log_transaction_file_cmd 3820 << "[" << m_cpt_total_cycles << "] " 3821 << "RSP DATA SC " 3822 << "(" << p_vci_ini_rw.rpktid.read() << ") " 3823 << std::endl; 3824 } 3825 #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 3826 3827 break; 3828 } 3829 default : 3830 { 3831 ASSERT(false, "Unexpected response"); 3832 } 3833 } 3834 } 3835 3836 r_vci_rsp_num_cache = p_vci_ini_rw.rpktid.read(); 3837 } 3838 break; 3839 3840 case RSP_INS_MISS: 3841 3842 m_cost_imiss_transaction++; 3843 PRINTF(" * <RSP> rspval : %d / r_vci_rsp_fifo_icache_data.wok %d\n",(uint32_t)p_vci_ini_rw.rspval.read(),(uint32_t)r_vci_rsp_fifo_icache_data.wok()); 3844 3845 if (p_vci_ini_rw.rspval.read() and r_vci_rsp_fifo_icache_data.wok()) 3846 { 3847 PRINTF(" * <RSP> have rsp - r_vci_rsp_cpt : %d/%d\n",(uint32_t)r_vci_rsp_cpt.read(),(uint32_t)m_icache_words); 3848 PRINTF(" * <RSP> ins : %x\n",(int)p_vci_ini_rw.rdata.read()); 3849 3850 ASSERT( (r_vci_rsp_cpt.read() < m_icache_words), 3851 "The VCI response packet for instruction miss is too long" ); 3852 r_vci_rsp_cpt = r_vci_rsp_cpt.read() + 1; 3853 vci_rsp_fifo_icache_put = true, 3854 vci_rsp_fifo_icache_num_cache = r_vci_rsp_num_cache; 3855 vci_rsp_fifo_icache_data = p_vci_ini_rw.rdata.read(); 3856 3857 if ( p_vci_ini_rw.reop.read() ) 3858 { 3859 PRINTF(" * <RSP> have reop\n"); 3860 3861 ASSERT( ((r_vci_rsp_cpt.read() == m_icache_words - 1) or 3862 (p_vci_ini_rw.rerror.read()&1) or 3863 (r_vci_rsp_ins_error[r_vci_rsp_num_cache].read()&0x1)), 3864 "The VCI response packet for instruction miss is too short"); 3865 r_vci_rsp_cpt = 0; 3866 r_vci_rsp_fsm = RSP_IDLE; 3867 3868 } 3869 if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error[r_vci_rsp_num_cache] = true; 3870 } 3871 break; 3872 3873 case RSP_INS_UNC: 3874 3875 m_cost_imiss_transaction++; 3876 if (p_vci_ini_rw.rspval.read() and r_vci_rsp_fifo_icache_data.wok()) 3877 { 3878 ASSERT(p_vci_ini_rw.reop.read(), 3879 "illegal VCI response packet for uncached instruction"); 3880 3881 vci_rsp_fifo_icache_put = true, 3882 vci_rsp_fifo_icache_num_cache = r_vci_rsp_num_cache; 3883 vci_rsp_fifo_icache_data = p_vci_ini_rw.rdata.read(); 3884 3885 r_vci_rsp_fsm = RSP_IDLE; 3886 3887 if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error[r_vci_rsp_num_cache] = true; 3888 } 3889 break; 3890 3891 case RSP_DATA_MISS: 3892 3893 m_cost_dmiss_transaction++; 3894 3895 PRINTF(" * <RSP> rspval : %d / r_vci_rsp_fifo_icache_data.wok %d\n",(uint32_t)p_vci_ini_rw.rspval.read(),(uint32_t)r_vci_rsp_fifo_dcache_data.wok()); 3896 3897 if (p_vci_ini_rw.rspval.read() and r_vci_rsp_fifo_dcache_data.wok()) 3898 { 3899 PRINTF(" * <RSP> have rsp - r_vci_rsp_cpt : %d/%d\n",(uint32_t)r_vci_rsp_cpt.read(),(uint32_t)m_icache_words); 3900 3901 ASSERT(r_vci_rsp_cpt.read() < m_dcache_words, 3902 "illegal VCI response packet for data read miss"); 3903 r_vci_rsp_cpt = r_vci_rsp_cpt.read() + 1; 3904 3905 vci_rsp_fifo_dcache_put = true, 3906 vci_rsp_fifo_dcache_num_cache = r_vci_rsp_num_cache; 3907 vci_rsp_fifo_dcache_data = p_vci_ini_rw.rdata.read(); 3908 3909 if ( p_vci_ini_rw.reop.read() ) { 3910 ASSERT( ((r_vci_rsp_cpt.read() == m_dcache_words - 1) 3911 or (p_vci_ini_rw.rerror.read()&0x1) 3912 or r_vci_rsp_data_error[r_vci_rsp_num_cache].read()), 3913 "illegal VCI response packet for data read miss"); 3914 r_vci_rsp_cpt = 0; 3915 r_vci_rsp_fsm = RSP_IDLE; 3916 } 3917 if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error[r_vci_rsp_num_cache] = true; 3918 } 3919 break; 3920 3921 case RSP_DATA_WRITE: 3922 m_cost_write_transaction++; 3923 if (p_vci_ini_rw.rspval.read()) 3924 { 3925 PRINTF(" * <RSP> have rspval - error : %d\n",(int)p_vci_ini_rw.rerror.read()); 3926 3927 ASSERT(p_vci_ini_rw.reop.read(), 3928 "A VCI response packet must contain one flit for a write transaction"); 3929 r_vci_rsp_fsm = RSP_IDLE; 3930 uint32_t wbuf_index = p_vci_ini_rw.rtrdid.read() - (1<<(vci_param::T-1)); 3931 size_t cpu_id = r_wbuf[r_vci_rsp_num_cache]->getCpuId (wbuf_index); 3932 bool cached = r_wbuf[r_vci_rsp_num_cache]->completed(wbuf_index); 3933 PRINTF(" * <RSP> cached : %d\n",cached); 3934 3935 if (not cached) 3936 r_dcache_previous_unc[r_vci_rsp_num_cache] = false; 3937 3938 if ((p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL) 3939 m_iss[cpu_id]->setWriteBerr(); 3940 3941 #if MWBUF_VHDL_TESTBENCH 3942 vhdl_mwbuf_port_completed_val [r_vci_rsp_num_cache] = (vhdl_tb_t)1; 3943 vhdl_mwbuf_port_completed_index [r_vci_rsp_num_cache] = (vhdl_tb_t)wbuf_index; 3944 vhdl_mwbuf_test_completed_cached [r_vci_rsp_num_cache] = (vhdl_tb_t)1; 3945 vhdl_mwbuf_port_completed_cached [r_vci_rsp_num_cache] = (vhdl_tb_t)cached; 3946 vhdl_mwbuf_test_completed_cpu_id [r_vci_rsp_num_cache] = (vhdl_tb_t)1; 3947 vhdl_mwbuf_port_completed_cpu_id [r_vci_rsp_num_cache] = (vhdl_tb_t)cpu_id; 3948 #endif 3949 } 3950 break; 3951 3952 case RSP_DATA_UNC: 3953 m_cost_unc_transaction++; 3954 if (p_vci_ini_rw.rspval.read() and r_vci_rsp_fifo_dcache_data.wok()) 3955 { 3956 ASSERT(p_vci_ini_rw.reop.read(), 3957 "illegal VCI response packet for data read uncached"); 3958 3959 vci_rsp_fifo_dcache_put = true, 3960 vci_rsp_fifo_dcache_num_cache = r_vci_rsp_num_cache; 3961 vci_rsp_fifo_dcache_data = p_vci_ini_rw.rdata.read(); 3962 3963 r_vci_rsp_fsm = RSP_IDLE; 3964 r_dcache_previous_unc[r_vci_rsp_num_cache] = false; 3965 3966 if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error[r_vci_rsp_num_cache] = true; 3967 } 3968 break; 3969 3970 case RSP_DATA_SC: 3971 m_cost_unc_transaction++; 3972 if (p_vci_ini_rw.rspval.read() and r_vci_rsp_fifo_dcache_data.wok()) 3973 { 3974 ASSERT(p_vci_ini_rw.reop.read(), 3975 "illegal VCI response packet for data SC"); 3976 3977 vci_rsp_fifo_dcache_put = true, 3978 vci_rsp_fifo_dcache_num_cache = r_vci_rsp_num_cache; 3979 vci_rsp_fifo_dcache_data = p_vci_ini_rw.rdata.read(); 3980 3981 r_vci_rsp_fsm = RSP_IDLE; 3982 r_dcache_previous_unc[r_vci_rsp_num_cache] = false; 3983 3984 if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error[r_vci_rsp_num_cache] = true; 3985 } 3986 break; 3987 3988 } // end switch r_vci_rsp_fsm 3989 3990 ////////////////////////////////////////////////////////////////////////// 3991 // FIFO_RSP 3992 ////////////////////////////////////////////////////////////////////////// 3993 3994 r_vci_rsp_fifo_icache_data .update(vci_rsp_fifo_icache_get, 3995 vci_rsp_fifo_icache_put, 3996 vci_rsp_fifo_icache_data); 3997 r_vci_rsp_fifo_icache_num_cache.update(vci_rsp_fifo_icache_get, 3998 vci_rsp_fifo_icache_put, 3999 vci_rsp_fifo_icache_num_cache); 4000 4001 r_vci_rsp_fifo_dcache_data .update(vci_rsp_fifo_dcache_get, 4002 vci_rsp_fifo_dcache_put, 4003 vci_rsp_fifo_dcache_data); 4004 r_vci_rsp_fifo_dcache_num_cache.update(vci_rsp_fifo_dcache_get, 4005 vci_rsp_fifo_dcache_put, 4006 vci_rsp_fifo_dcache_num_cache); 4007 4008 #if MWBUF_VHDL_TESTBENCH 4009 for (uint32_t num_dcache=0; num_dcache<m_nb_dcache; ++num_dcache) 4010 { 4011 vhdl_mwbuf_test_empty [num_dcache] = (vhdl_tb_t)1; 4012 vhdl_mwbuf_port_empty [num_dcache] = (vhdl_tb_t)r_wbuf[num_dcache]->empty(); 4013 4014 vhdl_testbench_mwbuf [num_dcache] 4015 << std::hex 4016 << vhdl_mwbuf_test_empty [num_dcache] << " " 4017 << vhdl_mwbuf_port_empty [num_dcache] << " " 4018 << vhdl_mwbuf_port_flush [num_dcache] << " " 4019 << vhdl_mwbuf_port_write_val [num_dcache] << " " 4020 << vhdl_mwbuf_test_write_ack [num_dcache] << " " 4021 << vhdl_mwbuf_port_write_ack [num_dcache] << " " 4022 << vhdl_mwbuf_port_write_addr [num_dcache] << " " 4023 << vhdl_mwbuf_port_write_data [num_dcache] << " " 4024 << vhdl_mwbuf_port_write_be [num_dcache] << " " 4025 << vhdl_mwbuf_port_write_cached [num_dcache] << " " 4026 << vhdl_mwbuf_port_write_cpu_id [num_dcache] << " " 4027 << vhdl_mwbuf_test_sent_val [num_dcache] << " " 4028 << vhdl_mwbuf_port_sent_val [num_dcache] << " " 4029 << vhdl_mwbuf_port_sent_ack [num_dcache] << " " 4030 << vhdl_mwbuf_test_sent_word_min [num_dcache] << " " 4031 << vhdl_mwbuf_port_sent_word_min [num_dcache] << " " 4032 << vhdl_mwbuf_test_sent_word_max [num_dcache] << " " 4033 << vhdl_mwbuf_port_sent_word_max [num_dcache] << " " 4034 << vhdl_mwbuf_port_sent_word [num_dcache] << " " 4035 << vhdl_mwbuf_test_sent_addr [num_dcache] << " " 4036 << vhdl_mwbuf_port_sent_addr [num_dcache] << " " 4037 << vhdl_mwbuf_test_sent_data [num_dcache] << " " 4038 << vhdl_mwbuf_port_sent_data [num_dcache] << " " 4039 << vhdl_mwbuf_test_sent_be [num_dcache] << " " 4040 << vhdl_mwbuf_port_sent_be [num_dcache] << " " 4041 << vhdl_mwbuf_test_sent_index [num_dcache] << " " 4042 << vhdl_mwbuf_port_sent_index [num_dcache] << " " 4043 << vhdl_mwbuf_port_raw_test [num_dcache] << " " 4044 << vhdl_mwbuf_port_raw_addr [num_dcache] << " " 4045 << vhdl_mwbuf_test_raw_miss [num_dcache] << " " 4046 << vhdl_mwbuf_port_raw_miss [num_dcache] << " " 4047 << vhdl_mwbuf_port_completed_val [num_dcache] << " " 4048 << vhdl_mwbuf_port_completed_index [num_dcache] << " " 4049 << vhdl_mwbuf_test_completed_cached [num_dcache] << " " 4050 << vhdl_mwbuf_port_completed_cached [num_dcache] << " " 4051 << vhdl_mwbuf_test_completed_cpu_id [num_dcache] << " " 4052 << vhdl_mwbuf_port_completed_cpu_id [num_dcache] 4053 << std::dec 4054 << std::endl; 4055 } 4056 #endif 4057 } // end transition() 4058 4059 ////////////////////////////////////////////////////////////////////////////////// 4060 tmpl(void)::genMoore() 4061 ////////////////////////////////////////////////////////////////////////////////// 2429 r_vci_rsp_fifo_dcache.update(vci_rsp_fifo_dcache_get, 2430 vci_rsp_fifo_dcache_put, 2431 vci_rsp_fifo_dcache_data); 2432 2433 } // end transition() 2434 2435 ////////////////////////// 2436 tmpl(void)::genMoore() 2437 ////////////////////////// 2438 { 2439 //////////////////////////////////////////////////////////////// 2440 // VCI initiator command on the coherence network (cleanup) 2441 2442 vci_addr_t address; 2443 2444 if ( r_cleanup_fsm.read() == CLEANUP_DATA_GO ) 2445 address = (vci_addr_t)r_dcache_cleanup_line.read()<<m_cache_words_shift; 2446 else if ( r_cleanup_fsm.read() == CLEANUP_INS_GO ) 2447 address = (vci_addr_t)r_icache_cleanup_line.read()<<m_cache_words_shift; 2448 else 2449 address = 0; 2450 2451 p_vci_ini_c.cmdval = ((r_cleanup_fsm.read() == CLEANUP_DATA_GO) or 2452 (r_cleanup_fsm.read() == CLEANUP_INS_GO) ); 2453 p_vci_ini_c.address = address; 2454 p_vci_ini_c.wdata = 0; 2455 p_vci_ini_c.be = 0xF; 2456 p_vci_ini_c.plen = 4; 2457 p_vci_ini_c.cmd = vci_param::CMD_WRITE; 2458 p_vci_ini_c.trdid = r_cleanup_trdid.read(); 2459 p_vci_ini_c.pktid = 0; 2460 p_vci_ini_c.srcid = m_srcid_c; 2461 p_vci_ini_c.cons = false; 2462 p_vci_ini_c.wrap = false; 2463 p_vci_ini_c.contig = false; 2464 p_vci_ini_c.clen = 0; 2465 p_vci_ini_c.cfixed = false; 2466 p_vci_ini_c.eop = true; 2467 2468 ///////////////////////////////////////////////////////////////// 2469 // VCI initiator response on the coherence network (cleanup) 2470 2471 p_vci_ini_c.rspack = true; 2472 2473 ////////////////////////////////////////////// 2474 // VCI initiator command on the direct network 2475 switch (r_vci_cmd_fsm.read() ) 4062 2476 { 4063 PRINTF("--------------------------------------------\n"); 4064 PRINTF(" * CC_XCACHE_WRAPPER \"%s\" genMoore - Time = %d\n",name().c_str(),(uint32_t)m_cpt_total_cycles); 4065 4066 // VCI initiator response 4067 switch ( r_cleanup_fsm.read() ) { 4068 case CLEANUP_IDLE: 4069 p_vci_ini_c.rspack = false; 4070 p_vci_ini_c.cmdval = false; 4071 p_vci_ini_c.address = 0; 4072 p_vci_ini_c.wdata = 0; 4073 p_vci_ini_c.be = 0; 4074 p_vci_ini_c.plen = 0; 4075 p_vci_ini_c.cmd = vci_param::CMD_WRITE; 4076 p_vci_ini_c.trdid = 0; 4077 p_vci_ini_c.pktid = 0; 4078 p_vci_ini_c.srcid = 0; 4079 p_vci_ini_c.cons = false; 4080 p_vci_ini_c.wrap = false; 4081 p_vci_ini_c.contig = false; 4082 p_vci_ini_c.clen = 0; 4083 p_vci_ini_c.cfixed = false; 4084 p_vci_ini_c.eop = false; 4085 break; 4086 4087 case CLEANUP_REQ: 4088 { 4089 addr_40 addr; 4090 if (r_cleanup_icache) 4091 { 4092 addr = r_icache_cleanup_line[r_cleanup_num_cache].read()<<m_icache_words_shift; 4093 set_num_icache(addr,r_cleanup_num_cache); 4094 4095 PRINTF(" * <CLEANUP> icache : %llx\n",(blob_t)addr); 4096 } 4097 else 4098 { 4099 addr = r_dcache_cleanup_line[r_cleanup_num_cache].read()<<m_dcache_words_shift; 4100 set_num_dcache(addr,r_cleanup_num_cache); 4101 4102 PRINTF(" * <CLEANUP> dcache : %llx\n",(blob_t)addr); 4103 } 4104 4105 p_vci_ini_c.rspack = false; 4106 p_vci_ini_c.cmdval = true; 4107 p_vci_ini_c.address = addr; 4108 p_vci_ini_c.wdata = 0; 4109 p_vci_ini_c.be = 0xF; 4110 p_vci_ini_c.plen = 4; 4111 p_vci_ini_c.cmd = vci_param::CMD_WRITE; 4112 p_vci_ini_c.trdid = (r_cleanup_icache)?TYPE_INS_CLEANUP:TYPE_DATA_CLEANUP; 4113 p_vci_ini_c.pktid = (sc_dt::sc_uint<vci_param::P>)r_cleanup_num_cache; 4114 p_vci_ini_c.srcid = m_srcid_c; 4115 p_vci_ini_c.cons = false; 4116 p_vci_ini_c.wrap = false; 4117 p_vci_ini_c.contig = false; 4118 p_vci_ini_c.clen = 0; 4119 p_vci_ini_c.cfixed = false; 4120 p_vci_ini_c.eop = true; 4121 4122 break; 4123 } 4124 4125 case CLEANUP_RSP_DCACHE: 4126 p_vci_ini_c.rspack = true; 4127 p_vci_ini_c.cmdval = false; 4128 p_vci_ini_c.address = 0; 4129 p_vci_ini_c.wdata = 0; 4130 p_vci_ini_c.be = 0; 4131 p_vci_ini_c.plen = 0; 4132 p_vci_ini_c.cmd = vci_param::CMD_WRITE; 4133 p_vci_ini_c.trdid = 0; 4134 p_vci_ini_c.pktid = 0; 4135 p_vci_ini_c.srcid = 0; 4136 p_vci_ini_c.cons = false; 4137 p_vci_ini_c.wrap = false; 4138 p_vci_ini_c.contig = false; 4139 p_vci_ini_c.clen = 0; 4140 p_vci_ini_c.cfixed = false; 4141 p_vci_ini_c.eop = false; 4142 break; 4143 4144 case CLEANUP_RSP_ICACHE: 4145 p_vci_ini_c.rspack = true; 4146 p_vci_ini_c.cmdval = false; 4147 p_vci_ini_c.address = 0; 4148 p_vci_ini_c.wdata = 0; 4149 p_vci_ini_c.be = 0; 4150 p_vci_ini_c.plen = 0; 4151 p_vci_ini_c.cmd = vci_param::CMD_WRITE; 4152 p_vci_ini_c.trdid = 0; 4153 p_vci_ini_c.pktid = 0; 4154 p_vci_ini_c.srcid = 0; 4155 p_vci_ini_c.cons = false; 4156 p_vci_ini_c.wrap = false; 4157 p_vci_ini_c.contig = false; 4158 p_vci_ini_c.clen = 0; 4159 p_vci_ini_c.cfixed = false; 4160 p_vci_ini_c.eop = false; 4161 break; 4162 } // end switch r_cleanup_fsm 4163 4164 // VCI initiator command 4165 4166 switch (r_vci_cmd_fsm.read() ) { 4167 case CMD_IDLE: 4168 { 4169 p_vci_ini_rw.cmdval = false; 4170 p_vci_ini_rw.address = 0; 4171 p_vci_ini_rw.wdata = 0; 4172 p_vci_ini_rw.be = 0; 4173 p_vci_ini_rw.plen = 0; 4174 p_vci_ini_rw.cmd = vci_param::CMD_NOP; 4175 p_vci_ini_rw.trdid = 0; 4176 p_vci_ini_rw.pktid = 0; 4177 p_vci_ini_rw.srcid = 0; 4178 p_vci_ini_rw.cons = false; 4179 p_vci_ini_rw.wrap = false; 4180 p_vci_ini_rw.contig = false; 4181 p_vci_ini_rw.clen = 0; 4182 p_vci_ini_rw.cfixed = false; 4183 p_vci_ini_rw.eop = false; 4184 4185 break; 4186 } 4187 case CMD_DATA_UNC: 4188 { 4189 p_vci_ini_rw.cmdval = true; 4190 4191 addr_40 addr = (addr_40) r_dcache_addr_save[r_vci_cmd_num_cache].read() & ~0x3; 4192 set_num_dcache(addr,r_vci_cmd_num_cache); 4193 4194 PRINTF(" * <CMD> DATA_UNC : %d - %llx\n",(uint32_t)r_vci_cmd_num_cache,(blob_t)(addr)); 4195 4196 p_vci_ini_rw.address = addr; 4197 switch( r_dcache_type_save[r_vci_cmd_num_cache] ) { 4198 case iss_t::DATA_READ: 4199 p_vci_ini_rw.wdata = 0; 4200 p_vci_ini_rw.be = r_dcache_be_save[r_vci_cmd_num_cache].read(); 4201 p_vci_ini_rw.cmd = vci_param::CMD_READ; 4202 break; 4203 case iss_t::DATA_LL: 4204 p_vci_ini_rw.wdata = 0; 4205 p_vci_ini_rw.be = 0xF; 4206 p_vci_ini_rw.cmd = vci_param::CMD_LOCKED_READ; 4207 break; 4208 default: 4209 ASSERT(false,"this should not happen"); 4210 } 4211 p_vci_ini_rw.plen = 4; 4212 p_vci_ini_rw.trdid = TYPE_DATA_UNC; // data cache uncached read 4213 p_vci_ini_rw.pktid = (sc_dt::sc_uint<vci_param::P>)r_vci_cmd_num_cache; 4214 p_vci_ini_rw.srcid = m_srcid_rw; 4215 p_vci_ini_rw.cons = false; 4216 p_vci_ini_rw.wrap = false; 4217 p_vci_ini_rw.contig = true; 4218 p_vci_ini_rw.clen = 0; 4219 p_vci_ini_rw.cfixed = false; 4220 p_vci_ini_rw.eop = true; 4221 4222 break; 4223 } 4224 case CMD_DATA_SC: 4225 { 4226 p_vci_ini_rw.cmdval = true; 4227 4228 addr_40 addr = (addr_40) r_dcache_addr_save[r_vci_cmd_num_cache].read() & ~0x3; 4229 set_num_dcache(addr,r_vci_cmd_num_cache); 4230 4231 PRINTF(" * <CMD> DATA_SC : %d - %llx\n",(uint32_t)r_vci_cmd_num_cache,(blob_t)(addr)); 4232 4233 p_vci_ini_rw.address = addr; 4234 if(r_vci_cmd_max.read() == 3){ 4235 ASSERT(false, "Not handled yet"); 4236 } else { // r_vci_cmd_cpt == 1 4237 switch(r_vci_cmd_cpt.read()){ 4238 case 0: 4239 p_vci_ini_rw.wdata = (uint32_t)(r_dcache_ll_data[r_vci_cmd_num_cache][r_dcache_num_cpu_save[r_vci_cmd_num_cache]].read() & 0xFFFFFFFF); 4240 break; 4241 case 1: 4242 p_vci_ini_rw.wdata = r_dcache_wdata_save[r_vci_cmd_num_cache].read(); 4243 break; 4244 } 4245 } 4246 p_vci_ini_rw.be = 0xF; 4247 p_vci_ini_rw.cmd = vci_param::CMD_STORE_COND; 4248 p_vci_ini_rw.plen = 4*(r_vci_cmd_max.read()+1); 4249 p_vci_ini_rw.trdid = TYPE_DATA_SC; // data cache uncached read 4250 p_vci_ini_rw.pktid = (sc_dt::sc_uint<vci_param::P>)r_vci_cmd_num_cache; 4251 p_vci_ini_rw.srcid = m_srcid_rw; 4252 p_vci_ini_rw.cons = true; 4253 p_vci_ini_rw.wrap = false; 4254 p_vci_ini_rw.contig = false; 4255 p_vci_ini_rw.clen = 0; 4256 p_vci_ini_rw.cfixed = false; 4257 p_vci_ini_rw.eop = (r_vci_cmd_cpt.read() == r_vci_cmd_max.read()); 4258 4259 break; 4260 } 4261 case CMD_DATA_WRITE: 4262 { 4263 p_vci_ini_rw.cmdval = true; 4264 4265 addr_40 addr = (addr_40) r_wbuf[r_vci_cmd_num_cache]->getAddress(r_vci_cmd_cpt)&~0x3; 4266 4267 PRINTF(" * <CMD> DATA_WRITE : %d - %llx\n",(uint32_t)r_vci_cmd_num_cache,(blob_t)(addr)); 4268 4269 p_vci_ini_rw.address = addr; 4270 p_vci_ini_rw.wdata = r_wbuf[r_vci_cmd_num_cache]->getData(r_vci_cmd_cpt); 4271 p_vci_ini_rw.be = r_wbuf[r_vci_cmd_num_cache]->getBe(r_vci_cmd_cpt); 4272 p_vci_ini_rw.plen = (r_vci_cmd_max - r_vci_cmd_min + 1)<<2; 4273 p_vci_ini_rw.cmd = vci_param::CMD_WRITE; 4274 p_vci_ini_rw.trdid = r_wbuf[r_vci_cmd_num_cache]->getIndex() + (1<<(vci_param::T-1)); 4275 p_vci_ini_rw.pktid = (sc_dt::sc_uint<vci_param::P>)r_vci_cmd_num_cache; 4276 p_vci_ini_rw.srcid = m_srcid_rw; 4277 p_vci_ini_rw.cons = false; 4278 p_vci_ini_rw.wrap = false; 4279 p_vci_ini_rw.contig = true; 4280 p_vci_ini_rw.clen = 0; 4281 p_vci_ini_rw.cfixed = false; 4282 p_vci_ini_rw.eop = (r_vci_cmd_cpt == r_vci_cmd_max); 4283 4284 break; 4285 } 4286 case CMD_DATA_MISS: 4287 { 4288 p_vci_ini_rw.cmdval = true; 4289 4290 addr_40 addr = r_dcache_addr_save[r_vci_cmd_num_cache].read() & (addr_40) m_dcache_yzmask; 4291 set_num_dcache(addr,r_vci_cmd_num_cache); 4292 4293 PRINTF(" * <CMD> DATA_MISS : %d - %llx\n",(uint32_t)r_vci_cmd_num_cache,(blob_t)(addr)); 4294 4295 p_vci_ini_rw.address = addr; 4296 p_vci_ini_rw.be = 0xF; 4297 p_vci_ini_rw.plen = m_dcache_words << 2; 4298 p_vci_ini_rw.cmd = vci_param::CMD_READ; 4299 p_vci_ini_rw.trdid = TYPE_DATA_MISS; // data cache cached read 4300 p_vci_ini_rw.pktid = (sc_dt::sc_uint<vci_param::P>)r_vci_cmd_num_cache; 4301 p_vci_ini_rw.srcid = m_srcid_rw; 4302 p_vci_ini_rw.cons = false; 4303 p_vci_ini_rw.wrap = false; 4304 p_vci_ini_rw.contig = true; 4305 p_vci_ini_rw.clen = 0; 4306 p_vci_ini_rw.cfixed = false; 4307 p_vci_ini_rw.eop = true; 4308 4309 break; 4310 } 4311 case CMD_INS_MISS: 4312 { 4313 p_vci_ini_rw.cmdval = true; 4314 4315 addr_40 addr = r_icache_addr_save[r_vci_cmd_num_cache].read() & (addr_40) m_icache_yzmask; 4316 set_num_icache(addr,r_vci_cmd_num_cache); 4317 4318 PRINTF(" * <CMD> INS_MISS : %d - %llx\n",(uint32_t)r_vci_cmd_num_cache,(blob_t)(addr)); 4319 4320 p_vci_ini_rw.address = addr; 4321 p_vci_ini_rw.be = 0xF; 4322 p_vci_ini_rw.plen = m_icache_words << 2; 4323 p_vci_ini_rw.cmd = vci_param::CMD_READ; 4324 p_vci_ini_rw.trdid = TYPE_INS_MISS; // ins cache cached read 4325 p_vci_ini_rw.pktid = (sc_dt::sc_uint<vci_param::P>)r_vci_cmd_num_cache; 4326 p_vci_ini_rw.srcid = m_srcid_rw; 4327 p_vci_ini_rw.cons = false; 4328 p_vci_ini_rw.wrap = false; 4329 p_vci_ini_rw.contig = true; 4330 p_vci_ini_rw.clen = 0; 4331 p_vci_ini_rw.cfixed = false; 4332 p_vci_ini_rw.eop = true; 4333 4334 break; 4335 } 4336 case CMD_INS_UNC: 4337 { 4338 p_vci_ini_rw.cmdval = true; 4339 4340 addr_40 addr = r_icache_addr_save[r_vci_cmd_num_cache].read() & ~0x3; 4341 set_num_icache(addr,r_vci_cmd_num_cache); 4342 4343 PRINTF(" * <CMD> INS_UNC : %d - %llx\n",(uint32_t)r_vci_cmd_num_cache,(blob_t)(addr)); 4344 4345 p_vci_ini_rw.address = addr; 4346 p_vci_ini_rw.be = 0xF; 4347 p_vci_ini_rw.plen = 4; 4348 p_vci_ini_rw.cmd = vci_param::CMD_READ; 4349 p_vci_ini_rw.trdid = TYPE_INS_UNC; // ins cache uncached read 4350 p_vci_ini_rw.pktid = (sc_dt::sc_uint<vci_param::P>)r_vci_cmd_num_cache; 4351 p_vci_ini_rw.srcid = m_srcid_rw; 4352 p_vci_ini_rw.cons = false; 4353 p_vci_ini_rw.wrap = false; 4354 p_vci_ini_rw.contig = true; 4355 p_vci_ini_rw.clen = 0; 4356 p_vci_ini_rw.cfixed = false; 4357 p_vci_ini_rw.eop = true; 4358 4359 break; 4360 } 4361 } // end switch r_vci_cmd_fsm 4362 4363 switch (r_vci_rsp_fsm.read() ) { 4364 case RSP_DATA_WRITE : p_vci_ini_rw.rspack = true; break; 4365 case RSP_INS_MISS : 4366 case RSP_INS_UNC : p_vci_ini_rw.rspack = r_vci_rsp_fifo_icache_data.wok(); break; 4367 case RSP_DATA_MISS : 4368 case RSP_DATA_UNC : 4369 case RSP_DATA_SC : p_vci_ini_rw.rspack = r_vci_rsp_fifo_dcache_data.wok(); break; 4370 case RSP_IDLE : 4371 default : p_vci_ini_rw.rspack = false; break; 4372 } // end switch r_vci_rsp_fsm 4373 4374 // VCI_TGT 4375 4376 // PRINTF(" * <TGT> srcid : %d\n", r_tgt_srcid.read()); 4377 4378 switch ( r_vci_tgt_fsm.read() ) { 4379 4380 case TGT_IDLE: 4381 case TGT_UPDT_WORD: 4382 case TGT_UPDT_DATA: 4383 p_vci_tgt.cmdack = true; 4384 p_vci_tgt.rspval = false; 4385 break; 4386 4387 case TGT_RSP_BROADCAST: 4388 { 4389 bool tgt_icache_req; 4390 bool tgt_icache_rsp; 4391 4392 #if (CC_XCACHE_WRAPPER_MULTI_CACHE==1) 4393 tgt_icache_req = r_tgt_icache_req[r_tgt_num_cache].read(); 4394 tgt_icache_rsp = r_tgt_icache_rsp[r_tgt_num_cache].read(); 4395 #elif (CC_XCACHE_WRAPPER_MULTI_CACHE==2) 4396 tgt_icache_req = false; 4397 tgt_icache_rsp = false; 4398 for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) 4399 { 4400 tgt_icache_req |= r_tgt_icache_req[num_cache].read(); 4401 tgt_icache_rsp |= r_tgt_icache_rsp[num_cache].read(); 4402 } 4403 #endif 4404 4405 bool rspval = ((not tgt_icache_req and not r_tgt_dcache_req[r_tgt_num_cache].read()) 4406 and (tgt_icache_rsp | r_tgt_dcache_rsp[r_tgt_num_cache])); 4407 4408 PRINTF(" * <TGT> RSP_BROADCAST : rspval : %d (i %d %d, d %d %d)\n",rspval,tgt_icache_req,tgt_icache_rsp, r_tgt_dcache_req[r_tgt_num_cache].read(), r_tgt_dcache_rsp[r_tgt_num_cache].read()); 4409 4410 p_vci_tgt.cmdack = false; 4411 p_vci_tgt.rspval = rspval; 4412 p_vci_tgt.rsrcid = r_tgt_srcid.read(); 4413 p_vci_tgt.rpktid = r_tgt_pktid.read(); 4414 p_vci_tgt.rtrdid = r_tgt_trdid.read(); 4415 p_vci_tgt.rdata = 0; 4416 p_vci_tgt.rerror = 0x2 & ( (1 << vci_param::E) - 1); // Write OK 4417 p_vci_tgt.reop = true; 4418 break; 4419 } 4420 case TGT_RSP_ICACHE: 4421 { 4422 bool rspval = not r_tgt_icache_req[r_tgt_num_cache].read() and r_tgt_icache_rsp[r_tgt_num_cache].read(); 4423 4424 PRINTF(" * <TGT> RSP_ICACHE : rspval : %d\n",rspval); 4425 4426 p_vci_tgt.cmdack = false; 4427 p_vci_tgt.rspval = rspval; 4428 p_vci_tgt.rsrcid = r_tgt_srcid.read(); 4429 p_vci_tgt.rpktid = r_tgt_pktid.read(); 4430 p_vci_tgt.rtrdid = r_tgt_trdid.read(); 4431 p_vci_tgt.rdata = 0; 4432 p_vci_tgt.rerror = 0x2 & ( (1 << vci_param::E) - 1); // Write OK 4433 p_vci_tgt.reop = true; 4434 break; 4435 } 4436 case TGT_RSP_DCACHE: 4437 { 4438 bool rspval = not r_tgt_dcache_req[r_tgt_num_cache].read() and r_tgt_dcache_rsp[r_tgt_num_cache].read(); 4439 4440 PRINTF(" * <TGT> RSP_DCACHE : rspval : %d\n",rspval); 4441 4442 p_vci_tgt.cmdack = false; 4443 p_vci_tgt.rspval = rspval; 4444 p_vci_tgt.rsrcid = r_tgt_srcid.read(); 4445 p_vci_tgt.rpktid = r_tgt_pktid.read(); 4446 p_vci_tgt.rtrdid = r_tgt_trdid.read(); 4447 p_vci_tgt.rdata = 0; 4448 p_vci_tgt.rerror = 0x2 & ( (1 << vci_param::E) - 1); // Write OK 4449 p_vci_tgt.reop = true; 4450 break; 4451 } 4452 case TGT_REQ_BROADCAST: 4453 case TGT_REQ_ICACHE: 4454 case TGT_REQ_DCACHE: 4455 p_vci_tgt.cmdack = false; 4456 p_vci_tgt.rspval = false; 4457 break; 4458 4459 } // end switch TGT_FSM 4460 } // end genMoore() 2477 case CMD_IDLE: 2478 { 2479 p_vci_ini_d.cmdval = false; 2480 p_vci_ini_d.address = 0; 2481 p_vci_ini_d.wdata = 0; 2482 p_vci_ini_d.be = 0; 2483 p_vci_ini_d.plen = 0; 2484 p_vci_ini_d.cmd = vci_param::CMD_NOP; 2485 p_vci_ini_d.trdid = 0; 2486 p_vci_ini_d.pktid = 0; 2487 p_vci_ini_d.srcid = 0; 2488 p_vci_ini_d.cons = false; 2489 p_vci_ini_d.wrap = false; 2490 p_vci_ini_d.contig = false; 2491 p_vci_ini_d.clen = 0; 2492 p_vci_ini_d.cfixed = false; 2493 p_vci_ini_d.eop = false; 2494 break; 2495 } 2496 case CMD_DATA_UNC: 2497 { 2498 p_vci_ini_d.cmdval = true; 2499 p_vci_ini_d.address = (vci_addr_t) r_dcache_addr_save.read() & ~0x3; 2500 p_vci_ini_d.wdata = 0; 2501 p_vci_ini_d.be = r_dcache_be_save.read(); 2502 p_vci_ini_d.cmd = vci_param::CMD_READ; 2503 p_vci_ini_d.plen = 4; 2504 p_vci_ini_d.trdid = TYPE_DATA_UNC; 2505 p_vci_ini_d.pktid = 0; 2506 p_vci_ini_d.srcid = m_srcid_d; 2507 p_vci_ini_d.cons = false; 2508 p_vci_ini_d.wrap = false; 2509 p_vci_ini_d.contig = true; 2510 p_vci_ini_d.clen = 0; 2511 p_vci_ini_d.cfixed = false; 2512 p_vci_ini_d.eop = true; 2513 break; 2514 } 2515 case CMD_DATA_SC: 2516 { 2517 p_vci_ini_d.cmdval = true; 2518 p_vci_ini_d.address = (vci_addr_t)r_dcache_addr_save.read() & ~0x3; 2519 if ( r_vci_cmd_cpt.read() == 0 ) p_vci_ini_d.wdata = r_dcache_ll_data.read(); 2520 else p_vci_ini_d.wdata = r_dcache_wdata_save.read(); 2521 p_vci_ini_d.be = 0xF; 2522 p_vci_ini_d.cmd = vci_param::CMD_STORE_COND; 2523 p_vci_ini_d.plen = 8; 2524 p_vci_ini_d.trdid = TYPE_DATA_UNC; 2525 p_vci_ini_d.pktid = 0; 2526 p_vci_ini_d.srcid = m_srcid_d; 2527 p_vci_ini_d.cons = true; 2528 p_vci_ini_d.wrap = false; 2529 p_vci_ini_d.contig = false; 2530 p_vci_ini_d.clen = 0; 2531 p_vci_ini_d.cfixed = false; 2532 p_vci_ini_d.eop = (r_vci_cmd_cpt.read() == 1); 2533 break; 2534 } 2535 case CMD_DATA_WRITE: 2536 { 2537 p_vci_ini_d.cmdval = true; 2538 p_vci_ini_d.address = (vci_addr_t)r_wbuf->getAddress(r_vci_cmd_cpt.read())&~0x3; 2539 p_vci_ini_d.wdata = r_wbuf->getData(r_vci_cmd_cpt.read()); 2540 p_vci_ini_d.be = r_wbuf->getBe(r_vci_cmd_cpt.read()); 2541 p_vci_ini_d.plen = (r_vci_cmd_max - r_vci_cmd_min + 1)<<2; 2542 p_vci_ini_d.cmd = vci_param::CMD_WRITE; 2543 p_vci_ini_d.trdid = r_wbuf->getIndex() + (1<<(vci_param::T-1)); 2544 p_vci_ini_d.pktid = 0; 2545 p_vci_ini_d.srcid = m_srcid_d; 2546 p_vci_ini_d.cons = false; 2547 p_vci_ini_d.wrap = false; 2548 p_vci_ini_d.contig = true; 2549 p_vci_ini_d.clen = 0; 2550 p_vci_ini_d.cfixed = false; 2551 p_vci_ini_d.eop = (r_vci_cmd_cpt.read() == r_vci_cmd_max.read()); 2552 break; 2553 } 2554 case CMD_DATA_MISS: 2555 { 2556 p_vci_ini_d.cmdval = true; 2557 p_vci_ini_d.address = (vci_addr_t)r_dcache_addr_save.read() & (vci_addr_t)m_cache_yzmask; 2558 p_vci_ini_d.be = 0xF; 2559 p_vci_ini_d.plen = m_cache_words << 2; 2560 p_vci_ini_d.cmd = vci_param::CMD_READ; 2561 p_vci_ini_d.trdid = TYPE_DATA_MISS; 2562 p_vci_ini_d.pktid = 0; 2563 p_vci_ini_d.srcid = m_srcid_d; 2564 p_vci_ini_d.cons = false; 2565 p_vci_ini_d.wrap = false; 2566 p_vci_ini_d.contig = true; 2567 p_vci_ini_d.clen = 0; 2568 p_vci_ini_d.cfixed = false; 2569 p_vci_ini_d.eop = true; 2570 break; 2571 } 2572 case CMD_INS_MISS: 2573 { 2574 p_vci_ini_d.cmdval = true; 2575 p_vci_ini_d.address = (vci_addr_t)r_icache_addr_save.read() & (vci_addr_t)m_cache_yzmask; 2576 p_vci_ini_d.be = 0xF; 2577 p_vci_ini_d.plen = m_cache_words << 2; 2578 p_vci_ini_d.cmd = vci_param::CMD_READ; 2579 p_vci_ini_d.trdid = TYPE_INS_MISS; 2580 p_vci_ini_d.pktid = 0; 2581 p_vci_ini_d.srcid = m_srcid_d; 2582 p_vci_ini_d.cons = false; 2583 p_vci_ini_d.wrap = false; 2584 p_vci_ini_d.contig = true; 2585 p_vci_ini_d.clen = 0; 2586 p_vci_ini_d.cfixed = false; 2587 p_vci_ini_d.eop = true; 2588 break; 2589 } 2590 case CMD_INS_UNC: 2591 { 2592 p_vci_ini_d.cmdval = true; 2593 p_vci_ini_d.address = (vci_addr_t)r_icache_addr_save.read() & ~0x3; 2594 p_vci_ini_d.be = 0xF; 2595 p_vci_ini_d.plen = 4; 2596 p_vci_ini_d.cmd = vci_param::CMD_READ; 2597 p_vci_ini_d.trdid = TYPE_INS_UNC; 2598 p_vci_ini_d.pktid = 0; 2599 p_vci_ini_d.srcid = m_srcid_d; 2600 p_vci_ini_d.cons = false; 2601 p_vci_ini_d.wrap = false; 2602 p_vci_ini_d.contig = true; 2603 p_vci_ini_d.clen = 0; 2604 p_vci_ini_d.cfixed = false; 2605 p_vci_ini_d.eop = true; 2606 break; 2607 } 2608 } // end switch r_vci_cmd_fsm 2609 2610 /////////////////////////////////////////////// 2611 // VCI initiator response on the direct network 2612 switch (r_vci_rsp_fsm.read() ) 2613 { 2614 case RSP_DATA_WRITE : p_vci_ini_d.rspack = true; break; 2615 case RSP_INS_MISS : 2616 case RSP_INS_UNC : p_vci_ini_d.rspack = r_vci_rsp_fifo_icache.wok(); break; 2617 case RSP_DATA_MISS : 2618 case RSP_DATA_UNC : 2619 case RSP_DATA_SC : p_vci_ini_d.rspack = r_vci_rsp_fifo_dcache.wok(); break; 2620 case RSP_IDLE : 2621 default : p_vci_ini_d.rspack = false; break; 2622 } // end switch r_vci_rsp_fsm 2623 2624 //////////////////////////////////////////////////////////// 2625 // VCI target command and response on the coherence network 2626 switch ( r_tgt_fsm.read() ) 2627 { 2628 case TGT_IDLE: 2629 case TGT_UPDT_WORD: 2630 case TGT_UPDT_DATA: 2631 { 2632 p_vci_tgt_c.cmdack = true; 2633 p_vci_tgt_c.rspval = false; 2634 break; 2635 } 2636 case TGT_RSP_BROADCAST: 2637 { 2638 p_vci_tgt_c.cmdack = false; 2639 p_vci_tgt_c.rspval = (not r_tgt_icache_req.read() and not r_tgt_dcache_req.read()) 2640 and (r_tgt_icache_rsp.read() or r_tgt_dcache_rsp.read()); 2641 p_vci_tgt_c.rsrcid = r_tgt_srcid.read(); 2642 p_vci_tgt_c.rpktid = r_tgt_pktid.read(); 2643 p_vci_tgt_c.rtrdid = r_tgt_trdid.read(); 2644 p_vci_tgt_c.rdata = 0; 2645 p_vci_tgt_c.rerror = 0; 2646 p_vci_tgt_c.reop = true; 2647 break; 2648 } 2649 case TGT_RSP_ICACHE: 2650 { 2651 p_vci_tgt_c.cmdack = false; 2652 p_vci_tgt_c.rspval = not r_tgt_icache_req.read() and r_tgt_icache_rsp.read(); 2653 p_vci_tgt_c.rsrcid = r_tgt_srcid.read(); 2654 p_vci_tgt_c.rpktid = r_tgt_pktid.read(); 2655 p_vci_tgt_c.rtrdid = r_tgt_trdid.read(); 2656 p_vci_tgt_c.rdata = 0; 2657 p_vci_tgt_c.rerror = 0; 2658 p_vci_tgt_c.reop = true; 2659 break; 2660 } 2661 case TGT_RSP_DCACHE: 2662 { 2663 p_vci_tgt_c.cmdack = false; 2664 p_vci_tgt_c.rspval = not r_tgt_dcache_req.read() and r_tgt_dcache_rsp.read(); 2665 p_vci_tgt_c.rsrcid = r_tgt_srcid.read(); 2666 p_vci_tgt_c.rpktid = r_tgt_pktid.read(); 2667 p_vci_tgt_c.rtrdid = r_tgt_trdid.read(); 2668 p_vci_tgt_c.rdata = 0; 2669 p_vci_tgt_c.rerror = 0; 2670 p_vci_tgt_c.reop = true; 2671 break; 2672 } 2673 case TGT_REQ_BROADCAST: 2674 case TGT_REQ_ICACHE: 2675 case TGT_REQ_DCACHE: 2676 { 2677 p_vci_tgt_c.cmdack = false; 2678 p_vci_tgt_c.rspval = false; 2679 break; 2680 } 2681 } // end switch TGT_FSM 2682 } // end genMoore() 4461 2683 4462 ////////////////////////////////////////////////////////////////////////////////// 4463 tmpl(void)::stop_simulation (uint32_t nb_frz_cycles) 4464 ////////////////////////////////////////////////////////////////////////////////// 4465 { 4466 #if CC_XCACHE_WRAPPER_STOP_SIMULATION 4467 if (nb_frz_cycles == 0) 4468 { 4469 PRINTF("CC_XCACHE_WRAPPER \"%s\" : don't stop the simulation.\n",name().c_str()); 4470 m_stop_simulation = false; 4471 } 4472 else 4473 { 4474 PRINTF("CC_XCACHE_WRAPPER \"%s\" : stop the simulation after %d cycles.\n",name().c_str(),nb_frz_cycles); 4475 m_stop_simulation = true; 4476 m_stop_simulation_nb_frz_cycles_max = nb_frz_cycles; 4477 } 4478 #else 4479 std::cout << "CC_XCACHE_WRAPPER \"" << name() << "\" : flag CC_XCACHE_WRAPPER_STOP_SIMULATION is unset, you can't use stop_simulation." << std::endl; 4480 #endif // CC_XCACHE_WRAPPER_STOP_SIMULATION 4481 4482 } 4483 4484 ////////////////////////////////////////////////////////////////////////////////// 4485 tmpl(void)::log_transaction ( bool generate_file_icache 4486 ,bool generate_file_dcache 4487 ,bool generate_file_cmd 4488 ,bool generate_file_tgt 4489 ,bool generate_file_cleanup) 4490 ////////////////////////////////////////////////////////////////////////////////// 4491 { 4492 #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION 4493 generate_log_transaction_file_icache = generate_file_icache ; 4494 generate_log_transaction_file_dcache = generate_file_dcache ; 4495 generate_log_transaction_file_cmd = generate_file_cmd ; 4496 generate_log_transaction_file_tgt = generate_file_tgt ; 4497 generate_log_transaction_file_cleanup = generate_file_cleanup; 4498 #else 4499 std::cout << "CC_XCACHE_WRAPPER \"" << name() << "\" : flag CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION is unset, you can't use log_transaction." << std::endl; 4500 #endif // CC_XCACHE_WRAPPER_STOP_SIMULATION 4501 4502 } 4503 4504 ////////////////////////////////////////////////////////////////////////////////// 4505 tmpl(void)::vhdl_testbench (bool generate_file_mwbuf) 4506 ////////////////////////////////////////////////////////////////////////////////// 4507 { 4508 #if MWBUF_VHDL_TESTBENCH 4509 if (simulation_started) 4510 std::cout << "CC_XCACHE_WRAPPER \"" << name() << "\" : Simulation is starting, you can't use vhdl_testbench." << std::endl; 4511 else 4512 generate_vhdl_testbench_mwbuf = generate_file_mwbuf; 4513 #else 4514 std::cout << "CC_XCACHE_WRAPPER \"" << name() << "\" : flag MWBUF_VHDL_TESTBENCH is unset, you can't use vhdl_testbench." << std::endl; 4515 #endif // CC_XCACHE_WRAPPER_STOP_SIMULATION 4516 } 4517 4518 ////////////////////////////////////////////////////////////////////////////////// 4519 tmpl(uint32_t)::get_num_cache(addr_40 & addr) 4520 ////////////////////////////////////////////////////////////////////////////////// 4521 { 4522 uint32_t num_cache = get_num_cache_only(addr); 4523 4524 addr = ((addr&m_num_cache_LSB_mask) | // keep LSB 4525 ((addr>>m_num_cache_MSB)<<m_num_cache_LSB)); // set MSB 4526 4527 return num_cache; 4528 } 4529 4530 ////////////////////////////////////////////////////////////////////////////////// 4531 tmpl(uint32_t)::get_num_cache_only(addr_40 addr) 4532 ////////////////////////////////////////////////////////////////////////////////// 4533 { 4534 return (addr>>m_num_cache_LSB)&m_num_cache_mask; 4535 } 4536 4537 ////////////////////////////////////////////////////////////////////////////////// 4538 tmpl(void)::set_num_cache(addr_40 & addr, uint32_t num_cache) 4539 ////////////////////////////////////////////////////////////////////////////////// 4540 { 4541 addr = ((addr&m_num_cache_LSB_mask) | // keep LSB 4542 ((addr_40)num_cache << m_num_cache_LSB) | 4543 ((addr>>m_num_cache_LSB)<<m_num_cache_MSB)); // set MSB 4544 } 4545 4546 ////////////////////////////////////////////////////////////////////////////////// 4547 // FIXME : mettre le type addr_40 4548 tmpl(sc_dt::sc_uint<40>)::set_num_cache_only(addr_40 addr, uint32_t num_cache) 4549 ////////////////////////////////////////////////////////////////////////////////// 4550 { 4551 return ((addr&m_num_cache_LSB_mask) | // keep LSB 4552 ((addr_40)num_cache << m_num_cache_LSB) | 4553 ((addr>>m_num_cache_LSB)<<m_num_cache_MSB)); // set MSB 4554 } 4555 4556 4557 }} // end namespace 2684 2685 }} // end namespace 4558 2686 4559 2687 // Local Variables:
Note: See TracChangeset
for help on using the changeset viewer.