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 | } |
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 | } |
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 |
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(); |
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() ) |