201 | | : |
202 | | soclib::caba::BaseModule(name), |
203 | | |
204 | | p_clk ("clk"), |
205 | | p_resetn ("resetn"), |
206 | | p_vci_ini_rw("vci_ini_rw"), |
207 | | p_vci_ini_c ("vci_ini_c"), |
208 | | p_vci_tgt ("vci_tgt"), |
209 | | |
210 | | m_cacheability_table(mtp.getCacheabilityTable<vci_addr_t>()), |
211 | | m_segment(mtc.getSegment(target_index)), |
212 | | m_iss(this->name(), proc_id), |
213 | | m_srcid_rw(mtp.indexForId(initiator_index_rw)), |
214 | | m_srcid_c(mtc.indexForId(initiator_index_c)), |
215 | | |
216 | | m_dcache_ways(dcache_ways), |
217 | | m_dcache_words(dcache_words), |
218 | | m_dcache_words_shift(uint32_log2(dcache_words)+2), |
219 | | m_dcache_yzmask((~0)<<m_dcache_words_shift), |
220 | | m_icache_ways(icache_ways), |
221 | | m_icache_words(icache_words), |
222 | | m_icache_words_shift(uint32_log2(icache_words)+2), |
223 | | m_icache_yzmask((~0)<<m_icache_words_shift), |
224 | | m_cache_words((dcache_words)?dcache_words:icache_words), |
225 | | |
226 | | r_dcache_fsm("r_dcache_fsm"), |
227 | | r_dcache_fsm_save("r_dcache_fsm_save"), |
228 | | r_dcache_addr_save("r_dcache_addr_save"), |
229 | | r_dcache_wdata_save("r_dcache_wdata_save"), |
230 | | r_dcache_rdata_save("r_dcache_rdata_save"), |
231 | | r_dcache_type_save("r_dcache_type_save"), |
232 | | r_dcache_be_save("r_dcache_be_save"), |
233 | | r_dcache_cached_save("r_dcache_cached_save"), |
234 | | r_dcache_cleanup_req("r_dcache_cleanup_req"), |
235 | | r_dcache_cleanup_line("r_dcache_cleanup_line"), |
236 | | r_dcache_miss_req("r_dcache_miss_req"), |
237 | | r_dcache_miss_way("r_dcache_miss_way"), |
238 | | r_dcache_miss_set("r_dcache_miss_set"), |
239 | | r_dcache_unc_req("r_dcache_unc_req"), |
240 | | r_dcache_sc_req("r_dcache_sc_req"), |
241 | | r_dcache_inval_rsp("r_dcache_inval_rsp"), |
242 | | r_dcache_update_addr("r_dcache_update_addr"), |
243 | | r_dcache_ll_data("r_dcache_ll_data"), |
244 | | r_dcache_ll_addr("r_dcache_ll_addr"), |
245 | | r_dcache_ll_valid("r_dcache_ll_valid"), |
246 | | r_dcache_previous_unc("r_dcache_previous_unc"), |
247 | | |
248 | | r_icache_fsm("r_icache_fsm"), |
249 | | r_icache_fsm_save("r_icache_fsm_save"), |
250 | | r_icache_addr_save("r_icache_addr_save"), |
251 | | r_icache_miss_req("r_icache_miss_req"), |
252 | | r_icache_miss_way("r_icache_miss_way"), |
253 | | r_icache_miss_set("r_icache_miss_set"), |
254 | | r_icache_unc_req("r_icache_unc_req"), |
255 | | r_icache_cleanup_req("r_icache_cleanup_req"), |
256 | | r_icache_cleanup_line("r_icache_cleanup_line"), |
257 | | r_icache_inval_rsp("r_icache_inval_rsp"), |
258 | | r_icache_update_addr("r_icache_update_addr"), |
259 | | |
260 | | r_vci_cmd_fsm("r_vci_cmd_fsm"), |
261 | | r_vci_cmd_min("r_vci_cmd_min"), |
262 | | r_vci_cmd_max("r_vci_cmd_max"), |
263 | | r_vci_cmd_cpt("r_vci_cmd_cpt"), |
264 | | r_vci_cmd_dcache_prior("r_vci_cmd_dcache_prior"), |
265 | | |
266 | | r_vci_rsp_fsm("r_vci_rsp_fsm"), |
267 | | r_vci_rsp_ins_error("r_vci_rsp_ins_error"), |
268 | | r_vci_rsp_data_error("r_vci_rsp_data_error"), |
269 | | r_vci_rsp_cpt("r_vci_rsp_cpt"), |
270 | | r_vci_rsp_ack("r_vci_rsp_ack"), |
271 | | |
272 | | r_icache_buf_unc_valid("r_icache_buf_unc_valid"), |
273 | | |
274 | | #if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE |
275 | | r_cache_word("r_cache_word"), |
| 202 | : |
| 203 | soclib::caba::BaseModule(name), |
| 204 | |
| 205 | p_clk ("clk"), |
| 206 | p_resetn ("resetn"), |
| 207 | p_vci_ini_rw("vci_ini_rw"), |
| 208 | p_vci_ini_c ("vci_ini_c"), |
| 209 | p_vci_tgt ("vci_tgt"), |
| 210 | |
| 211 | m_cacheability_table(mtp.getCacheabilityTable<vci_addr_t>()), |
| 212 | m_segment(mtc.getSegment(target_index)), |
| 213 | m_srcid_rw(mtp.indexForId(initiator_index_rw)), |
| 214 | m_srcid_c(mtc.indexForId(initiator_index_c)), |
| 215 | |
| 216 | m_nb_cpu(nb_cpu), |
| 217 | #if (CC_XCACHE_WRAPPER_MULTI_CACHE==1) |
| 218 | m_nb_icache(nb_dcache), |
| 219 | #elif (CC_XCACHE_WRAPPER_MULTI_CACHE==2) |
| 220 | m_nb_icache(m_nb_cpu), |
277 | | |
278 | | r_vci_tgt_fsm("r_vci_tgt_fsm"), |
279 | | r_tgt_addr("r_tgt_addr"), |
280 | | r_tgt_word("r_tgt_word"), |
281 | | r_tgt_update("r_tgt_update"), |
282 | | r_tgt_update_data("r_tgt_update_data"), |
283 | | // r_tgt_brdcast("r_tgt_brdcast"), |
284 | | r_tgt_srcid("r_tgt_srcid"), |
285 | | r_tgt_pktid("r_tgt_pktid"), |
286 | | r_tgt_trdid("r_tgt_trdid"), |
287 | | // r_tgt_plen("r_tgt_plen"), |
288 | | r_tgt_icache_req("r_tgt_icache_req"), |
289 | | r_tgt_dcache_req("r_tgt_dcache_req"), |
290 | | r_tgt_icache_rsp("r_tgt_icache_rsp"), |
291 | | r_tgt_dcache_rsp("r_tgt_dcache_rsp"), |
292 | | |
293 | | r_cleanup_fsm("r_cleanup_fsm"), |
294 | | |
295 | | r_wbuf("r_wbuf", wbuf_nwords, wbuf_nlines, wbuf_timeout, dcache_words), |
296 | | r_icache("icache", icache_ways, icache_sets, icache_words), |
297 | | r_dcache("dcache", dcache_ways, dcache_sets, dcache_words) |
298 | | { |
299 | | // Size of word is 32 bits |
300 | | ASSERT( (icache_words*vci_param::B) < (1<<vci_param::K), |
301 | | "I need more PLEN bits"); |
302 | | |
303 | | ASSERT( (vci_param::T > 2) and ((1<<(vci_param::T-1)) >= wbuf_nlines), |
304 | | "I need more TRDID bits"); |
305 | | |
306 | | CACHE_MISS_BUF_ALLOC; |
307 | | |
308 | | r_tgt_buf = new data_t[m_cache_words]; |
309 | | r_tgt_be = new be_t [m_cache_words]; |
310 | | |
311 | | SC_METHOD(transition); |
312 | | dont_initialize(); |
313 | | sensitive << p_clk.pos(); |
314 | | |
315 | | SC_METHOD(genMoore); |
316 | | dont_initialize(); |
317 | | sensitive << p_clk.neg(); |
318 | | |
319 | | |
320 | | typename iss_t::CacheInfo cache_info; |
321 | | cache_info.has_mmu = false; |
322 | | cache_info.icache_line_size = icache_words*sizeof(data_t); |
323 | | cache_info.icache_assoc = icache_ways; |
324 | | cache_info.icache_n_lines = icache_sets; |
325 | | cache_info.dcache_line_size = dcache_words*sizeof(data_t); |
326 | | cache_info.dcache_assoc = dcache_ways; |
327 | | cache_info.dcache_n_lines = dcache_sets; |
328 | | m_iss.setCacheInfo(cache_info); |
329 | | |
| 222 | m_nb_dcache(nb_dcache), |
| 223 | m_nb_cache((m_nb_dcache>m_nb_icache)?m_nb_dcache:m_nb_icache), |
| 224 | m_dcache_ways(dcache_ways), |
| 225 | m_dcache_words(dcache_words), |
| 226 | m_dcache_words_shift(uint32_log2(dcache_words)+uint32_log2(sizeof(data_t))), |
| 227 | m_dcache_yzmask((~0)<<m_dcache_words_shift), |
| 228 | m_icache_ways(icache_ways), |
| 229 | m_icache_words(icache_words), |
| 230 | m_icache_words_shift(uint32_log2(icache_words)+uint32_log2(sizeof(data_t))), |
| 231 | m_icache_yzmask((~0)<<m_icache_words_shift), |
| 232 | m_write_policy(write_policy), |
| 233 | m_cache_words((dcache_words)?dcache_words:icache_words), |
| 234 | |
| 235 | r_cpu_prior("r_cpu_prior"), |
| 236 | |
| 237 | r_vci_cmd_fsm("r_vci_cmd_fsm"), |
| 238 | r_vci_cmd_min("r_vci_cmd_min"), |
| 239 | r_vci_cmd_max("r_vci_cmd_max"), |
| 240 | r_vci_cmd_cpt("r_vci_cmd_cpt"), |
| 241 | r_vci_cmd_dcache_prior("r_vci_cmd_dcache_prior"), |
| 242 | r_vci_cmd_num_icache_prior("r_vci_cmd_num_icache_prior"), |
| 243 | r_vci_cmd_num_dcache_prior("r_vci_cmd_num_dcache_prior"), |
| 244 | r_vci_cmd_num_cache("r_vci_cmd_num_cache"), |
| 245 | |
| 246 | r_vci_rsp_fsm("r_vci_rsp_fsm"), |
| 247 | r_vci_rsp_cpt("r_vci_rsp_cpt"), |
| 248 | r_vci_rsp_num_cache("r_vci_rsp_num_cache"), |
| 249 | |
| 250 | r_vci_rsp_fifo_icache_data ("r_vci_rsp_fifo_icache_data" ,2), |
| 251 | r_vci_rsp_fifo_icache_num_cache ("r_vci_rsp_fifo_icache_num_cache",2), |
| 252 | r_vci_rsp_fifo_dcache_data ("r_vci_rsp_fifo_dcache_data" ,2), |
| 253 | r_vci_rsp_fifo_dcache_num_cache ("r_vci_rsp_fifo_dcache_num_cache",2), |
| 254 | |
| 255 | r_cache_word("r_cache_word"), |
| 256 | |
| 257 | r_vci_tgt_fsm("r_vci_tgt_fsm"), |
| 258 | r_tgt_iaddr("r_tgt_iaddr"), |
| 259 | r_tgt_daddr("r_tgt_daddr"), |
| 260 | r_tgt_word("r_tgt_word"), |
| 261 | r_tgt_update("r_tgt_update"), |
| 262 | r_tgt_update_data("r_tgt_update_data"), |
| 263 | // r_tgt_brdcast("r_tgt_brdcast"), |
| 264 | r_tgt_srcid("r_tgt_srcid"), |
| 265 | r_tgt_pktid("r_tgt_pktid"), |
| 266 | r_tgt_trdid("r_tgt_trdid"), |
| 267 | // r_tgt_plen("r_tgt_plen"), |
| 268 | r_tgt_num_cache("r_tgt_num_cache"), |
| 269 | |
| 270 | r_cleanup_fsm("r_cleanup_fsm"), |
| 271 | r_cleanup_num_cache("r_cleanup_num_cache"), |
| 272 | r_cleanup_icache("r_cleanup_icache"), |
| 273 | |
| 274 | m_num_cache_LSB(uint32_log2(icache_words) + uint32_log2(sizeof(data_t))), |
| 275 | m_num_cache_MSB(uint32_log2(nb_dcache) + m_num_cache_LSB) |
| 276 | { |
| 277 | // Size of word is 32 bits |
| 278 | ASSERT((icache_words*vci_param::B) < (1<<vci_param::K), |
| 279 | "Need more PLEN bits."); |
| 280 | |
| 281 | ASSERT((vci_param::T > 2) and ((1<<(vci_param::T-1)) >= (wbuf_nlines/m_nb_dcache)), |
| 282 | "Need more TRDID bits."); |
| 283 | |
| 284 | ASSERT(uint32_log2(nb_dcache) <= (1<<vci_param::P), |
| 285 | "Need more PKTID bits."); |
| 286 | |
| 287 | ASSERT(IS_POW_OF_2(m_nb_dcache), |
| 288 | "nb_dcache must be a power of 2."); |
| 289 | |
| 290 | ASSERT(IS_POW_OF_2(m_nb_cpu) and (m_nb_cpu <= m_nb_dcache) and (m_nb_cpu > 0), |
| 291 | "nb cpu must be a multiple of nb cache."); |
| 292 | |
| 293 | ASSERT(IS_POW_OF_2(m_icache_ways) and (m_nb_icache <= m_icache_ways), |
| 294 | "nb icache ways must be a multiple of nb cache."); |
| 295 | |
| 296 | ASSERT(IS_POW_OF_2(m_dcache_ways) and (m_nb_dcache <= m_dcache_ways), |
| 297 | "nb dcache ways must be a multiple of nb cache."); |
| 298 | |
| 299 | ASSERT(icache_words == dcache_words, |
| 300 | "icache_words must be equal at dcache_words."); |
| 301 | |
| 302 | ASSERT(IS_POW_OF_2(wbuf_nlines) and (m_nb_dcache <= wbuf_nlines), |
| 303 | "wbuf_nlines must be a multiple of nb cache."); |
| 304 | |
| 305 | // FIXME : s'adapter à la taille des requêtes XTN_READ/XTN_WRITE |
| 306 | ASSERT((m_nb_dcache == 1) or (dcache_words >= 16), |
| 307 | "When multi cache is activated, need 4 bits (16 word) to the cache set ."); |
| 308 | |
| 309 | if (m_nb_cpu > 1) |
| 310 | ASSERT(CC_XCACHE_MULTI_CPU!=0, |
| 311 | "Macro CC_XCACHE_MULTI_CPU in wbuf must be set at 1."); |
| 312 | |
| 313 | p_irq = new sc_in<bool> * [m_nb_cpu]; |
| 314 | for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) |
| 315 | p_irq [num_cpu] = new sc_in<bool> [iss_t::n_irq]; |
| 316 | |
| 317 | m_iss = new iss_t * [m_nb_cpu]; |
| 318 | for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) |
| 319 | { |
| 320 | std::ostringstream iss_name(""); |
| 321 | iss_name << this->name() << "_" << num_cpu; |
| 322 | |
| 323 | m_iss[num_cpu] = new iss_t (iss_name.str().c_str(), proc_id+num_cpu); |
| 324 | } |
| 325 | |
| 326 | r_icache_lock = new sc_signal<uint32_t>[m_nb_icache]; |
| 327 | r_dcache_lock = new sc_signal<uint32_t>[m_nb_dcache]; |
| 328 | r_dcache_sync = new sc_signal<bool> [m_nb_dcache]; |
| 329 | |
| 330 | r_icache_fsm = new sc_signal<int> [m_nb_icache]; |
| 331 | r_icache_fsm_save = new sc_signal<int> [m_nb_icache]; |
| 332 | r_icache_addr_save = new sc_signal<addr_40> [m_nb_icache]; |
| 333 | r_icache_miss_req = new sc_signal<bool> [m_nb_icache]; |
| 334 | r_icache_miss_way = new sc_signal<size_t> [m_nb_icache]; |
| 335 | r_icache_miss_set = new sc_signal<size_t> [m_nb_icache]; |
| 336 | r_icache_unc_req = new sc_signal<bool> [m_nb_icache]; |
| 337 | r_icache_cleanup_req = new sc_signal<bool> [m_nb_icache]; |
| 338 | r_icache_cleanup_line = new sc_signal<addr_40> [m_nb_icache]; |
| 339 | r_icache_inval_rsp = new sc_signal<bool> [m_nb_icache]; |
| 340 | r_icache_update_addr = new sc_signal<size_t> [m_nb_icache]; |
| 341 | r_icache_buf_unc_valid = new sc_signal<bool> [m_nb_icache]; |
| 342 | |
| 343 | r_dcache_fsm = new sc_signal<int> [m_nb_dcache]; |
| 344 | r_dcache_fsm_save = new sc_signal<int> [m_nb_dcache]; |
| 345 | r_dcache_addr_save = new sc_signal<addr_40> [m_nb_dcache]; |
| 346 | r_dcache_wdata_save = new sc_signal<data_t> [m_nb_dcache]; |
| 347 | r_dcache_rdata_save = new sc_signal<data_t> [m_nb_dcache]; |
| 348 | r_dcache_type_save = new sc_signal<int> [m_nb_dcache]; |
| 349 | r_dcache_be_save = new sc_signal<be_t> [m_nb_dcache]; |
| 350 | r_dcache_cached_save = new sc_signal<bool> [m_nb_dcache]; |
| 351 | r_dcache_num_cpu_save = new sc_signal<uint32_t>[m_nb_dcache]; |
| 352 | r_dcache_cleanup_req = new sc_signal<bool> [m_nb_dcache]; |
| 353 | r_dcache_cleanup_line = new sc_signal<addr_40> [m_nb_dcache]; |
| 354 | r_dcache_miss_req = new sc_signal<bool> [m_nb_dcache]; |
| 355 | r_dcache_miss_way = new sc_signal<size_t> [m_nb_dcache]; |
| 356 | r_dcache_miss_set = new sc_signal<size_t> [m_nb_dcache]; |
| 357 | r_dcache_unc_req = new sc_signal<bool> [m_nb_dcache]; |
| 358 | r_dcache_sc_req = new sc_signal<bool> [m_nb_dcache]; |
| 359 | r_dcache_inval_rsp = new sc_signal<bool> [m_nb_dcache]; |
| 360 | r_dcache_update_addr = new sc_signal<size_t> [m_nb_dcache]; |
| 361 | r_dcache_previous_unc = new sc_signal<bool> [m_nb_dcache]; |
| 362 | |
| 363 | r_dcache_ll_data = new sc_signal<data_t> * [m_nb_dcache]; |
| 364 | r_dcache_ll_addr = new sc_signal<addr_40> * [m_nb_dcache]; |
| 365 | r_dcache_ll_valid = new sc_signal<bool> * [m_nb_dcache]; |
| 366 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 367 | { |
| 368 | r_dcache_ll_data [num_cache] = new sc_signal<data_t> [m_nb_cpu]; |
| 369 | r_dcache_ll_addr [num_cache] = new sc_signal<addr_40> [m_nb_cpu]; |
| 370 | r_dcache_ll_valid [num_cache] = new sc_signal<bool> [m_nb_cpu]; |
| 371 | } |
| 372 | |
| 373 | r_tgt_icache_req = new sc_signal<bool> [m_nb_icache]; |
| 374 | r_tgt_icache_rsp = new sc_signal<bool> [m_nb_icache]; |
| 375 | r_tgt_dcache_req = new sc_signal<bool> [m_nb_dcache]; |
| 376 | r_tgt_dcache_rsp = new sc_signal<bool> [m_nb_dcache]; |
| 377 | |
| 378 | r_tgt_buf = new data_t [m_cache_words]; |
| 379 | r_tgt_be = new be_t [m_cache_words]; |
| 380 | |
| 381 | r_vci_rsp_ins_error = new sc_signal<bool> [m_nb_icache]; |
| 382 | r_vci_rsp_data_error = new sc_signal<bool> [m_nb_dcache]; |
| 383 | |
| 384 | ireq = new typename iss_t::InstructionRequest [m_nb_icache]; |
| 385 | irsp = new typename iss_t::InstructionResponse [m_nb_icache]; |
| 386 | ireq_cached = new bool [m_nb_icache]; |
| 387 | ireq_num_cpu = new uint32_t [m_nb_dcache]; |
| 388 | |
| 389 | dreq = new typename iss_t::DataRequest [m_nb_dcache]; |
| 390 | drsp = new typename iss_t::DataResponse [m_nb_dcache]; |
| 391 | dreq_cached = new bool [m_nb_dcache]; |
| 392 | dreq_num_cpu = new uint32_t [m_nb_dcache]; |
| 393 | |
| 394 | m_cpt_icache_access = new uint32_t [m_nb_icache]; |
| 395 | m_cpt_dcache_access = new uint32_t [m_nb_dcache]; |
| 396 | m_cpt_icache_miss_victim_wait = new uint32_t [m_nb_icache]; |
| 397 | m_cpt_dcache_miss_victim_wait = new uint32_t [m_nb_dcache]; |
| 398 | |
| 399 | m_cpt_dcache_store_after_store = new uint32_t [m_nb_dcache]; |
| 400 | m_cpt_dcache_hit_after_miss_read = new uint32_t [m_nb_dcache]; |
| 401 | m_cpt_dcache_hit_after_miss_write = new uint32_t [m_nb_dcache]; |
| 402 | |
| 403 | m_cpt_fsm_dcache = new uint32_t * [m_nb_dcache]; |
| 404 | m_cpt_fsm_icache = new uint32_t * [m_nb_icache]; |
| 405 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 406 | m_cpt_fsm_dcache[num_cache] = new uint32_t [soclib::common::size(dcache_fsm_state_str )]; |
| 407 | for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) |
| 408 | m_cpt_fsm_icache[num_cache] = new uint32_t [soclib::common::size(icache_fsm_state_str )]; |
| 409 | m_cpt_fsm_cmd = new uint32_t [soclib::common::size(cmd_fsm_state_str )]; |
| 410 | m_cpt_fsm_rsp = new uint32_t [soclib::common::size(rsp_fsm_state_str )]; |
| 411 | m_cpt_fsm_tgt = new uint32_t [soclib::common::size(tgt_fsm_state_str )]; |
| 412 | m_cpt_fsm_cleanup = new uint32_t [soclib::common::size(cleanup_fsm_state_str)]; |
| 413 | |
| 414 | m_cpt_frz_cycles = new uint32_t [m_nb_cpu]; |
| 415 | // r_icache_fsm("r_icache_fsm"), |
| 416 | // r_icache_fsm_save("r_icache_fsm_save"), |
| 417 | // r_icache_addr_save("r_icache_addr_save"), |
| 418 | // r_icache_miss_req("r_icache_miss_req"), |
| 419 | // r_icache_miss_way("r_icache_miss_way"), |
| 420 | // r_icache_miss_set("r_icache_miss_set"), |
| 421 | // r_icache_unc_req("r_icache_unc_req"), |
| 422 | // r_icache_cleanup_req("r_icache_cleanup_req"), |
| 423 | // r_icache_cleanup_line("r_icache_cleanup_line"), |
| 424 | // r_icache_inval_rsp("r_icache_inval_rsp"), |
| 425 | // r_icache_update_addr("r_icache_update_addr"), |
| 426 | // r_icache_buf_unc_valid("r_icache_buf_unc_valid"), |
| 427 | |
| 428 | // r_dcache_fsm("r_dcache_fsm"), |
| 429 | // r_dcache_fsm_save("r_dcache_fsm_save"), |
| 430 | // r_dcache_addr_save("r_dcache_addr_save"), |
| 431 | // r_dcache_wdata_save("r_dcache_wdata_save"), |
| 432 | // r_dcache_rdata_save("r_dcache_rdata_save"), |
| 433 | // r_dcache_type_save("r_dcache_type_save"), |
| 434 | // r_dcache_be_save("r_dcache_be_save"), |
| 435 | // r_dcache_cached_save("r_dcache_cached_save"), |
| 436 | // r_dcache_cleanup_req("r_dcache_cleanup_req"), |
| 437 | // r_dcache_cleanup_line("r_dcache_cleanup_line"), |
| 438 | // r_dcache_miss_req("r_dcache_miss_req"), |
| 439 | // r_dcache_miss_way("r_dcache_miss_way"), |
| 440 | // r_dcache_miss_set("r_dcache_miss_set"), |
| 441 | // r_dcache_unc_req("r_dcache_unc_req"), |
| 442 | // r_dcache_sc_req("r_dcache_sc_req"), |
| 443 | // r_dcache_inval_rsp("r_dcache_inval_rsp"), |
| 444 | // r_dcache_update_addr("r_dcache_update_addr"), |
| 445 | // r_dcache_ll_data("r_dcache_ll_data"), |
| 446 | // r_dcache_ll_addr("r_dcache_ll_addr"), |
| 447 | // r_dcache_ll_valid("r_dcache_ll_valid"), |
| 448 | // r_dcache_previous_unc("r_dcache_previous_unc"), |
| 449 | |
| 450 | // r_tgt_icache_req("r_tgt_icache_req"), |
| 451 | // r_tgt_icache_rsp("r_tgt_icache_rsp"), |
| 452 | |
| 453 | // r_tgt_dcache_req("r_tgt_dcache_req"), |
| 454 | // r_tgt_dcache_rsp("r_tgt_dcache_rsp"), |
| 455 | |
| 456 | // r_vci_rsp_ins_error("r_vci_rsp_ins_error"), |
| 457 | // r_vci_rsp_data_error("r_vci_rsp_data_error"), |
| 458 | |
| 459 | size_t _icache_ways = icache_ways /m_nb_icache; |
| 460 | size_t _icache_sets = icache_sets ; |
| 461 | size_t _dcache_ways = dcache_ways /m_nb_dcache; |
| 462 | size_t _dcache_sets = dcache_sets ; |
| 463 | size_t _icache_words = icache_words; |
| 464 | size_t _dcache_words = dcache_words; |
| 465 | |
| 466 | size_t _wbuf_nwords = wbuf_nwords ; |
| 467 | size_t _wbuf_nlines = wbuf_nlines /m_nb_dcache; |
| 468 | size_t _wbuf_timeout = wbuf_timeout; |
| 469 | |
| 470 | r_icache = new GenericCache<vci_addr_t> * [m_nb_icache]; |
| 471 | r_dcache = new GenericCache<vci_addr_t> * [m_nb_dcache]; |
| 472 | r_wbuf = new MultiWriteBuffer<addr_40> * [m_nb_dcache]; |
| 473 | |
| 474 | for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) |
| 475 | { |
| 476 | r_icache [num_cache] = new GenericCache<vci_addr_t> ("icache", _icache_ways, _icache_sets, _icache_words); |
| 477 | } |
| 478 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 479 | { |
| 480 | r_dcache [num_cache] = new GenericCache<vci_addr_t> ("dcache", _dcache_ways, _dcache_sets, _dcache_words); |
| 481 | r_wbuf [num_cache] = new MultiWriteBuffer<addr_40> ("r_wbuf", _wbuf_nwords, _wbuf_nlines, _wbuf_timeout, _dcache_words); |
| 482 | } |
| 483 | |
| 484 | m_num_cache_LSB_mask = 0; |
| 485 | for (uint32_t i=0; i<m_num_cache_LSB; ++i) |
| 486 | { |
| 487 | m_num_cache_LSB_mask <<= 1; |
| 488 | m_num_cache_LSB_mask |= 1; |
| 489 | } |
| 490 | m_num_cache_mask = 0; |
| 491 | for (uint32_t i=0; i<(m_num_cache_MSB-m_num_cache_LSB); ++i) |
| 492 | { |
| 493 | m_num_cache_mask <<= 1; |
| 494 | m_num_cache_mask |= 1; |
| 495 | } |
| 496 | |
| 497 | SC_METHOD(transition); |
| 498 | dont_initialize(); |
| 499 | sensitive << p_clk.pos(); |
| 500 | |
| 501 | SC_METHOD(genMoore); |
| 502 | dont_initialize(); |
| 503 | sensitive << p_clk.neg(); |
| 504 | |
| 505 | typename iss_t::CacheInfo cache_info; |
| 506 | cache_info.has_mmu = false; |
| 507 | cache_info.icache_line_size = icache_words*sizeof(data_t); |
| 508 | cache_info.icache_assoc = icache_ways; |
| 509 | cache_info.icache_n_lines = icache_sets; |
| 510 | cache_info.dcache_line_size = dcache_words*sizeof(data_t); |
| 511 | cache_info.dcache_assoc = dcache_ways; |
| 512 | cache_info.dcache_n_lines = dcache_sets; |
| 513 | |
| 514 | for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) |
| 515 | m_iss[num_cpu]->setCacheInfo(cache_info); |
| 516 | |
351 | | delete [] r_tgt_buf; |
352 | | delete [] r_tgt_be ; |
353 | | |
354 | | CACHE_MISS_BUF_DEALLOC; |
| 597 | #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION |
| 598 | for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) |
| 599 | { |
| 600 | log_transaction_file_dcache[num_cpu].close(); |
| 601 | log_transaction_file_icache[num_cpu].close(); |
| 602 | } |
| 603 | delete [] log_transaction_file_dcache; |
| 604 | delete [] log_transaction_file_icache; |
| 605 | |
| 606 | log_transaction_file_cmd .close(); |
| 607 | log_transaction_file_tgt .close(); |
| 608 | log_transaction_file_cleanup.close(); |
| 609 | #endif |
| 610 | |
| 611 | delete [] m_stop_simulation_nb_frz_cycles; |
| 612 | |
| 613 | |
| 614 | delete [] r_icache_lock ; |
| 615 | delete [] r_dcache_lock ; |
| 616 | delete [] r_dcache_sync ; |
| 617 | |
| 618 | delete [] r_icache_fsm ; |
| 619 | delete [] r_icache_fsm_save ; |
| 620 | delete [] r_icache_addr_save ; |
| 621 | delete [] r_icache_miss_req ; |
| 622 | delete [] r_icache_miss_way ; |
| 623 | delete [] r_icache_miss_set ; |
| 624 | delete [] r_icache_unc_req ; |
| 625 | delete [] r_icache_cleanup_req ; |
| 626 | delete [] r_icache_cleanup_line ; |
| 627 | delete [] r_icache_inval_rsp ; |
| 628 | delete [] r_icache_update_addr ; |
| 629 | delete [] r_icache_buf_unc_valid; |
| 630 | |
| 631 | delete [] r_dcache_fsm ; |
| 632 | delete [] r_dcache_fsm_save ; |
| 633 | delete [] r_dcache_addr_save ; |
| 634 | delete [] r_dcache_wdata_save ; |
| 635 | delete [] r_dcache_rdata_save ; |
| 636 | delete [] r_dcache_type_save ; |
| 637 | delete [] r_dcache_be_save ; |
| 638 | delete [] r_dcache_cached_save ; |
| 639 | delete [] r_dcache_cleanup_req ; |
| 640 | delete [] r_dcache_cleanup_line ; |
| 641 | delete [] r_dcache_miss_req ; |
| 642 | delete [] r_dcache_miss_way ; |
| 643 | delete [] r_dcache_miss_set ; |
| 644 | delete [] r_dcache_unc_req ; |
| 645 | delete [] r_dcache_sc_req ; |
| 646 | delete [] r_dcache_inval_rsp ; |
| 647 | delete [] r_dcache_update_addr ; |
| 648 | delete [] r_dcache_previous_unc ; |
| 649 | |
| 650 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 651 | { |
| 652 | delete [] r_dcache_ll_data [num_cache]; |
| 653 | delete [] r_dcache_ll_addr [num_cache]; |
| 654 | delete [] r_dcache_ll_valid [num_cache]; |
| 655 | } |
| 656 | delete [] r_dcache_num_cpu_save ; |
| 657 | delete [] r_dcache_ll_data ; |
| 658 | delete [] r_dcache_ll_addr ; |
| 659 | delete [] r_dcache_ll_valid ; |
| 660 | |
| 661 | delete [] r_tgt_icache_req ; |
| 662 | delete [] r_tgt_icache_rsp ; |
| 663 | delete [] r_tgt_dcache_req ; |
| 664 | delete [] r_tgt_dcache_rsp ; |
| 665 | |
| 666 | delete [] r_tgt_be ; |
| 667 | delete [] r_tgt_buf; |
| 668 | |
| 669 | delete [] r_vci_rsp_ins_error ; |
| 670 | delete [] r_vci_rsp_data_error ; |
| 671 | |
| 672 | delete [] ireq ; |
| 673 | delete [] irsp ; |
| 674 | delete [] ireq_cached ; |
| 675 | delete [] ireq_num_cpu ; |
| 676 | delete [] dreq ; |
| 677 | delete [] drsp ; |
| 678 | delete [] dreq_cached ; |
| 679 | delete [] dreq_num_cpu ; |
| 680 | |
| 681 | delete [] m_cpt_frz_cycles; |
| 682 | |
| 683 | delete [] m_cpt_icache_access ; |
| 684 | delete [] m_cpt_dcache_access ; |
| 685 | delete [] m_cpt_icache_miss_victim_wait; |
| 686 | delete [] m_cpt_dcache_miss_victim_wait; |
| 687 | delete [] m_cpt_dcache_store_after_store; |
| 688 | delete [] m_cpt_dcache_hit_after_miss_read; |
| 689 | delete [] m_cpt_dcache_hit_after_miss_write; |
| 690 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 691 | delete [] m_cpt_fsm_dcache [num_cache]; |
| 692 | for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) |
| 693 | delete [] m_cpt_fsm_icache [num_cache]; |
| 694 | |
| 695 | delete [] m_cpt_fsm_dcache ; |
| 696 | delete [] m_cpt_fsm_icache ; |
| 697 | delete [] m_cpt_fsm_cmd ; |
| 698 | delete [] m_cpt_fsm_rsp ; |
| 699 | delete [] m_cpt_fsm_tgt ; |
| 700 | delete [] m_cpt_fsm_cleanup; |
| 701 | |
| 702 | for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) |
| 703 | { |
| 704 | delete r_icache [num_cache]; |
| 705 | } |
| 706 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 707 | { |
| 708 | delete r_wbuf [num_cache]; |
| 709 | delete r_dcache [num_cache]; |
| 710 | } |
| 711 | delete [] r_wbuf; |
| 712 | delete [] r_icache; |
| 713 | delete [] r_dcache; |
| 714 | |
| 715 | for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) |
| 716 | { |
| 717 | delete m_iss [num_cpu]; |
| 718 | delete [] p_irq [num_cpu]; |
| 719 | } |
| 720 | delete [] m_iss; |
| 721 | delete [] p_irq; |
368 | | float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles); |
369 | | |
370 | | uint32_t m_cpt_data_read_cached = m_cpt_data_read-m_cpt_data_read_uncached; |
371 | | uint32_t m_cpt_data_write_cached = m_cpt_data_write-m_cpt_data_write_uncached; |
372 | | std::cout << "------------------------------------" << std:: dec << std::endl; |
373 | | std::cout << "CPU " << m_srcid_rw << " / Time = " << m_cpt_total_cycles << std::endl; |
374 | | std::cout << "- CPI : " << (float)m_cpt_total_cycles/run_cycles << std::endl ; |
375 | | std::cout << "- IPC : " << (float)run_cycles/m_cpt_total_cycles << std::endl ; |
376 | | std::cout << "- DATA READ * : " << m_cpt_data_read << std::endl ; |
377 | | std::cout << " + Uncached : " << m_cpt_data_read_uncached << " (" << (float)m_cpt_data_read_uncached*100.0/(float)m_cpt_data_read << "%)" << std::endl ; |
378 | | 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; |
379 | | std::cout << "- DATA WRITE * : " << m_cpt_data_write << std::endl ; |
380 | | std::cout << " + Uncached : " << m_cpt_data_write_uncached << " (" << (float)m_cpt_data_write_uncached*100.0/(float)m_cpt_data_write << "%)" << std::endl ; |
381 | | 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; |
382 | | // std::cout << "- WRITE RATE : " << (float)m_cpt_data_write/run_cycles << std::endl; |
383 | | // std::cout << "- UNCACHED READ RATE : " << (float)m_cpt_data_read_uncached/m_cpt_data_read << std::endl ; |
384 | | // std::cout << "- CACHED WRITE RATE : " << (float)m_cpt_data_write_cached/m_cpt_data_write << std::endl ; |
385 | | // std::cout << "- IMISS_RATE : " << (float)m_cpt_ins_miss/run_cycles << std::endl; |
386 | | // std::cout << "- DMISS RATE : " << (float)m_cpt_data_miss/(m_cpt_data_read-m_cpt_data_read_uncached) << std::endl ; |
387 | | // std::cout << "- INS MISS COST : " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl; |
388 | | // std::cout << "- IMISS TRANSACTION : " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl; |
389 | | // std::cout << "- DMISS COST : " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl; |
390 | | // std::cout << "- DMISS TRANSACTION : " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl; |
391 | | // std::cout << "- UNC COST : " << (float)m_cost_unc_read_frz/m_cpt_data_read_uncached << std::endl; |
392 | | // std::cout << "- UNC TRANSACTION : " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl; |
393 | | // std::cout << "- WRITE COST : " << (float)m_cost_write_frz/m_cpt_data_write << std::endl; |
394 | | // std::cout << "- WRITE TRANSACTION : " << (float)m_cost_write_transaction/m_cpt_data_write_transaction << std::endl; |
395 | | // std::cout << "- WRITE LENGTH : " << (float)m_length_write_transaction/m_cpt_data_write_transaction << std::endl; |
396 | | |
397 | | std::cout << "- CC_UPDATE_ICACHE : " << m_cpt_cc_update_icache << std::endl; |
398 | | 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; |
399 | | std::cout << "- CC_UPDATE_DCACHE : " << m_cpt_cc_update_dcache << std::endl; |
400 | | 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; |
401 | | uint32_t m_cpt_cc_inval = m_cpt_cc_inval_broadcast+m_cpt_cc_inval_icache+m_cpt_cc_inval_dcache; |
402 | | std::cout << "- CC_INVALID : " << m_cpt_cc_inval << std::endl; |
403 | | std::cout << " + ICACHE Only : " << (float)m_cpt_cc_inval_icache *100.0/(float)m_cpt_cc_inval << "%" << std::endl; |
404 | | std::cout << " + DCACHE Only : " << (float)m_cpt_cc_inval_dcache *100.0/(float)m_cpt_cc_inval << "%" << std::endl; |
405 | | std::cout << " + BROADCAST : " << (float)m_cpt_cc_inval_broadcast*100.0/(float)m_cpt_cc_inval << "%" << std::endl; |
406 | | std::cout << "* : accepted or not by the cache" << std::endl ; |
407 | | |
408 | | r_wbuf.printStatistics(); |
| 736 | uint32_t m_cpt_data_read_cached = m_cpt_data_read-m_cpt_data_read_uncached; |
| 737 | uint32_t m_cpt_data_write_cached = m_cpt_data_write-m_cpt_data_write_uncached; |
| 738 | std::cout << "------------------------------------" << std:: dec << std::endl; |
| 739 | std::cout << "CPU " << m_srcid_rw << " / Time = " << m_cpt_total_cycles << std::endl; |
| 740 | for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) |
| 741 | { |
| 742 | float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles[num_cpu]); |
| 743 | |
| 744 | std::cout << "- CPI : [" << num_cpu << "] "<< (float)m_cpt_total_cycles/run_cycles << std::endl ; |
| 745 | std::cout << "- IPC : [" << num_cpu << "] "<< (float)run_cycles/m_cpt_total_cycles << std::endl ; |
| 746 | } |
| 747 | std::cout << "- DATA READ * : " << m_cpt_data_read << std::endl ; |
| 748 | std::cout << " + Uncached : " << m_cpt_data_read_uncached << " (" << (float)m_cpt_data_read_uncached*100.0/(float)m_cpt_data_read << "%)" << std::endl ; |
| 749 | 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; |
| 750 | std::cout << "- DATA WRITE * : " << m_cpt_data_write << std::endl ; |
| 751 | std::cout << " + Uncached : " << m_cpt_data_write_uncached << " (" << (float)m_cpt_data_write_uncached*100.0/(float)m_cpt_data_write << "%)" << std::endl ; |
| 752 | 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; |
| 753 | // std::cout << "- WRITE RATE : " << (float)m_cpt_data_write/run_cycles << std::endl; |
| 754 | // std::cout << "- UNCACHED READ RATE : " << (float)m_cpt_data_read_uncached/m_cpt_data_read << std::endl ; |
| 755 | // std::cout << "- CACHED WRITE RATE : " << (float)m_cpt_data_write_cached/m_cpt_data_write << std::endl ; |
| 756 | // std::cout << "- IMISS_RATE : " << (float)m_cpt_ins_miss/run_cycles << std::endl; |
| 757 | // std::cout << "- DMISS RATE : " << (float)m_cpt_data_miss/(m_cpt_data_read-m_cpt_data_read_uncached) << std::endl ; |
| 758 | // std::cout << "- INS MISS COST : " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl; |
| 759 | // std::cout << "- IMISS TRANSACTION : " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl; |
| 760 | // std::cout << "- DMISS COST : " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl; |
| 761 | // std::cout << "- DMISS TRANSACTION : " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl; |
| 762 | // std::cout << "- UNC COST : " << (float)m_cost_unc_read_frz/m_cpt_data_read_uncached << std::endl; |
| 763 | // std::cout << "- UNC TRANSACTION : " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl; |
| 764 | // std::cout << "- WRITE COST : " << (float)m_cost_write_frz/m_cpt_data_write << std::endl; |
| 765 | // std::cout << "- WRITE TRANSACTION : " << (float)m_cost_write_transaction/m_cpt_data_write_transaction << std::endl; |
| 766 | // std::cout << "- WRITE LENGTH : " << (float)m_length_write_transaction/m_cpt_data_write_transaction << std::endl; |
| 767 | |
| 768 | std::cout << "- CC_UPDATE_ICACHE : " << m_cpt_cc_update_icache << std::endl; |
| 769 | 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; |
| 770 | std::cout << "- CC_UPDATE_DCACHE : " << m_cpt_cc_update_dcache << std::endl; |
| 771 | 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; |
| 772 | uint32_t m_cpt_cc_inval = m_cpt_cc_inval_broadcast+m_cpt_cc_inval_icache+m_cpt_cc_inval_dcache; |
| 773 | std::cout << "- CC_INVALID : " << m_cpt_cc_inval << std::endl; |
| 774 | std::cout << " + ICACHE Only : " << (float)m_cpt_cc_inval_icache *100.0/(float)m_cpt_cc_inval << "%" << std::endl; |
| 775 | std::cout << " + DCACHE Only : " << (float)m_cpt_cc_inval_dcache *100.0/(float)m_cpt_cc_inval << "%" << std::endl; |
| 776 | std::cout << " + BROADCAST : " << (float)m_cpt_cc_inval_broadcast*100.0/(float)m_cpt_cc_inval << "%" << std::endl; |
| 777 | |
| 778 | uint32_t m_cpt_icache_access_all = 0; |
| 779 | for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) |
| 780 | m_cpt_icache_access_all += m_cpt_icache_access [num_cache]; |
| 781 | |
| 782 | std::cout << "- ICACHE ACCESS : " << m_cpt_icache_access_all << std::endl; |
| 783 | for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) |
| 784 | 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; |
| 785 | |
| 786 | uint32_t m_cpt_dcache_access_all = 0; |
| 787 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 788 | m_cpt_dcache_access_all += m_cpt_dcache_access [num_cache]; |
| 789 | |
| 790 | std::cout << "- DCACHE ACCESS : " << m_cpt_dcache_access_all << std::endl; |
| 791 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 792 | { |
| 793 | 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 << "%)"; |
| 794 | |
| 795 | std::cout << " - store after store : " << m_cpt_dcache_store_after_store [num_cache]; |
| 796 | 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]; |
| 797 | std::cout << std::endl; |
| 798 | } |
| 799 | |
| 800 | uint32_t m_cpt_icache_miss_victim_wait_all = 0; |
| 801 | for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) |
| 802 | m_cpt_icache_miss_victim_wait_all += m_cpt_icache_miss_victim_wait [num_cache]; |
| 803 | std::cout << "- ICACHE MISS VICTIM WAIT : " << m_cpt_icache_miss_victim_wait_all << std::endl; |
| 804 | for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) |
| 805 | std::cout << " + [" << num_cache << "] : " << m_cpt_icache_miss_victim_wait [num_cache] << std::endl; |
| 806 | |
| 807 | uint32_t m_cpt_dcache_miss_victim_wait_all = 0; |
| 808 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 809 | m_cpt_dcache_miss_victim_wait_all += m_cpt_dcache_miss_victim_wait [num_cache]; |
| 810 | std::cout << "- DCACHE MISS VICTIM WAIT : " << m_cpt_dcache_miss_victim_wait_all << std::endl; |
| 811 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 812 | std::cout << " + [" << num_cache << "] : " << m_cpt_dcache_miss_victim_wait [num_cache] << std::endl; |
| 813 | |
| 814 | if (print_fsm) |
| 815 | { |
| 816 | std::cout << "- DCACHE FSM" << std::endl; |
| 817 | for (uint32_t i=0; i<soclib::common::size(dcache_fsm_state_str ); ++i) |
| 818 | { |
| 819 | std::cout << " + " << dcache_fsm_state_str[i] << " :\t "; |
| 820 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 821 | std::cout << m_cpt_fsm_dcache [num_cache][i] << ", "; |
| 822 | std::cout << std::endl; |
| 823 | } |
| 824 | std::cout << "- ICACHE FSM" << std::endl; |
| 825 | for (uint32_t i=0; i<soclib::common::size(icache_fsm_state_str ); ++i) |
| 826 | { |
| 827 | std::cout << " + " << icache_fsm_state_str[i] << " :\t "; |
| 828 | for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) |
| 829 | std::cout << m_cpt_fsm_icache [num_cache][i] << ", "; |
| 830 | std::cout << std::endl; |
| 831 | } |
| 832 | std::cout << "- CMD FSM" << std::endl; |
| 833 | for (uint32_t i=0; i<soclib::common::size(cmd_fsm_state_str ); ++i) |
| 834 | std::cout << " + " << cmd_fsm_state_str[i] << " :\t " << m_cpt_fsm_cmd [i] << std::endl; |
| 835 | std::cout << "- RSP FSM" << std::endl; |
| 836 | for (uint32_t i=0; i<soclib::common::size(rsp_fsm_state_str ); ++i) |
| 837 | std::cout << " + " << rsp_fsm_state_str[i] << " :\t " << m_cpt_fsm_rsp [i] << std::endl; |
| 838 | std::cout << "- TGT FSM" << std::endl; |
| 839 | for (uint32_t i=0; i<soclib::common::size(tgt_fsm_state_str ); ++i) |
| 840 | std::cout << " + " << tgt_fsm_state_str[i] << " :\t " << m_cpt_fsm_tgt [i] << std::endl; |
| 841 | std::cout << "- CLEANUP FSM" << std::endl; |
| 842 | for (uint32_t i=0; i<soclib::common::size(cleanup_fsm_state_str ); ++i) |
| 843 | std::cout << " + " << cleanup_fsm_state_str[i] << " :\t " << m_cpt_fsm_cleanup [i] << std::endl; |
| 844 | } |
| 845 | |
| 846 | std::cout << "* : accepted or not by the cache" << std::endl ; |
| 847 | |
| 848 | if (print_wbuf) |
| 849 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 850 | r_wbuf[num_cache]->printStatistics(); |
493 | | r_tgt_icache_req = false; |
494 | | r_tgt_dcache_req = false; |
495 | | r_tgt_icache_rsp = false; |
496 | | r_tgt_dcache_rsp = false; |
497 | | |
498 | | #if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE |
499 | | r_cache_word = 0; |
| 955 | r_tgt_icache_req [num_cache] = false; |
| 956 | r_tgt_icache_rsp [num_cache] = false; |
| 957 | |
| 958 | r_vci_rsp_ins_error [num_cache] = false; |
| 959 | }// end for num_cache |
| 960 | |
| 961 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 962 | { |
| 963 | // write buffer & caches |
| 964 | r_wbuf [num_cache]->reset(); |
| 965 | r_dcache[num_cache]->reset(); |
| 966 | |
| 967 | // synchronisation flip-flops from ICACHE & DCACHE FSMs to VCI FSMs |
| 968 | r_dcache_miss_req [num_cache] = false; |
| 969 | r_dcache_unc_req [num_cache] = false; |
| 970 | r_dcache_sc_req [num_cache] = false; |
| 971 | r_dcache_cleanup_req [num_cache] = false; |
| 972 | r_dcache_previous_unc[num_cache] = false; |
| 973 | |
| 974 | // internal messages in DCACHE et ICACHE FSMs |
| 975 | r_dcache_inval_rsp [num_cache] = false; |
| 976 | |
| 977 | // error signals from the VCI RSP FSM to the ICACHE or DCACHE FSMs |
| 978 | for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) |
| 979 | r_dcache_ll_valid [num_cache][num_cpu] = false; |
| 980 | |
| 981 | // synchronisation flip-flops from TGT FSM to ICACHE & DCACHE FSMs |
| 982 | r_tgt_dcache_req [num_cache] = false; |
| 983 | r_tgt_dcache_rsp [num_cache] = false; |
| 984 | |
| 985 | r_vci_rsp_data_error [num_cache] = false; |
| 986 | }// end for num_cache |
| 987 | |
| 988 | r_cache_word = 0; |
| 989 | |
| 990 | r_vci_cmd_dcache_prior = false; |
| 991 | r_vci_cmd_num_icache_prior = 0; |
| 992 | r_vci_cmd_num_dcache_prior = 0; |
| 993 | |
| 994 | r_vci_rsp_fifo_icache_data .init(); |
| 995 | r_vci_rsp_fifo_icache_num_cache .init(); |
| 996 | r_vci_rsp_fifo_dcache_data .init(); |
| 997 | r_vci_rsp_fifo_dcache_num_cache .init(); |
| 998 | |
| 999 | // activity counters |
| 1000 | m_cpt_dcache_data_read = 0; |
| 1001 | m_cpt_dcache_data_write = 0; |
| 1002 | m_cpt_dcache_dir_read = 0; |
| 1003 | m_cpt_dcache_dir_write = 0; |
| 1004 | m_cpt_icache_data_read = 0; |
| 1005 | m_cpt_icache_data_write = 0; |
| 1006 | m_cpt_icache_dir_read = 0; |
| 1007 | m_cpt_icache_dir_write = 0; |
| 1008 | |
| 1009 | m_cpt_cc_update_icache = 0; |
| 1010 | m_cpt_cc_update_dcache = 0; |
| 1011 | m_cpt_cc_inval_broadcast = 0; |
| 1012 | m_cpt_cc_inval_icache = 0; |
| 1013 | m_cpt_cc_inval_dcache = 0; |
| 1014 | m_cpt_cc_update_icache_word_useful = 0; |
| 1015 | m_cpt_cc_update_dcache_word_useful = 0; |
| 1016 | |
| 1017 | for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) |
| 1018 | m_cpt_frz_cycles [num_cpu] = 0; |
| 1019 | m_cpt_total_cycles = 0; |
| 1020 | |
| 1021 | m_cpt_data_read = 0; |
| 1022 | m_cpt_data_read_miss = 0; |
| 1023 | m_cpt_data_read_uncached = 0; |
| 1024 | m_cpt_data_write = 0; |
| 1025 | m_cpt_data_write_miss = 0; |
| 1026 | m_cpt_data_write_uncached = 0; |
| 1027 | |
| 1028 | m_cpt_ins_miss = 0; |
| 1029 | |
| 1030 | m_cost_write_frz = 0; |
| 1031 | m_cost_data_miss_frz = 0; |
| 1032 | m_cost_unc_read_frz = 0; |
| 1033 | m_cost_ins_miss_frz = 0; |
| 1034 | |
| 1035 | m_cpt_imiss_transaction = 0; |
| 1036 | m_cpt_dmiss_transaction = 0; |
| 1037 | m_cpt_unc_transaction = 0; |
| 1038 | m_cpt_data_write_transaction = 0; |
| 1039 | |
| 1040 | m_cost_imiss_transaction = 0; |
| 1041 | m_cost_dmiss_transaction = 0; |
| 1042 | m_cost_unc_transaction = 0; |
| 1043 | m_cost_write_transaction = 0; |
| 1044 | m_length_write_transaction = 0; |
| 1045 | |
| 1046 | for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) |
| 1047 | { |
| 1048 | m_cpt_icache_access [num_cache] = 0; |
| 1049 | m_cpt_icache_miss_victim_wait [num_cache] = 0; |
| 1050 | |
| 1051 | for (uint32_t i=0; i<soclib::common::size(icache_fsm_state_str ); ++i) |
| 1052 | m_cpt_fsm_icache [num_cache][i] = 0; |
| 1053 | } |
| 1054 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 1055 | { |
| 1056 | m_cpt_dcache_access [num_cache] = 0; |
| 1057 | m_cpt_dcache_miss_victim_wait [num_cache] = 0; |
| 1058 | m_cpt_dcache_store_after_store [num_cache] = 0; |
| 1059 | m_cpt_dcache_hit_after_miss_read [num_cache] = 0; |
| 1060 | m_cpt_dcache_hit_after_miss_write [num_cache] = 0; |
| 1061 | for (uint32_t i=0; i<soclib::common::size(dcache_fsm_state_str ); ++i) |
| 1062 | m_cpt_fsm_dcache [num_cache][i] = 0; |
| 1063 | } |
| 1064 | |
| 1065 | for (uint32_t i=0; i<soclib::common::size(cmd_fsm_state_str ); ++i) |
| 1066 | m_cpt_fsm_cmd [i] = 0; |
| 1067 | for (uint32_t i=0; i<soclib::common::size(rsp_fsm_state_str ); ++i) |
| 1068 | m_cpt_fsm_rsp [i] = 0; |
| 1069 | for (uint32_t i=0; i<soclib::common::size(tgt_fsm_state_str ); ++i) |
| 1070 | m_cpt_fsm_tgt [i] = 0; |
| 1071 | for (uint32_t i=0; i<soclib::common::size(cleanup_fsm_state_str); ++i) |
| 1072 | m_cpt_fsm_cleanup [i] = 0; |
| 1073 | |
| 1074 | return; // reset is finish, quit the transition fonction |
| 1075 | } |
| 1076 | |
| 1077 | bool vci_rsp_fifo_icache_get = false; |
| 1078 | bool vci_rsp_fifo_icache_put = false; |
| 1079 | data_t vci_rsp_fifo_icache_data = 0; |
| 1080 | uint32_t vci_rsp_fifo_icache_num_cache = 0; |
| 1081 | |
| 1082 | bool vci_rsp_fifo_dcache_get = false; |
| 1083 | bool vci_rsp_fifo_dcache_put = false; |
| 1084 | data_t vci_rsp_fifo_dcache_data = 0; |
| 1085 | uint32_t vci_rsp_fifo_dcache_num_cache = 0; |
| 1086 | |
| 1087 | ///////////////////////////////////////////////////////////////////// |
| 1088 | // VHDL TESTBENCH |
| 1089 | // Create and initialize variable |
| 1090 | ///////////////////////////////////////////////////////////////////// |
| 1091 | |
| 1092 | #if MWBUF_VHDL_TESTBENCH |
| 1093 | simulation_started = true; |
| 1094 | |
| 1095 | vhdl_tb_t vhdl_mwbuf_test_empty [m_nb_dcache]; |
| 1096 | vhdl_tb_t vhdl_mwbuf_port_empty [m_nb_dcache]; |
| 1097 | vhdl_tb_t vhdl_mwbuf_port_flush [m_nb_dcache]; |
| 1098 | vhdl_tb_t vhdl_mwbuf_port_write_val [m_nb_dcache]; |
| 1099 | vhdl_tb_t vhdl_mwbuf_test_write_ack [m_nb_dcache]; |
| 1100 | vhdl_tb_t vhdl_mwbuf_port_write_ack [m_nb_dcache]; |
| 1101 | vhdl_tb_t vhdl_mwbuf_port_write_addr [m_nb_dcache]; |
| 1102 | vhdl_tb_t vhdl_mwbuf_port_write_data [m_nb_dcache]; |
| 1103 | vhdl_tb_t vhdl_mwbuf_port_write_be [m_nb_dcache]; |
| 1104 | vhdl_tb_t vhdl_mwbuf_port_write_cached [m_nb_dcache]; |
| 1105 | vhdl_tb_t vhdl_mwbuf_port_write_cpu_id [m_nb_dcache]; |
| 1106 | vhdl_tb_t vhdl_mwbuf_test_sent_val [m_nb_dcache]; |
| 1107 | vhdl_tb_t vhdl_mwbuf_port_sent_val [m_nb_dcache]; |
| 1108 | vhdl_tb_t vhdl_mwbuf_port_sent_ack [m_nb_dcache]; |
| 1109 | vhdl_tb_t vhdl_mwbuf_test_sent_word_min [m_nb_dcache]; |
| 1110 | vhdl_tb_t vhdl_mwbuf_port_sent_word_min [m_nb_dcache]; |
| 1111 | vhdl_tb_t vhdl_mwbuf_test_sent_word_max [m_nb_dcache]; |
| 1112 | vhdl_tb_t vhdl_mwbuf_port_sent_word_max [m_nb_dcache]; |
| 1113 | vhdl_tb_t vhdl_mwbuf_port_sent_word [m_nb_dcache]; |
| 1114 | vhdl_tb_t vhdl_mwbuf_test_sent_addr [m_nb_dcache]; |
| 1115 | vhdl_tb_t vhdl_mwbuf_port_sent_addr [m_nb_dcache]; |
| 1116 | vhdl_tb_t vhdl_mwbuf_test_sent_data [m_nb_dcache]; |
| 1117 | vhdl_tb_t vhdl_mwbuf_port_sent_data [m_nb_dcache]; |
| 1118 | vhdl_tb_t vhdl_mwbuf_test_sent_be [m_nb_dcache]; |
| 1119 | vhdl_tb_t vhdl_mwbuf_port_sent_be [m_nb_dcache]; |
| 1120 | vhdl_tb_t vhdl_mwbuf_test_sent_index [m_nb_dcache]; |
| 1121 | vhdl_tb_t vhdl_mwbuf_port_sent_index [m_nb_dcache]; |
| 1122 | vhdl_tb_t vhdl_mwbuf_port_raw_test [m_nb_dcache]; |
| 1123 | vhdl_tb_t vhdl_mwbuf_port_raw_addr [m_nb_dcache]; |
| 1124 | vhdl_tb_t vhdl_mwbuf_test_raw_miss [m_nb_dcache]; |
| 1125 | vhdl_tb_t vhdl_mwbuf_port_raw_miss [m_nb_dcache]; |
| 1126 | vhdl_tb_t vhdl_mwbuf_port_completed_val [m_nb_dcache]; |
| 1127 | vhdl_tb_t vhdl_mwbuf_port_completed_index [m_nb_dcache]; |
| 1128 | vhdl_tb_t vhdl_mwbuf_test_completed_cached [m_nb_dcache]; |
| 1129 | vhdl_tb_t vhdl_mwbuf_port_completed_cached [m_nb_dcache]; |
| 1130 | vhdl_tb_t vhdl_mwbuf_test_completed_cpu_id [m_nb_dcache]; |
| 1131 | vhdl_tb_t vhdl_mwbuf_port_completed_cpu_id [m_nb_dcache]; |
| 1132 | |
| 1133 | for (uint32_t num_dcache=0; num_dcache<m_nb_dcache; ++num_dcache) |
| 1134 | { |
| 1135 | vhdl_mwbuf_test_empty [num_dcache] = 0; |
| 1136 | vhdl_mwbuf_port_empty [num_dcache] = 0; |
| 1137 | vhdl_mwbuf_port_flush [num_dcache] = 0; |
| 1138 | vhdl_mwbuf_port_write_val [num_dcache] = 0; |
| 1139 | vhdl_mwbuf_test_write_ack [num_dcache] = 0; |
| 1140 | vhdl_mwbuf_port_write_ack [num_dcache] = 0; |
| 1141 | vhdl_mwbuf_port_write_addr [num_dcache] = 0; |
| 1142 | vhdl_mwbuf_port_write_data [num_dcache] = 0; |
| 1143 | vhdl_mwbuf_port_write_be [num_dcache] = 0; |
| 1144 | vhdl_mwbuf_port_write_cached [num_dcache] = 0; |
| 1145 | vhdl_mwbuf_port_write_cpu_id [num_dcache] = 0; |
| 1146 | vhdl_mwbuf_test_sent_val [num_dcache] = 0; |
| 1147 | vhdl_mwbuf_port_sent_val [num_dcache] = 0; |
| 1148 | vhdl_mwbuf_port_sent_ack [num_dcache] = 0; |
| 1149 | vhdl_mwbuf_test_sent_word_min [num_dcache] = 0; |
| 1150 | vhdl_mwbuf_port_sent_word_min [num_dcache] = 0; |
| 1151 | vhdl_mwbuf_test_sent_word_max [num_dcache] = 0; |
| 1152 | vhdl_mwbuf_port_sent_word_max [num_dcache] = 0; |
| 1153 | vhdl_mwbuf_port_sent_word [num_dcache] = 0; |
| 1154 | vhdl_mwbuf_test_sent_addr [num_dcache] = 0; |
| 1155 | vhdl_mwbuf_port_sent_addr [num_dcache] = 0; |
| 1156 | vhdl_mwbuf_test_sent_data [num_dcache] = 0; |
| 1157 | vhdl_mwbuf_port_sent_data [num_dcache] = 0; |
| 1158 | vhdl_mwbuf_test_sent_be [num_dcache] = 0; |
| 1159 | vhdl_mwbuf_port_sent_be [num_dcache] = 0; |
| 1160 | vhdl_mwbuf_test_sent_index [num_dcache] = 0; |
| 1161 | vhdl_mwbuf_port_sent_index [num_dcache] = 0; |
| 1162 | vhdl_mwbuf_port_raw_test [num_dcache] = 0; |
| 1163 | vhdl_mwbuf_port_raw_addr [num_dcache] = 0; |
| 1164 | vhdl_mwbuf_test_raw_miss [num_dcache] = 0; |
| 1165 | vhdl_mwbuf_port_raw_miss [num_dcache] = 0; |
| 1166 | vhdl_mwbuf_port_completed_val [num_dcache] = 0; |
| 1167 | vhdl_mwbuf_port_completed_index [num_dcache] = 0; |
| 1168 | vhdl_mwbuf_test_completed_cached [num_dcache] = 0; |
| 1169 | vhdl_mwbuf_port_completed_cached [num_dcache] = 0; |
| 1170 | vhdl_mwbuf_test_completed_cpu_id [num_dcache] = 0; |
| 1171 | vhdl_mwbuf_port_completed_cpu_id [num_dcache] = 0; |
| 1172 | } |
502 | | |
503 | | // internal messages in DCACHE et ICACHE FSMs |
504 | | r_icache_inval_rsp = false; |
505 | | r_dcache_inval_rsp = false; |
506 | | |
507 | | // error signals from the VCI RSP FSM to the ICACHE or DCACHE FSMs |
508 | | r_dcache_ll_valid = false; |
509 | | r_icache_buf_unc_valid = false; |
510 | | |
511 | | r_vci_cmd_dcache_prior = false; |
512 | | |
513 | | r_vci_rsp_data_error = false; |
514 | | r_vci_rsp_ins_error = false; |
515 | | |
516 | | CACHE_MISS_BUF_RESET(i); |
517 | | CACHE_MISS_BUF_RESET(d); |
518 | | |
519 | | // activity counters |
520 | | m_cpt_dcache_data_read = 0; |
521 | | m_cpt_dcache_data_write = 0; |
522 | | m_cpt_dcache_dir_read = 0; |
523 | | m_cpt_dcache_dir_write = 0; |
524 | | m_cpt_icache_data_read = 0; |
525 | | m_cpt_icache_data_write = 0; |
526 | | m_cpt_icache_dir_read = 0; |
527 | | m_cpt_icache_dir_write = 0; |
528 | | |
529 | | m_cpt_cc_update_icache = 0; |
530 | | m_cpt_cc_update_dcache = 0; |
531 | | m_cpt_cc_inval_broadcast = 0; |
532 | | m_cpt_cc_inval_icache = 0; |
533 | | m_cpt_cc_inval_dcache = 0; |
534 | | m_cpt_cc_update_icache_word_useful = 0; |
535 | | m_cpt_cc_update_dcache_word_useful = 0; |
536 | | |
537 | | m_cpt_frz_cycles = 0; |
538 | | m_cpt_total_cycles = 0; |
539 | | |
540 | | m_cpt_data_read = 0; |
541 | | m_cpt_data_read_miss = 0; |
542 | | m_cpt_data_read_uncached = 0; |
543 | | m_cpt_data_write = 0; |
544 | | m_cpt_data_write_miss = 0; |
545 | | m_cpt_data_write_uncached = 0; |
546 | | |
547 | | m_cpt_ins_miss = 0; |
548 | | |
549 | | m_cost_write_frz = 0; |
550 | | m_cost_data_miss_frz = 0; |
551 | | m_cost_unc_read_frz = 0; |
552 | | m_cost_ins_miss_frz = 0; |
553 | | |
554 | | m_cpt_imiss_transaction = 0; |
555 | | m_cpt_dmiss_transaction = 0; |
556 | | m_cpt_unc_transaction = 0; |
557 | | m_cpt_data_write_transaction = 0; |
558 | | |
559 | | m_cost_imiss_transaction = 0; |
560 | | m_cost_dmiss_transaction = 0; |
561 | | m_cost_unc_transaction = 0; |
562 | | m_cost_write_transaction = 0; |
563 | | m_length_write_transaction = 0; |
564 | | |
565 | | return; |
566 | | } |
567 | | |
568 | | // printf("%d\n",(uint32_t)m_cpt_total_cycles); |
569 | | |
570 | | PRINTF("--------------------------------------------\n"); |
571 | | PRINTF(" * CC_XCACHE_WRAPPER \"%s\" - Time = %d\n",name().c_str(),(uint32_t)m_cpt_total_cycles); |
572 | | PRINTF(" * fsm dcache = %s\n",dcache_fsm_state_str[r_dcache_fsm]); |
573 | | PRINTF(" * fsm icache = %s\n",icache_fsm_state_str[r_icache_fsm]); |
574 | | PRINTF(" * fsm cmd = %s\n",cmd_fsm_state_str[r_vci_cmd_fsm]); |
575 | | PRINTF(" * fsm rsp = %s\n",rsp_fsm_state_str[r_vci_rsp_fsm]); |
576 | | PRINTF(" * fsm tgt = %s\n",tgt_fsm_state_str[r_vci_tgt_fsm]); |
577 | | PRINTF(" * fsm cleanup = %s\n",cleanup_fsm_state_str[r_cleanup_fsm]); |
578 | | PRINTF(" * ll info : %d %llx %llx\n",r_dcache_ll_valid.read(), (uint64_t)r_dcache_ll_addr.read(), (uint64_t)r_dcache_ll_data.read()); |
579 | | PRINTF(" * dcache_previous_unc : %d\n",r_dcache_previous_unc.read()); |
580 | | // CACHE_MISS_BUF_RSP_PRINT(i); |
581 | | // CACHE_MISS_BUF_RSP_PRINT(d); |
| 1175 | ///////////////////////////////////////////////////////////////////// |
| 1176 | // DEBUG : |
| 1177 | // print state of all fsm and main register |
| 1178 | ///////////////////////////////////////////////////////////////////// |
| 1179 | |
| 1180 | // printf("%d\n",(uint32_t)m_cpt_total_cycles); |
| 1181 | |
| 1182 | PRINTF("--------------------------------------------\n"); |
| 1183 | PRINTF(" * CC_XCACHE_WRAPPER \"%s\" Transition - Time = %d\n",name().c_str(),(uint32_t)m_cpt_total_cycles); |
| 1184 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 1185 | 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)); |
| 1186 | for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) |
| 1187 | 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)); |
| 1188 | PRINTF(" * fsm cmd = (%.2d) %s\n",r_vci_cmd_num_cache.read(), cmd_fsm_state_str[r_vci_cmd_fsm]); |
| 1189 | PRINTF(" * fsm rsp = (%.2d) %s\n",r_vci_rsp_num_cache.read(), rsp_fsm_state_str[r_vci_rsp_fsm]); |
| 1190 | 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()); |
| 1191 | //PRINTF(" * fsm tgt = %s - %llx\n",tgt_fsm_state_str[r_vci_tgt_fsm],(blob_t)r_tgt_addr.read()); |
| 1192 | PRINTF(" * fsm cleanup = (%.2d) %s\n",r_cleanup_num_cache.read(), cleanup_fsm_state_str[r_cleanup_fsm]); |
| 1193 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 1194 | { |
| 1195 | for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) |
| 1196 | PRINTF(" * ll info : [%.2d][%.2d] %d %llx (%llx) %llx\n" |
| 1197 | ,num_cache |
| 1198 | ,num_cpu |
| 1199 | , r_dcache_ll_valid [num_cache][num_cpu].read() |
| 1200 | ,(blob_t)r_dcache_ll_addr [num_cache][num_cpu].read() |
| 1201 | ,(blob_t)set_num_dcache_only(r_dcache_ll_addr [num_cache][num_cpu].read(),num_cache) |
| 1202 | ,(blob_t)r_dcache_ll_data [num_cache][num_cpu].read()); |
| 1203 | |
| 1204 | PRINTF(" * dcache_previous_unc : [%.2d] %d\n",num_cache,r_dcache_previous_unc[num_cache].read()); |
590 | | m_cpt_total_cycles++; |
591 | | |
592 | | ///////////////////////////////////////////////////////////////////// |
593 | | // The TGT_FSM controls the following ressources: |
594 | | // - r_vci_tgt_fsm |
595 | | // - r_tgt_buf[nwords] |
596 | | // - r_tgt_be[nwords] |
597 | | // - r_tgt_update |
598 | | // - r_tgt_word |
599 | | // - r_tgt_addr |
600 | | // - r_tgt_srcid |
601 | | // - r_tgt_trdid |
602 | | // - r_tgt_pktid |
603 | | // All VCI commands must be CMD_WRITE. |
604 | | // If the VCI address offset is null, the command is an invalidate |
605 | | // request. It is an update request otherwise. |
606 | | // The VCI_TGT FSM stores the external request arguments in the |
607 | | // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req |
608 | | // & r_tgt_dcache_req flip-flops to signal the external request to |
609 | | // the ICACHE & DCACHE FSMs in the REQ state. It waits the completion |
610 | | // of the update or invalidate request in the RSP state. |
611 | | // - for an invalidate request the VCI packet length is 1 word. |
612 | | // The WDATA field contains the line index (i.e. the Z & Y fields). |
613 | | // - for an update request the VCI packet length is (n+2) words. |
614 | | // The WDATA field of the first VCI word contains the line number. |
615 | | // The WDATA field of the second VCI word contains the word index. |
616 | | // The WDATA field of the n following words contains the values. |
617 | | // - for both invalidate & update requests, the VCI response |
618 | | // is one single word. |
619 | | // In case of errors in the VCI command packet, the simulation |
620 | | // is stopped with an error message. |
621 | | ///////////////////////////////////////////////////////////////////// |
622 | | |
623 | | switch(r_vci_tgt_fsm) { |
624 | | |
625 | | case TGT_IDLE: |
626 | | if ( p_vci_tgt.cmdval.read() ) |
627 | | { |
628 | | PRINTF(" * <TGT> request\n"); |
629 | | |
630 | | addr_40 address = p_vci_tgt.address.read(); |
631 | | |
632 | | if ( p_vci_tgt.cmd.read() != vci_param::CMD_WRITE) |
633 | | { |
| 1211 | // VHDL debug |
| 1212 | // #if MWBUF_VHDL_TESTBENCH |
| 1213 | // printf("\nMWBUF[%d] - Time = %d\n\n",num_cache,(uint32_t)m_cpt_total_cycles); |
| 1214 | // r_wbuf[num_cache]->printTrace(1); |
| 1215 | // #endif |
| 1216 | |
| 1217 | } |
| 1218 | |
| 1219 | ///////////////////////////////////////////////////////////////////// |
| 1220 | // Statistics |
| 1221 | // Count state fsm activity |
| 1222 | ///////////////////////////////////////////////////////////////////// |
| 1223 | |
| 1224 | |
| 1225 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 1226 | m_cpt_fsm_dcache [num_cache][r_dcache_fsm[num_cache]] ++; |
| 1227 | for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) |
| 1228 | m_cpt_fsm_icache [num_cache][r_icache_fsm[num_cache]] ++; |
| 1229 | m_cpt_fsm_cmd [r_vci_cmd_fsm] ++; |
| 1230 | m_cpt_fsm_rsp [r_vci_rsp_fsm] ++; |
| 1231 | m_cpt_fsm_tgt [r_vci_tgt_fsm] ++; |
| 1232 | m_cpt_fsm_cleanup [r_cleanup_fsm] ++; |
| 1233 | |
| 1234 | m_cpt_total_cycles++; |
| 1235 | |
| 1236 | ///////////////////////////////////////////////////////////////////// |
| 1237 | // The TGT_FSM controls the following ressources: |
| 1238 | // - r_vci_tgt_fsm |
| 1239 | // - r_tgt_buf[nwords] |
| 1240 | // - r_tgt_be[nwords] |
| 1241 | // - r_tgt_update |
| 1242 | // - r_tgt_word |
| 1243 | // - r_tgt_addr |
| 1244 | // - r_tgt_srcid |
| 1245 | // - r_tgt_trdid |
| 1246 | // - r_tgt_pktid |
| 1247 | // All VCI commands must be CMD_WRITE. |
| 1248 | // If the VCI address offset is null, the command is an invalidate |
| 1249 | // request. It is an update request otherwise. |
| 1250 | // The VCI_TGT FSM stores the external request arguments in the |
| 1251 | // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req |
| 1252 | // & r_tgt_dcache_req flip-flops to signal the external request to |
| 1253 | // the ICACHE & DCACHE FSMs in the REQ state. It waits the completion |
| 1254 | // of the update or invalidate request in the RSP state. |
| 1255 | // - for an invalidate request the VCI packet length is 1 word. |
| 1256 | // The WDATA field contains the line index (i.e. the Z & Y fields). |
| 1257 | // - for an update request the VCI packet length is (n+2) words. |
| 1258 | // The WDATA field of the first VCI word contains the line number. |
| 1259 | // The WDATA field of the second VCI word contains the word index. |
| 1260 | // The WDATA field of the n following words contains the values. |
| 1261 | // - for both invalidate & update requests, the VCI response |
| 1262 | // is one single word. |
| 1263 | // In case of errors in the VCI command packet, the simulation |
| 1264 | // is stopped with an error message. |
| 1265 | ///////////////////////////////////////////////////////////////////// |
| 1266 | |
| 1267 | switch(r_vci_tgt_fsm) { |
| 1268 | |
| 1269 | case TGT_IDLE: |
| 1270 | if ( p_vci_tgt.cmdval.read() ) |
| 1271 | { |
| 1272 | PRINTF(" * <TGT> Request\n"); |
| 1273 | |
| 1274 | addr_40 address = p_vci_tgt.address.read(); |
| 1275 | |
| 1276 | if ( p_vci_tgt.cmd.read() != vci_param::CMD_WRITE) |
| 1277 | { |
| 1278 | std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl; |
| 1279 | std::cout << "coherence request is not a write" << std::endl; |
| 1280 | std::cout << "address = " << std::hex << address << std::dec << std::endl; |
| 1281 | std::cout << "srcid = " << p_vci_tgt.srcid.read() << std::endl; |
| 1282 | exit(0); |
| 1283 | } |
| 1284 | |
| 1285 | // multi-update or multi-invalidate for data type |
| 1286 | if ( ((address&0x3) != 0x3) and (not m_segment.contains(address)) ) |
| 1287 | { |
| 1288 | std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl; |
| 1289 | std::cout << "out of segment coherence request" << std::endl; |
| 1290 | std::cout << "address = " << std::hex << address << std::dec << std::endl; |
| 1291 | std::cout << "srcid = " << p_vci_tgt.srcid.read() << std::endl; |
| 1292 | exit(0); |
| 1293 | } |
| 1294 | |
| 1295 | 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; |
| 1296 | // * m_dcache_words * 4; |
| 1297 | |
| 1298 | addr_40 tgt_iaddr = tgt_addr; |
| 1299 | addr_40 tgt_daddr = tgt_addr; |
| 1300 | |
| 1301 | PRINTF(" * <TGT> srcid : %d\n",(uint32_t)p_vci_tgt.srcid.read()); |
| 1302 | PRINTF(" * <TGT> trdid : %d\n",(uint32_t)p_vci_tgt.trdid.read()); |
| 1303 | PRINTF(" * <TGT> pktid : %d\n",(uint32_t)p_vci_tgt.pktid.read()); |
| 1304 | PRINTF(" * <TGT> address (before) : %llx\n",(blob_t)tgt_iaddr); |
| 1305 | |
| 1306 | r_tgt_srcid = p_vci_tgt.srcid.read(); |
| 1307 | r_tgt_trdid = p_vci_tgt.trdid.read(); |
| 1308 | r_tgt_pktid = p_vci_tgt.pktid.read(); |
| 1309 | // r_tgt_plen = p_vci_tgt.plen.read(); |
| 1310 | |
| 1311 | // BROADCAST |
| 1312 | if ( (address&0x3) == 0x3 ) // broadcast invalidate for data or instruction type |
| 1313 | { |
| 1314 | if ( not p_vci_tgt.eop.read() ) |
| 1315 | { |
| 1316 | std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl; |
| 1317 | std::cout << "the BROADCAST INVALIDATE command length must be one word" << std::endl; |
| 1318 | exit(0); |
| 1319 | } |
| 1320 | r_tgt_update = false; |
| 1321 | // r_tgt_brdcast= true; |
| 1322 | r_vci_tgt_fsm = TGT_REQ_BROADCAST; |
| 1323 | uint32_t tgt_num_cache; |
| 1324 | tgt_num_cache = get_num_icache(tgt_iaddr,0); // none effect (else CC_XCACHE_WRAPPER_MULTI_CACHE==1) |
| 1325 | tgt_num_cache = get_num_dcache(tgt_daddr); |
| 1326 | r_tgt_num_cache = tgt_num_cache; |
| 1327 | |
| 1328 | PRINTF(" * <TGT> REQ_BROADCAST\n"); |
| 1329 | PRINTF(" * <TGT> num_cache (data) : %d\n",tgt_num_cache); |
| 1330 | |
| 1331 | m_cpt_cc_inval_broadcast++ ; |
| 1332 | |
| 1333 | #if CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION |
| 1334 | if (generate_log_transaction_file_tgt) |
| 1335 | { |
| 1336 | log_transaction_file_tgt |
| 1337 | << "[" << m_cpt_total_cycles << "] " |
| 1338 | << "BROADCAST " |
| 1339 | << std::hex |
| 1340 | << " L " << std::setw(10) << (blob_t)tgt_addr |
| 1341 | << std::dec |
| 1342 | << " - " << tgt_num_cache |
| 1343 | << std::endl; |
| 1344 | } |
| 1345 | #endif //CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION |
| 1346 | |
| 1347 | } |
| 1348 | else // multi-update or multi-invalidate for data type |
| 1349 | { |
| 1350 | uint32_t cell = address - m_segment.baseAddress(); // addr_40 |
| 1351 | // r_tgt_brdcast = false; |
| 1352 | |
| 1353 | if (cell == 0) |
| 1354 | { // invalidate data |
| 1355 | if ( not p_vci_tgt.eop.read() ) |
| 1356 | { |
| 1648 | |
| 1649 | // // one response |
| 1650 | // if ( not r_tgt_icache_rsp[r_tgt_num_cache] or not r_tgt_dcache_rsp[r_tgt_num_cache] ) |
| 1651 | // { |
| 1652 | // if ( p_vci_tgt.rspack.read() ) |
| 1653 | // { |
| 1654 | // r_vci_tgt_fsm = TGT_IDLE; |
| 1655 | // r_tgt_icache_rsp[r_tgt_num_cache] = false; |
| 1656 | // r_tgt_dcache_rsp[r_tgt_num_cache] = false; |
| 1657 | // } |
| 1658 | // } |
| 1659 | |
| 1660 | // // if data and instruction have the inval line, need two responses |
| 1661 | // if ( r_tgt_icache_rsp[r_tgt_num_cache] and r_tgt_dcache_rsp[r_tgt_num_cache] ) |
| 1662 | // { |
| 1663 | // if ( p_vci_tgt.rspack.read() ) |
| 1664 | // { |
| 1665 | // r_tgt_icache_rsp[r_tgt_num_cache] = false; // only reset one for respond the second time |
| 1666 | // } |
| 1667 | // } |
| 1668 | |
| 1669 | PRINTF(" * <TGT> icache_rsp : %d\n",(uint32_t) r_tgt_icache_rsp[r_tgt_num_cache]); |
| 1670 | PRINTF(" * <TGT> dcache_rsp[%d] : %d\n",(uint32_t)r_tgt_num_cache,(uint32_t)r_tgt_dcache_rsp[r_tgt_num_cache].read()); |
| 1671 | // if there is no need for a response |
| 1672 | if (not tgt_icache_rsp and not r_tgt_dcache_rsp[r_tgt_num_cache] ) |
| 1673 | { |
| 1674 | r_vci_tgt_fsm = TGT_IDLE; |
| 1675 | } |
| 1676 | |
| 1677 | } |
| 1678 | break; |
| 1679 | } |
| 1680 | //////////////////// |
| 1681 | case TGT_RSP_ICACHE: |
| 1682 | { |
| 1683 | 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(); |
| 1684 | |
| 1685 | PRINTF(" * <TGT> RSP_ICACHE : transaction : %d ((%d or not %d) and not %d)\n",transaction_rsp |
| 1686 | ,(int)p_vci_tgt.rspack.read() |
| 1687 | ,(int)r_tgt_icache_rsp[r_tgt_num_cache].read() |
| 1688 | ,(int)r_tgt_icache_req[r_tgt_num_cache].read() |
| 1689 | ); |
| 1690 | |
| 1691 | if (transaction_rsp) |
| 1692 | { |
| 1693 | r_vci_tgt_fsm = TGT_IDLE; |
| 1694 | r_tgt_icache_rsp[r_tgt_num_cache] = false; |
| 1695 | } |
| 1696 | break; |
| 1697 | } |
| 1698 | |
| 1699 | case TGT_RSP_DCACHE: |
| 1700 | { |
| 1701 | 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(); |
| 1702 | |
| 1703 | PRINTF(" * <TGT> RSP_DCACHE : transaction : %d\n",transaction_rsp); |
| 1704 | |
| 1705 | if (transaction_rsp) |
| 1706 | { |
| 1707 | r_vci_tgt_fsm = TGT_IDLE; |
| 1708 | r_tgt_dcache_rsp[r_tgt_num_cache] = false; |
| 1709 | } |
| 1710 | break; |
| 1711 | } |
| 1712 | } // end switch TGT_FSM |
| 1713 | |
| 1714 | ///////////////////////////////////////////////////////////////////// |
| 1715 | // Interface between CPU and CACHE FSM |
| 1716 | /////////////////////////////////////////////////////////////////////// |
| 1717 | |
| 1718 | uint32_t ireq_num_cache [m_nb_cpu]; |
| 1719 | uint32_t dreq_num_cache [m_nb_cpu]; |
| 1720 | bool have_sync = false; |
| 1721 | |
| 1722 | { |
| 1723 | typename iss_t::InstructionRequest _ireq = ISS_IREQ_INITIALIZER; |
| 1724 | typename iss_t::DataRequest _dreq = ISS_DREQ_INITIALIZER; |
| 1725 | |
| 1726 | for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) |
| 1727 | { |
| 1728 | ireq [num_cache] = _ireq; |
| 1729 | //irsp [num_cache] = _irsp; |
| 1730 | } |
| 1731 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 1732 | { |
| 1733 | dreq [num_cache] = _dreq; |
| 1734 | //drsp [num_cache] = _drsp; |
| 1735 | |
| 1736 | have_sync |= r_dcache_sync [num_cache]; |
| 1737 | } |
| 1738 | } |
| 1739 | |
| 1740 | for (uint32_t _num_cpu=0; _num_cpu<m_nb_cpu; ++_num_cpu) |
| 1741 | { |
| 1742 | // round robin priority |
| 1743 | uint32_t num_cpu = (r_cpu_prior+_num_cpu)%m_nb_cpu; |
| 1744 | |
| 1745 | typename iss_t::InstructionRequest _ireq = ISS_IREQ_INITIALIZER; |
| 1746 | typename iss_t::DataRequest _dreq = ISS_DREQ_INITIALIZER; |
| 1747 | |
| 1748 | m_iss[num_cpu]->getRequests(_ireq, _dreq); |
| 1749 | |
| 1750 | addr_40 addr; |
| 1751 | uint32_t num_cache; |
| 1752 | |
| 1753 | addr = (addr_40)_ireq.addr; |
| 1754 | num_cache = get_num_icache(addr,num_cpu); |
| 1755 | |
| 1756 | bool icache_req_valid = ((not ireq[num_cache].valid and // no previous request in this cycle |
| 1757 | (r_icache_lock [num_cache] == m_nb_cpu)) or // no previous request in previous cycle |
| 1758 | (r_icache_lock [num_cache] == num_cpu)); // previous request in previous cycle by this cpu |
| 1759 | |
| 1760 | if (icache_req_valid) |
| 1761 | { |
| 1762 | bool valid = _ireq.valid; |
| 1763 | |
| 1764 | if (valid) |
| 1765 | { |
| 1766 | PRINTF(" * <CPU2CACHE> ICACHE : Transaction between cpu %d and cache %d (lock)\n",num_cpu,num_cache); |
| 1767 | ireq_num_cache [num_cpu ] = num_cache; |
| 1768 | r_icache_lock [num_cache] = num_cpu; |
| 1769 | } |
| 1770 | else |
| 1771 | { |
| 1772 | PRINTF(" * <CPU2CACHE> ICACHE : No Transaction between cpu %d and cache %d : invalid\n",num_cpu,num_cache); |
| 1773 | ireq_num_cache [num_cpu] = m_nb_icache; |
| 1774 | } |
| 1775 | |
| 1776 | ireq_cached [num_cache] = m_cacheability_table[(vci_addr_t)_ireq.addr]; |
| 1777 | ireq_num_cpu [num_cache] = num_cpu; |
| 1778 | ireq [num_cache] = _ireq; |
| 1779 | ireq [num_cache].addr = addr; |
| 1780 | } |
| 1781 | else |
| 1782 | { |
| 1783 | PRINTF(" * <CPU2CACHE> ICACHE : No transaction (cpu %d)\n",num_cpu); |
| 1784 | |
| 1785 | ireq_num_cache [num_cpu] = m_nb_icache; |
| 1786 | } |
| 1787 | |
| 1788 | addr = (addr_40)_dreq.addr; |
| 1789 | num_cache = get_num_dcache(addr); |
| 1790 | |
| 1791 | |
| 1792 | bool dcache_no_lock = (r_dcache_lock [num_cache] == m_nb_cpu); |
| 1793 | bool dcache_lock_owner = (r_dcache_lock [num_cache] == num_cpu); |
| 1794 | bool dcache_lock_no_owner= not dcache_no_lock and not dcache_lock_owner; |
| 1795 | bool dcache_req_valid; |
| 1796 | |
| 1797 | // multi cache : hit after miss) |
| 1798 | if (m_nb_dcache > 0) |
| 1799 | { |
| 1800 | bool dcache_wait = ((r_dcache_fsm[num_cache] == DCACHE_MISS_WAIT)// or |
| 1801 | // (r_dcache_fsm[num_cache] == DCACHE_UNC_WAIT) or |
| 1802 | // (r_dcache_fsm[num_cache] == DCACHE_SC_WAIT) |
| 1803 | ); |
| 1804 | |
| 1805 | dcache_req_valid = ((not dreq[num_cache].valid and // no previous request in this cycle |
| 1806 | not have_sync and // no sync instruction |
| 1807 | (dcache_no_lock or |
| 1808 | (dcache_lock_no_owner and dcache_wait))) or // no previous request in previous cycle |
| 1809 | (dcache_lock_owner and not dcache_wait)); // previous request in previous cycle by this cpu |
| 1810 | } |
| 1811 | else |
| 1812 | { |
| 1813 | dcache_req_valid = ((not dreq[num_cache].valid and // no previous request in this cycle |
| 1814 | not have_sync and // no sync instruction |
| 1815 | dcache_no_lock) or // no previous request in previous cycle |
| 1816 | dcache_lock_owner); // previous request in previous cycle by this cpu |
| 1817 | } |
| 1818 | |
| 1819 | // test if already used |
| 1820 | if (dcache_req_valid) |
| 1821 | { |
| 1822 | bool valid = _dreq.valid; |
| 1823 | |
| 1824 | if (valid) |
| 1825 | { |
| 1826 | PRINTF(" * <CPU2CACHE> DCACHE : Transaction between cpu %d and cache %d (lock)\n",num_cpu,num_cache); |
| 1827 | dreq_num_cache [num_cpu ] = num_cache; |
| 1828 | |
| 1829 | // always lock if no multi cache |
| 1830 | if ((m_nb_dcache == 1) or (not dcache_lock_no_owner)) |
| 1831 | r_dcache_lock [num_cache] = num_cpu; |
| 1832 | } |
| 1833 | else |
| 1834 | { |
| 1835 | PRINTF(" * <CPU2CACHE> DCACHE : No Transaction between cpu %d and cache %d : invalid\n",num_cpu,num_cache); |
| 1836 | dreq_num_cache [num_cpu] = m_nb_dcache; |
| 1837 | } |
| 1838 | |
| 1839 | dreq_cached [num_cache] = m_cacheability_table[(vci_addr_t)_dreq.addr]; |
| 1840 | dreq_num_cpu [num_cache] = num_cpu; |
| 1841 | dreq [num_cache] = _dreq; |
| 1842 | dreq [num_cache].addr = addr; |
| 1843 | } |
| 1844 | else |
| 1845 | { |
| 1846 | PRINTF(" * <CPU2CACHE> DCACHE : No transaction (cpu %d)\n",num_cpu); |
| 1847 | |
| 1848 | dreq_num_cache [num_cpu] = m_nb_dcache; |
| 1849 | } |
| 1850 | |
| 1851 | |
| 1852 | #if CC_XCACHE_WRAPPER_DEBUG |
| 1853 | if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN) |
| 1854 | { |
| 1855 | std::cout << " * <CPU2CACHE> Instruction Request : " << ireq_num_cache[num_cpu] << " - " << _ireq << std::endl |
| 1856 | << " * <CPU2CACHE> Data Request : " << dreq_num_cache[num_cpu] << " - " << _dreq << std::endl; |
| 1857 | } |
| 1858 | #endif |
| 1859 | } |
| 1860 | |
| 1861 | // round robin priority |
| 1862 | r_cpu_prior = (r_cpu_prior+1)%m_nb_cpu; |
| 1863 | |
| 1864 | ///////////////////////////////////////////////////////////////////// |
| 1865 | // The ICACHE FSM controls the following ressources: |
| 1866 | // - r_icache_fsm |
| 1867 | // - r_icache_fsm_save |
| 1868 | // - r_icache instruction cache access |
| 1869 | // - r_icache_addr_save |
| 1870 | // - r_icache_miss_req set |
| 1871 | // - r_icache_unc_req set |
| 1872 | // - r_icache_buf_unc_valid set |
| 1873 | // - r_vci_rsp_icache_miss_ok reset |
| 1874 | // - r_vci_rsp_ins_error reset |
| 1875 | // - r_tgt_icache_req reset |
| 1876 | // - ireq & irsp structures for communication with the processor |
| 1877 | // |
| 1878 | // 1/ External requests (update or invalidate) have highest priority. |
| 1879 | // They are taken into account in the IDLE and WAIT states. |
| 1880 | // As external hit should be extremly rare on the ICACHE, |
| 1881 | // all external requests are handled as invalidate... |
| 1882 | // In case of external request the ICACHE FSM goes to the CC_CHECK |
| 1883 | // state to test the external hit, and returns in the |
| 1884 | // pre-empted state after completion. |
| 1885 | // 2/ Processor requests are taken into account only in the IDLE state. |
| 1886 | // In case of MISS, or in case of uncached instruction, the FSM |
| 1887 | // writes the missing address line in the r_icache_addr_save register |
| 1888 | // and sets the r_icache_miss_req or the r_icache_unc_req flip-flops. |
| 1889 | // These request flip-flops are reset by the VCI_RSP FSM |
| 1890 | // when the VCI transaction is completed and the r_icache_buf_unc_valid |
| 1891 | // is set in case of uncached access. |
| 1892 | // In case of bus error, the VCI_RSP FSM sets the r_vci_rsp_ins_error |
| 1893 | // flip-flop. It is reset by the ICACHE FSM. |
| 1894 | /////////////////////////////////////////////////////////////////////// |
| 1895 | |
| 1896 | for (uint32_t num_cache=0; num_cache<m_nb_icache; ++num_cache) |
| 1897 | { |
| 1898 | typename iss_t::InstructionRequest _ireq = ireq [num_cache]; |
| 1899 | typename iss_t::InstructionResponse _irsp = ISS_IRSP_INITIALIZER; |
| 1900 | |
| 1901 | switch(r_icache_fsm[num_cache]) { |
| 1902 | ///////////////// |
| 1903 | case ICACHE_IDLE: |
| 1904 | { |
| 1905 | if ( r_tgt_icache_req[num_cache] ) { // external request |
| 1906 | // if ( _ireq.valid ) m_cost_ins_miss_frz++; |
| 1907 | r_icache_fsm [num_cache] = ICACHE_CC_CHECK; |
| 1908 | r_icache_fsm_save[num_cache] = r_icache_fsm[num_cache]; |
830 | | |
831 | | // if data and instruction have the inval line, need two responses |
832 | | if ( r_tgt_icache_rsp and r_tgt_dcache_rsp ) |
| 2120 | } |
| 2121 | |
| 2122 | break; |
| 2123 | } |
| 2124 | //////////////////// |
| 2125 | case ICACHE_CC_CLEANUP: |
| 2126 | { |
| 2127 | // cleanup |
| 2128 | if(not r_icache_cleanup_req[num_cache]){ |
| 2129 | r_icache_cleanup_req [num_cache] = true; |
| 2130 | r_icache_cleanup_line[num_cache] = r_icache_addr_save[num_cache].read() >> m_icache_words_shift; |
| 2131 | r_icache_fsm [num_cache] = ICACHE_IDLE; |
| 2132 | |
| 2133 | m_cpt_icache_dir_read += m_icache_ways; |
| 2134 | r_icache[num_cache]->inval((addr_40)r_icache_addr_save[num_cache]); |
| 2135 | } |
| 2136 | break; |
| 2137 | } |
| 2138 | ///////////////////// |
| 2139 | case ICACHE_CC_CHECK: // read directory in case of invalidate or update request |
| 2140 | { |
| 2141 | |
| 2142 | m_cpt_icache_dir_read += m_icache_ways; |
| 2143 | m_cpt_icache_data_read += m_icache_ways; |
| 2144 | addr_40 ad = r_tgt_iaddr; |
| 2145 | data_t icache_rdata = 0; |
| 2146 | |
| 2147 | PRINTF(" * <ICACHE [%d]> CC_CHECK\n",num_cache); |
| 2148 | |
| 2149 | if((r_icache_fsm_save[num_cache] == ICACHE_MISS_WAIT) and |
| 2150 | ((r_icache_addr_save[num_cache].read() & ~((m_icache_words<<2)-1)) == (ad & ~((m_icache_words<<2)-1)))) { |
| 2151 | PRINTF(" * <ICACHE [%d]> have request, need inval rsp\n",num_cache); |
| 2152 | |
| 2153 | r_icache_inval_rsp[num_cache] = true; |
| 2154 | r_tgt_icache_req [num_cache] = false; |
| 2155 | if(r_tgt_update){ // Also send a cleanup and answer |
| 2156 | PRINTF(" * <ICACHE [%d]> send a cleanup and answer\n",num_cache); |
| 2157 | r_tgt_icache_rsp[num_cache] = true; |
| 2158 | } else { // Also send a cleanup but don't answer |
| 2159 | PRINTF(" * <ICACHE [%d]> send a cleanup and but don't answer\n",num_cache); |
| 2160 | r_tgt_icache_rsp[num_cache] = false; |
| 2161 | } |
| 2162 | r_icache_fsm[num_cache] = r_icache_fsm_save[num_cache]; |
| 2163 | } else { |
| 2164 | bool icache_hit = r_icache[num_cache]->read(ad, &icache_rdata); |
| 2165 | |
| 2166 | PRINTF(" * <ICACHE [%d]> have no request, hit cache : %d\n",num_cache,icache_hit); |
| 2167 | |
| 2168 | if ( icache_hit and r_tgt_update) |
| 2169 | { |
| 2170 | uint32_t word = r_cache_word; |
| 2171 | data_t mask = vci_param::be2mask(r_tgt_be[word]); |
| 2172 | data_t rdata = 0; |
| 2173 | |
| 2174 | r_icache[num_cache]->read(ad+word*4,&rdata); |
| 2175 | r_tgt_buf[word] = (mask & r_tgt_buf[word]) | (~mask & rdata); |
| 2176 | |
| 2177 | word ++; |
| 2178 | |
| 2179 | // Find next valid word |
| 2180 | for (; word<m_icache_words; ++word) |
| 2181 | if (r_tgt_be[word] != 0) |
| 2182 | break; |
| 2183 | |
| 2184 | if (word==m_icache_words) |
| 2185 | { |
| 2186 | r_icache_fsm[num_cache] = ICACHE_CC_UPDT; |
| 2187 | |
| 2188 | // find next valid word |
| 2189 | for (word=0; word<m_icache_words; ++word) |
| 2190 | if (r_tgt_be[word] != 0) |
| 2191 | break; |
| 2192 | } |
| 2193 | r_cache_word = word; |
| 2194 | |
| 2195 | } else if ( icache_hit and not r_tgt_update) { |
| 2196 | r_icache_fsm[num_cache] = ICACHE_CC_INVAL; |
| 2197 | } else { // instruction not found (can happen) |
| 2198 | r_tgt_icache_req[num_cache] = false; |
| 2199 | if(r_tgt_update){ |
| 2200 | r_tgt_icache_rsp[num_cache] = true; |
| 2201 | } else { |
| 2202 | r_tgt_icache_rsp[num_cache] = false; |
| 2203 | } |
| 2204 | r_icache_fsm[num_cache] = r_icache_fsm_save[num_cache]; |
| 2205 | } |
| 2206 | } |
| 2207 | break; |
| 2208 | } |
| 2209 | ///////////////////// |
| 2210 | case ICACHE_CC_INVAL: |
| 2211 | { |
| 2212 | addr_40 ad = r_tgt_iaddr; |
| 2213 | // if ( _ireq.valid ) m_cost_ins_miss_frz++; |
| 2214 | m_cpt_icache_dir_read += m_icache_ways; |
| 2215 | r_tgt_icache_rsp[num_cache] = true; |
| 2216 | r_icache[num_cache]->inval(ad); |
| 2217 | r_tgt_icache_req[num_cache] = false; |
| 2218 | r_icache_fsm [num_cache] = r_icache_fsm_save[num_cache]; |
| 2219 | break; |
| 2220 | } |
| 2221 | ///////////////////// |
| 2222 | case ICACHE_CC_UPDT: |
| 2223 | { |
| 2224 | addr_40 ad = r_tgt_iaddr.read(); |
| 2225 | m_cpt_icache_dir_write++; |
| 2226 | m_cpt_icache_data_write++; |
| 2227 | |
| 2228 | uint32_t word = r_cache_word; |
| 2229 | |
| 2230 | if(r_tgt_be[word]) |
| 2231 | r_icache[num_cache]->write(ad+word*4, r_tgt_buf[word]); |
| 2232 | |
| 2233 | word ++; |
| 2234 | |
| 2235 | // find next valid word |
| 2236 | for (; word<m_icache_words; ++word) |
| 2237 | if (r_tgt_be[word] != 0) |
| 2238 | break; |
| 2239 | |
| 2240 | if (word==m_icache_words) |
| 2241 | { |
| 2242 | r_tgt_icache_req[num_cache] = false; |
| 2243 | r_tgt_icache_rsp[num_cache] = true; |
| 2244 | r_icache_fsm [num_cache] = r_icache_fsm_save[num_cache].read(); |
| 2245 | word = 0; |
| 2246 | } |
| 2247 | r_cache_word = word; |
| 2248 | |
| 2249 | break; |
| 2250 | } |
| 2251 | |
| 2252 | }// end switch r_icache_fsm |
| 2253 | |
| 2254 | irsp [num_cache] = _irsp; |
| 2255 | if (_ireq.valid and _irsp.valid) |
| 2256 | { |
| 2257 | PRINTF(" * <CPU2CACHE> Transaction between cpu %d and Icache %d (unlock)\n",r_icache_lock [num_cache].read(),num_cache); |
| 2258 | |
| 2259 | r_icache_lock [num_cache] = m_nb_cpu; |
| 2260 | m_cpt_icache_access [num_cache] ++; |
| 2261 | } |
| 2262 | |
| 2263 | }// end for num_cache |
| 2264 | |
| 2265 | //////////////////////////////////////////////////////////////////////:///////////// |
| 2266 | // The DCACHE FSM controls the following ressources: |
| 2267 | // - r_dcache_fsm |
| 2268 | // - r_dcache_fsm_save |
| 2269 | // - r_dcache (data cache access) |
| 2270 | // - r_dcache_addr_save |
| 2271 | // - r_dcache_wdata_save |
| 2272 | // - r_dcache_rdata_save |
| 2273 | // - r_dcache_type_save |
| 2274 | // - r_dcache_be_save |
| 2275 | // - r_dcache_cached_save |
| 2276 | // - r_dcache_miss_req set |
| 2277 | // - r_dcache_unc_req set |
| 2278 | // - r_dcache_cleanup_req set |
| 2279 | // - r_vci_rsp_data_error reset |
| 2280 | // - r_tgt_dcache_req reset |
| 2281 | // - r_wbuf write |
| 2282 | // - dreq & drsp structures for communication with the processor |
| 2283 | // |
| 2284 | // 1/ EXTERNAL REQUEST : |
| 2285 | // There is an external request when the tgt_dcache req flip-flop is set, |
| 2286 | // requesting a line invalidation or a line update. |
| 2287 | // External requests are taken into account in the states IDLE, WRITE_REQ, |
| 2288 | // UNC_WAIT, MISS_WAIT, and have the highest priority : |
| 2289 | // The actions associated to the pre-empted state are not executed, the DCACHE FSM |
| 2290 | // goes to the CC_CHECK state to execute the requested action, and returns to the |
| 2291 | // pre-empted state. |
| 2292 | // 2/ PROCESSOR REQUEST : |
| 2293 | // In order to support VCI write burst, the processor requests are taken into account |
| 2294 | // in the WRITE_REQ state as well as in the IDLE state. |
| 2295 | // - In the IDLE state, the processor request cannot be satisfied if |
| 2296 | // there is a cached read miss, or an uncached read. |
| 2297 | // - In the WRITE_REQ state, the request cannot be satisfied if |
| 2298 | // there is a cached read miss, or an uncached read, |
| 2299 | // or when the write buffer is full. |
| 2300 | // - In all other states, the processor request is not satisfied. |
| 2301 | // |
| 2302 | // The cache access takes into account the cacheability_table. |
| 2303 | // In case of processor request, there is five conditions to exit the IDLE state: |
| 2304 | // - CACHED READ MISS => to the MISS_WAIT state (waiting the r_miss_ok signal), |
| 2305 | // then to the MISS_UPDT state, and finally to the IDLE state. |
| 2306 | // - UNCACHED READ => to the UNC_WAIT state (waiting the r_miss_ok signal), |
| 2307 | // and to the IDLE state. |
| 2308 | // - CACHE INVALIDATE HIT => to the INVAL state for one cycle, then to IDLE state. |
| 2309 | // - WRITE MISS => directly to the WRITE_REQ state to access the write buffer. |
| 2310 | // - WRITE HIT => to the WRITE_UPDT state, then to the WRITE_REQ state. |
| 2311 | // |
| 2312 | // Error handling : Read Bus Errors are synchronous events, but |
| 2313 | // Write Bus Errors are asynchronous events (processor is not frozen). |
| 2314 | // - If a Read Bus Error is detected, the VCI_RSP FSM sets the |
| 2315 | // r_vci_rsp_data_error flip-flop, and the synchronous error is signaled |
| 2316 | // by the DCACHE FSM. |
| 2317 | // - If a Write Bus Error is detected, the VCI_RSP FSM signals |
| 2318 | // the asynchronous error using the setWriteBerr() method. |
| 2319 | /////////////////////////////////////////////////////////////////////////////////// |
| 2320 | |
| 2321 | for (uint32_t num_cache=0; num_cache<m_nb_dcache; ++num_cache) |
| 2322 | { |
| 2323 | typename iss_t::DataRequest _dreq = dreq [num_cache]; |
| 2324 | typename iss_t::DataResponse _drsp = ISS_DRSP_INITIALIZER; |
| 2325 | |
| 2326 | switch ( r_dcache_fsm[num_cache]) { |
| 2327 | |
| 2328 | ///////////////// |
| 2329 | case DCACHE_IDLE: |
| 2330 | { |
| 2331 | if ( r_tgt_dcache_req[num_cache]) { // external request |
| 2332 | r_dcache_fsm [num_cache] = DCACHE_CC_CHECK; |
| 2333 | r_dcache_fsm_save[num_cache] = r_dcache_fsm[num_cache]; |
| 2334 | break; |
| 2335 | } |
| 2336 | |
| 2337 | if ( _dreq.valid ) { |
| 2338 | PRINTF(" * <DCACHE [%d]> Have dreq\n",num_cache); |
| 2339 | |
| 2340 | data_t dcache_rdata = 0; |
| 2341 | // dcache_cached and dcache_hit don't used with _dreq.type == {DATA_SC, XTN_READ, XTN_WRITE} |
| 2342 | bool dcache_cached = dreq_cached [num_cache]; |
| 2343 | uint32_t dcache_num_cpu = dreq_num_cpu [num_cache]; |
| 2344 | bool dcache_hit = r_dcache[num_cache]->read((vci_addr_t) _dreq.addr, &dcache_rdata); |
| 2345 | bool dcache_cleanup_hit = r_dcache_cleanup_req[num_cache] and (((addr_40)_dreq.addr >> (addr_40)m_dcache_words_shift) == r_dcache_cleanup_line[num_cache].read()); |
| 2346 | |
| 2347 | PRINTF(" * <DCACHE [%d]> hit %d - cached %d - cleanup_hit %d\n",num_cache,dcache_hit, dcache_cached, dcache_cleanup_hit); |
| 2348 | |
| 2349 | m_cpt_dcache_data_read += m_dcache_ways; |
| 2350 | m_cpt_dcache_dir_read += m_dcache_ways; |
| 2351 | |
| 2352 | switch( _dreq.type ) { |
| 2353 | case iss_t::DATA_READ: |
| 2354 | case iss_t::DATA_LL: |
| 2355 | { |
| 2356 | m_cpt_data_read++; // new dcache read |
| 2357 | |
| 2358 | if (dcache_hit) // no special test for uncached read, because it's always miss |
| 2359 | { |
| 2360 | // address is in the cache : return the word |
| 2361 | r_dcache_fsm [num_cache] = DCACHE_IDLE; |
| 2362 | |
| 2363 | _drsp.valid = true; |
| 2364 | _drsp.rdata = dcache_rdata; // return read data (cf dcache_hit) |
| 2365 | |
| 2366 | // if the request is a Load Linked instruction, save request information |
| 2367 | if(_dreq.type == iss_t::DATA_LL) |
| 2368 | { |
| 2369 | PRINTF(" * <DCACHE [%d]> ll_valid = true\n",num_cache); |
| 2370 | |
| 2371 | r_dcache_ll_valid [num_cache][dcache_num_cpu] = true; |
| 2372 | r_dcache_ll_data [num_cache][dcache_num_cpu] = dcache_rdata; |
| 2373 | r_dcache_ll_addr [num_cache][dcache_num_cpu] = (vci_addr_t) _dreq.addr; |
| 2374 | } |
| 2375 | } |
| 2376 | else |
| 2377 | { |
| 2378 | if (not dcache_cleanup_hit) |
| 2379 | { |
| 2380 | |
| 2381 | // Miss : send signal at the CMD_FSM (via r_dcache_miss_req or r_dcache_unc_req) |
| 2382 | if ( dcache_cached ) { |
| 2383 | // to prevent deadlock, miss victim don't be block |
| 2384 | if (not r_dcache_cleanup_req[num_cache].read()) |
| 2385 | { |
| 2386 | m_cpt_data_read_miss++; |
| 2387 | m_cost_data_miss_frz++; |
| 2388 | r_dcache_miss_req [num_cache] = true; |
| 2389 | r_dcache_fsm [num_cache] = DCACHE_MISS_VICTIM; |
| 2390 | } |
| 2391 | else |
| 2392 | m_cpt_icache_miss_victim_wait [num_cache] ++; |
| 2393 | } else { |
| 2394 | if (not r_dcache_previous_unc[num_cache].read()) // strongly order to the uncached access |
| 2395 | { |
| 2396 | r_dcache_previous_unc[num_cache] = true; |
| 2397 | |
| 2398 | m_cpt_data_read_uncached++; |
| 2399 | m_cost_unc_read_frz++; |
| 2400 | r_dcache_unc_req[num_cache] = true; |
| 2401 | r_dcache_fsm [num_cache] = DCACHE_UNC_WAIT; |
| 2402 | } |
| 2403 | } |
| 2404 | } |
| 2405 | } |
| 2406 | } |
| 2407 | break; |
| 2408 | case iss_t::DATA_SC: |
| 2409 | { |
| 2410 | PRINTF(" * <DCACHE [%d]> DATA_SC - ll_valid = %d, num_cpu = %d\n",num_cache,r_dcache_ll_valid[num_cache][dcache_num_cpu].read(),dcache_num_cpu); |
| 2411 | |
| 2412 | if (not r_dcache_previous_unc[num_cache].read() and not dcache_cleanup_hit) // strongly order to the uncached access |
| 2413 | { |
| 2414 | //m_cpt_data_read_unc++; // instruction must read the memory in uncached mode |
| 2415 | m_cost_unc_read_frz++; |
| 2416 | |
| 2417 | // if previous load linked (with the same address), make a transaction |
| 2418 | // else, keep in IDLE state and return 1 (no OK) |
| 2419 | if( r_dcache_ll_valid[num_cache][dcache_num_cpu].read() and |
| 2420 | (r_dcache_ll_addr [num_cache][dcache_num_cpu].read() == (vci_addr_t)_dreq.addr)){ |
| 2421 | PRINTF(" * <DCACHE [%d]> have previous load linked\n",num_cache); |
| 2422 | |
| 2423 | r_dcache_previous_unc[num_cache] = true; |
| 2424 | r_dcache_sc_req [num_cache] = true; |
| 2425 | |
| 2426 | r_dcache_fsm [num_cache] = DCACHE_SC_WAIT; |
| 2427 | } else { |
| 2428 | PRINTF(" * <DCACHE [%d]> don't have previous load linked\n",num_cache); |
| 2429 | |
| 2430 | _drsp.valid = true; |
| 2431 | _drsp.rdata = 1; // SC rsp NOK |
| 2432 | r_dcache_ll_valid[num_cache][dcache_num_cpu] = false; |
| 2433 | } |
| 2434 | } |
| 2435 | |
| 2436 | break; |
| 2437 | } |
| 2438 | case iss_t::XTN_READ: |
| 2439 | case iss_t::XTN_WRITE: |
| 2440 | { |
| 2441 | bool valid = false; |
| 2442 | // only DCACHE INVALIDATE and SYNC request are supported |
| 2443 | switch (_dreq.addr>>2) |
| 2444 | { |
| 2445 | case iss_t::XTN_DCACHE_INVAL : |
| 2446 | { |
| 2447 | valid = true; |
| 2448 | r_dcache_fsm[num_cache] = DCACHE_INVAL; |
| 2449 | break; |
| 2450 | } |
| 2451 | case iss_t::XTN_SYNC : |
| 2452 | { |
| 2453 | // Test if write buffer is already empty |
| 2454 | // * gain : 1 cycle |
| 2455 | // * cost : can be on the critical path |
| 2456 | |
| 2457 | bool empty=true; |
| 2458 | for (uint32_t i=0; i<m_nb_dcache; ++i) |
| 2459 | empty &= r_wbuf[i]->empty(); |
| 2460 | |
| 2461 | if (empty) |
| 2462 | { |
| 2463 | valid = true; |
| 2464 | r_dcache_fsm [num_cache] = DCACHE_IDLE; |
| 2465 | } |
| 2466 | else |
| 2467 | { |
| 2468 | valid = false; |
| 2469 | r_dcache_fsm [num_cache] = DCACHE_SYNC; |
| 2470 | r_dcache_sync[num_cache] = true; |
| 2471 | } |
| 2472 | break; |
| 2473 | } |
| 2474 | default : |
| 2475 | { |
| 2476 | // std::cout << "Warning in VCI_CC_XCACHE_WRAPPER " << name() << std::endl; |
| 2477 | // std::cout << "Unsupported external access : " << (_dreq.addr>>2) << std::endl; |
| 2478 | |
| 2479 | r_dcache_fsm [num_cache] = DCACHE_IDLE; |
| 2480 | } |
| 2481 | }//end switch (_dreq.addr>>2) |
| 2482 | |
| 2483 | _drsp.valid = valid; |
| 2484 | _drsp.rdata = 0; |
| 2485 | break; |
| 2486 | } |
| 2487 | case iss_t::DATA_WRITE: |
| 2488 | |
| 2489 | PRINTF(" * <DCACHE [%d]> r_dcache_previous_unc : %d\n",num_cache,r_dcache_previous_unc[num_cache].read()); |
| 2490 | |
| 2491 | if (dcache_cached or not r_dcache_previous_unc[num_cache].read()) // strongly order to the uncached access |
836 | | r_tgt_icache_rsp = false; // only reset one for respond the second time |
| 2518 | m_cpt_data_write++; |
| 2519 | |
| 2520 | if (not dcache_cached) |
| 2521 | { |
| 2522 | r_dcache_previous_unc[num_cache] = true; |
| 2523 | m_cpt_data_write_uncached++; |
| 2524 | } |
| 2525 | else if (not dcache_hit) |
| 2526 | m_cpt_data_write_miss++; |
| 2527 | |
| 2528 | if (dcache_hit) { |
| 2529 | // update data cache |
| 2530 | r_dcache_fsm[num_cache] = DCACHE_WRITE_UPDT; |
| 2531 | } else { |
| 2532 | // write accepted |
| 2533 | r_dcache_fsm [num_cache] = DCACHE_IDLE; |
| 2534 | } |
| 2535 | } |
| 2536 | |
| 2537 | _drsp.valid = valid; |
| 2538 | _drsp.rdata = 0; |
| 2539 | } |
| 2540 | break; |
| 2541 | } // end switch _dreq.type |
| 2542 | |
| 2543 | r_dcache_addr_save [num_cache] = (addr_40) _dreq.addr; |
| 2544 | r_dcache_type_save [num_cache] = _dreq.type; |
| 2545 | r_dcache_wdata_save [num_cache] = _dreq.wdata; |
| 2546 | r_dcache_be_save [num_cache] = _dreq.be; |
| 2547 | r_dcache_rdata_save [num_cache] = dcache_rdata; |
| 2548 | r_dcache_cached_save [num_cache] = dcache_cached; |
| 2549 | r_dcache_num_cpu_save[num_cache] = dcache_num_cpu; |
| 2550 | |
| 2551 | } else { // end if _dreq.valid |
| 2552 | r_dcache_fsm [num_cache] = DCACHE_IDLE; |
| 2553 | } |
| 2554 | |
| 2555 | break; |
| 2556 | } |
| 2557 | /////////////////////// |
| 2558 | case DCACHE_WRITE_UPDT: |
| 2559 | { |
| 2560 | m_cpt_dcache_data_write++; |
| 2561 | data_t mask = vci_param::be2mask(r_dcache_be_save[num_cache]); |
| 2562 | data_t wdata = (mask & r_dcache_wdata_save[num_cache]) | (~mask & r_dcache_rdata_save[num_cache]); |
| 2563 | vci_addr_t ad = r_dcache_addr_save[num_cache].read(); |
| 2564 | r_dcache[num_cache]->write(ad, wdata); |
| 2565 | |
| 2566 | int dcache_fsm_next = DCACHE_IDLE; // default |
| 2567 | |
| 2568 | // Test if write after write |
| 2569 | |
| 2570 | if (_dreq.valid and (_dreq.type == iss_t::DATA_WRITE)) |
| 2571 | { |
| 2572 | PRINTF(" * <DCACHE [%d]> Have dreq (Write after Write)\n",num_cache); |
| 2573 | |
| 2574 | data_t dcache_rdata = 0; |
| 2575 | // dcache_cached and dcache_hit don't used with _dreq.type == {DATA_SC, XTN_READ, XTN_WRITE} |
| 2576 | bool dcache_cached = dreq_cached [num_cache]; |
| 2577 | uint32_t dcache_num_cpu = dreq_num_cpu [num_cache]; |
| 2578 | bool dcache_hit = r_dcache[num_cache]->read((vci_addr_t) _dreq.addr, &dcache_rdata); |
| 2579 | |
| 2580 | m_cpt_dcache_data_read += m_dcache_ways; |
| 2581 | m_cpt_dcache_dir_read += m_dcache_ways; |
| 2582 | |
| 2583 | PRINTF(" * <DCACHE [%d]> r_dcache_previous_unc : %d\n",num_cache,r_dcache_previous_unc[num_cache].read()); |
| 2584 | |
| 2585 | if (dcache_cached or not r_dcache_previous_unc[num_cache].read()) // strongly order to the uncached access |
| 2586 | { |
| 2587 | bool valid; |
| 2588 | addr_40 addr = _dreq.addr; |
| 2589 | set_num_dcache(addr,num_cache); |
| 2590 | |
| 2591 | // FIXME : |
| 2592 | // * dans le wbuf, ne pas mettre l'adresse au complet (economie de surface) |
| 2593 | // * pour cela, virer le set_num_dcache ! |
| 2594 | valid = r_wbuf[num_cache]->write(addr, _dreq.be, _dreq.wdata, dcache_cached, dcache_num_cpu); |
| 2595 | |
| 2596 | #if MWBUF_VHDL_TESTBENCH |
| 2597 | vhdl_mwbuf_port_write_val [num_cache] = (vhdl_tb_t)1; |
| 2598 | vhdl_mwbuf_test_write_ack [num_cache] = (vhdl_tb_t)1; |
| 2599 | vhdl_mwbuf_port_write_ack [num_cache] = (vhdl_tb_t)valid; |
| 2600 | vhdl_mwbuf_port_write_addr [num_cache] = (vhdl_tb_t)addr; |
| 2601 | vhdl_mwbuf_port_write_data [num_cache] = (vhdl_tb_t)_dreq.wdata; |
| 2602 | vhdl_mwbuf_port_write_be [num_cache] = (vhdl_tb_t)_dreq.be; |
| 2603 | vhdl_mwbuf_port_write_cached [num_cache] = (vhdl_tb_t)dcache_cached; |
| 2604 | vhdl_mwbuf_port_write_cpu_id [num_cache] = (vhdl_tb_t)dcache_num_cpu; |
| 2605 | #endif |
| 2606 | |
| 2607 | PRINTF(" * <DCACHE [%d]> r_wbuf valid : %d\n",num_cache,valid); |
| 2608 | |
| 2609 | if (valid) |
| 2610 | { |
| 2611 | m_cpt_dcache_store_after_store [num_cache] ++; |
| 2612 | |
| 2613 | m_cpt_data_write++; |
| 2614 | |
| 2615 | if (not dcache_cached) |
| 2616 | { |
| 2617 | r_dcache_previous_unc[num_cache] = true; |
| 2618 | m_cpt_data_write_uncached++; |
| 2619 | } |
| 2620 | else if (not dcache_hit) |
| 2621 | m_cpt_data_write_miss++; |
| 2622 | |
| 2623 | if (dcache_hit) { |
| 2624 | // update data cache |
| 2625 | dcache_fsm_next = DCACHE_WRITE_UPDT; |
| 2626 | } else { |
| 2627 | // write accepted |
| 2628 | dcache_fsm_next = DCACHE_IDLE; |
| 2629 | } |
| 2630 | } |
| 2631 | |
| 2632 | _drsp.valid = valid; |
| 2633 | _drsp.rdata = 0; |
| 2634 | } |
| 2635 | |
| 2636 | r_dcache_addr_save [num_cache] = (addr_40) _dreq.addr; |
| 2637 | // r_dcache_type_save [num_cache] = _dreq.type; |
| 2638 | r_dcache_wdata_save [num_cache] = _dreq.wdata; |
| 2639 | r_dcache_be_save [num_cache] = _dreq.be; |
| 2640 | r_dcache_rdata_save [num_cache] = dcache_rdata; |
| 2641 | // r_dcache_cached_save [num_cache] = dcache_cached; |
| 2642 | // r_dcache_num_cpu_save[num_cache] = dcache_num_cpu; |
| 2643 | } |
| 2644 | |
| 2645 | r_dcache_fsm [num_cache] = dcache_fsm_next; // default |
| 2646 | |
| 2647 | break; |
| 2648 | } |
| 2649 | ////////////////////// |
| 2650 | case DCACHE_MISS_VICTIM: |
| 2651 | { |
| 2652 | // if (not r_dcache_cleanup_req[num_cache].read()) |
| 2653 | { |
| 2654 | size_t way; |
| 2655 | size_t set; |
| 2656 | vci_addr_t addr = (vci_addr_t) r_dcache_addr_save[num_cache].read(); |
| 2657 | vci_addr_t victim; |
| 2658 | bool victim_val = r_dcache[num_cache]->victim_select(addr, &victim, &way, &set ); |
| 2659 | |
| 2660 | r_dcache_cleanup_req [num_cache] = victim_val; |
| 2661 | r_dcache_cleanup_line [num_cache] = (addr_40) victim; |
| 2662 | r_dcache_miss_way [num_cache] = way; |
| 2663 | r_dcache_miss_set [num_cache] = set; |
| 2664 | |
| 2665 | PRINTF(" * <DCACHE [%d]> MISS_VICTIM : Victim %d - %llx (way %d, set %d)\n",num_cache,victim_val, (blob_t)victim, (int)way, (int)set); |
| 2666 | |
| 2667 | r_dcache_fsm [num_cache] = DCACHE_MISS_WAIT; |
| 2668 | } |
| 2669 | |
| 2670 | break; |
| 2671 | } |
| 2672 | ////////////////////// |
| 2673 | case DCACHE_MISS_WAIT: |
| 2674 | { |
| 2675 | // Multi_cache ; Hit after Miss |
| 2676 | if (m_nb_dcache>0) |
| 2677 | { |
| 2678 | data_t dcache_rdata = 0; |
| 2679 | bool dcache_hit = r_dcache[num_cache]->read((vci_addr_t) _dreq.addr, &dcache_rdata); |
| 2680 | // bool dcache_cached = dreq_cached [num_cache]; |
| 2681 | // uint32_t dcache_num_cpu = dreq_num_cpu [num_cache]; |
| 2682 | |
| 2683 | m_cpt_dcache_data_read += m_dcache_ways; |
| 2684 | m_cpt_dcache_dir_read += m_dcache_ways; |
| 2685 | |
| 2686 | if (_dreq.valid) |
| 2687 | switch (_dreq.type) |
| 2688 | { |
| 2689 | case iss_t::DATA_READ : // accept only hit dcache load |
| 2690 | { |
| 2691 | m_cpt_data_read++; // new dcache read |
| 2692 | |
| 2693 | if (dcache_hit) // no special test for uncached read, because it's always miss |
| 2694 | { |
| 2695 | m_cpt_dcache_hit_after_miss_read [num_cache] ++; |
| 2696 | |
| 2697 | // address is in the cache : return the word |
| 2698 | _drsp.valid = true; |
| 2699 | _drsp.rdata = dcache_rdata; // return read data (cf dcache_hit) |
| 2700 | } |
| 2701 | break; |
| 2702 | } |
| 2703 | // case iss_t::DATA_WRITE : // accept only cached write and miss in dcache (else need update dcache) |
| 2704 | // { |
| 2705 | // if (dcache_cached and not dcache_hit) |
| 2706 | // { |
| 2707 | // bool valid; |
| 2708 | // addr_40 addr = _dreq.addr; |
| 2709 | // set_num_dcache(addr,num_cache); |
| 2710 | |
| 2711 | // // FIXME : |
| 2712 | // // * dans le wbuf, ne pas mettre l'adresse au complet (economie de surface) |
| 2713 | // // * pour cela, virer le set_num_dcache ! |
| 2714 | // valid = r_wbuf[num_cache]->write(addr, _dreq.be, _dreq.wdata, dcache_cached, dcache_num_cpu); |
| 2715 | // PRINTF(" * <DCACHE [%d]> r_wbuf valid : %d\n",num_cache,valid); |
| 2716 | |
| 2717 | // if (valid) |
| 2718 | // { |
| 2719 | // m_cpt_dcache_hit_after_miss_write [num_cache] ++; |
| 2720 | |
| 2721 | // m_cpt_data_write++; |
| 2722 | // m_cpt_data_write_miss++; |
| 2723 | // } |
| 2724 | |
| 2725 | // _drsp.valid = valid; |
| 2726 | // _drsp.rdata = 0; |
| 2727 | // } |
| 2728 | // break; |
| 2729 | // } |
| 2730 | default : |
| 2731 | { |
| 2732 | break; |
| 2733 | } |
| 2734 | } |
| 2735 | } // end multi cache hit after miss |
| 2736 | |
| 2737 | // if ( _dreq.valid ) m_cost_data_miss_frz++; |
| 2738 | if ( r_tgt_dcache_req[num_cache].read() ) { // external request |
| 2739 | r_dcache_fsm [num_cache] = DCACHE_CC_CHECK; |
| 2740 | r_dcache_fsm_save [num_cache] = r_dcache_fsm[num_cache]; |
| 2741 | break; |
| 2742 | } |
| 2743 | |
| 2744 | bool val = (r_vci_rsp_fifo_dcache_data.rok() and |
| 2745 | (r_vci_rsp_fifo_dcache_num_cache.read() == num_cache)); |
| 2746 | |
| 2747 | if (val) |
| 2748 | { |
| 2749 | // Miss read response and no invalidation |
| 2750 | if (r_vci_rsp_data_error[num_cache]) |
| 2751 | { |
| 2752 | r_dcache_fsm [num_cache] = DCACHE_ERROR; |
| 2753 | } |
| 2754 | else |
| 2755 | { |
| 2756 | r_dcache_update_addr[num_cache] = 0; |
| 2757 | r_dcache_fsm [num_cache] = DCACHE_MISS_UPDT; |
| 2758 | } |
| 2759 | } |
| 2760 | break; |
| 2761 | } |
| 2762 | ////////////////////// |
| 2763 | case DCACHE_MISS_UPDT: |
| 2764 | { |
| 2765 | size_t word = r_dcache_update_addr[num_cache].read(); |
| 2766 | vci_addr_t addr = (vci_addr_t) r_dcache_addr_save[num_cache].read(); |
| 2767 | size_t way = r_dcache_miss_way[num_cache].read(); |
| 2768 | size_t set = r_dcache_miss_set[num_cache].read(); |
| 2769 | |
| 2770 | PRINTF(" * <DCACHE [%d]> MISS_UPDT : Victim way %d, set %d\n",num_cache, (int)way, (int)set); |
| 2771 | |
| 2772 | bool val = (r_vci_rsp_fifo_dcache_data.rok() and |
| 2773 | (r_vci_rsp_fifo_dcache_num_cache.read() == num_cache)); |
| 2774 | |
| 2775 | if (val) |
| 2776 | { |
| 2777 | // m_cpt_dcache_dir_write++; |
| 2778 | // if ( _dreq.valid ) m_cost_data_miss_frz++; |
| 2779 | |
| 2780 | // if need invalid rsp, don't modify the cache, but pop the buf_rsp |
| 2781 | // (power save) |
| 2782 | if (not r_dcache_inval_rsp[num_cache]) |
| 2783 | { |
| 2784 | r_dcache[num_cache]->write(way, set, word, r_vci_rsp_fifo_dcache_data.read()); |
| 2785 | m_cpt_dcache_data_write++; |
| 2786 | } |
| 2787 | |
| 2788 | vci_rsp_fifo_dcache_get = true; |
| 2789 | |
| 2790 | r_dcache_update_addr[num_cache] = ++word; |
| 2791 | |
| 2792 | // if last word, finish the update |
| 2793 | if (word >= m_dcache_words) |
| 2794 | { |
| 2795 | // in all case (inval_rsp or not), update the victim tag |
| 2796 | // because victim is already cleanup |
| 2797 | r_dcache[num_cache]->victim_update_tag(addr, way, set); |
| 2798 | |
| 2799 | // Last word : if previous invalid_rsp, can cleanup, else update the TAG |
| 2800 | if (r_dcache_inval_rsp[num_cache]) |
| 2801 | { |
| 2802 | r_dcache_inval_rsp[num_cache] = false; |
| 2803 | r_dcache_fsm [num_cache] = DCACHE_CC_CLEANUP; |
| 2804 | } |
| 2805 | else |
| 2806 | { |
| 2807 | r_dcache_fsm [num_cache] = DCACHE_IDLE; |
868 | | } // end switch TGT_FSM |
869 | | |
870 | | ///////////////////////////////////////////////////////////////////// |
871 | | // The ICACHE FSM controls the following ressources: |
872 | | // - r_icache_fsm |
873 | | // - r_icache_fsm_save |
874 | | // - r_icache instruction cache access |
875 | | // - r_icache_addr_save |
876 | | // - r_icache_miss_req set |
877 | | // - r_icache_unc_req set |
878 | | // - r_icache_buf_unc_valid set |
879 | | // - r_vci_rsp_icache_miss_ok reset |
880 | | // - r_vci_rsp_ins_error reset |
881 | | // - r_tgt_icache_req reset |
882 | | // - ireq & irsp structures for communication with the processor |
883 | | // |
884 | | // 1/ External requests (update or invalidate) have highest priority. |
885 | | // They are taken into account in the IDLE and WAIT states. |
886 | | // As external hit should be extremly rare on the ICACHE, |
887 | | // all external requests are handled as invalidate... |
888 | | // In case of external request the ICACHE FSM goes to the CC_CHECK |
889 | | // state to test the external hit, and returns in the |
890 | | // pre-empted state after completion. |
891 | | // 2/ Processor requests are taken into account only in the IDLE state. |
892 | | // In case of MISS, or in case of uncached instruction, the FSM |
893 | | // writes the missing address line in the r_icache_addr_save register |
894 | | // and sets the r_icache_miss_req or the r_icache_unc_req flip-flops. |
895 | | // These request flip-flops are reset by the VCI_RSP FSM |
896 | | // when the VCI transaction is completed and the r_icache_buf_unc_valid |
897 | | // is set in case of uncached access. |
898 | | // In case of bus error, the VCI_RSP FSM sets the r_vci_rsp_ins_error |
899 | | // flip-flop. It is reset by the ICACHE FSM. |
900 | | /////////////////////////////////////////////////////////////////////// |
901 | | |
902 | | typename iss_t::InstructionRequest ireq = ISS_IREQ_INITIALIZER; |
903 | | typename iss_t::InstructionResponse irsp = ISS_IRSP_INITIALIZER; |
904 | | |
905 | | typename iss_t::DataRequest dreq = ISS_DREQ_INITIALIZER; |
906 | | typename iss_t::DataResponse drsp = ISS_DRSP_INITIALIZER; |
907 | | |
908 | | m_iss.getRequests( ireq, dreq ); |
| 3023 | r_cache_word = word; |
| 3024 | |
| 3025 | break; |
| 3026 | } |
| 3027 | ///////////////////// |
| 3028 | case DCACHE_CC_INVAL: // invalidate a cache line |
| 3029 | { |
| 3030 | addr_40 ad = r_tgt_daddr; |
| 3031 | r_tgt_dcache_rsp[num_cache] = true; |
| 3032 | r_dcache [num_cache]->inval(ad); |
| 3033 | r_tgt_dcache_req[num_cache] = false; |
| 3034 | r_dcache_fsm [num_cache] = r_dcache_fsm_save[num_cache]; |
| 3035 | break; |
| 3036 | } |
| 3037 | /////////////////// |
| 3038 | case DCACHE_CC_CLEANUP: |
| 3039 | { |
| 3040 | // cleanup |
| 3041 | if(not r_dcache_cleanup_req[num_cache]){ |
| 3042 | r_dcache_cleanup_req [num_cache] = true; |
| 3043 | r_dcache_cleanup_line [num_cache] = r_dcache_addr_save[num_cache].read() >> m_dcache_words_shift; |
| 3044 | r_dcache_fsm [num_cache] = DCACHE_IDLE; |
| 3045 | |
| 3046 | m_cpt_dcache_dir_read += m_dcache_ways; |
| 3047 | r_dcache[num_cache]->inval((addr_40)r_dcache_addr_save[num_cache]); |
| 3048 | } |
| 3049 | break; |
| 3050 | } |
| 3051 | |
| 3052 | } // end switch r_dcache_fsm |
| 3053 | |
| 3054 | ////////// write buffer state update ///////////// |
| 3055 | // The update() method must be called at each cycle to update the internal state. |
| 3056 | // All pending write requests must be locked in case of SYNC |
| 3057 | |
| 3058 | r_wbuf[num_cache]->update (have_sync); |
| 3059 | |
| 3060 | #if MWBUF_VHDL_TESTBENCH |
| 3061 | vhdl_mwbuf_port_flush [num_cache] = (vhdl_tb_t)have_sync; |
| 3062 | #endif |
| 3063 | |
| 3064 | drsp [num_cache] = _drsp; |
| 3065 | if (_dreq.valid and _drsp.valid) |
| 3066 | { |
| 3067 | PRINTF(" * <CPU2CACHE> Transaction between cpu %d and Dcache %d (unlock)\n",r_dcache_lock [num_cache].read(),num_cache); |
| 3068 | |
| 3069 | r_dcache_lock [num_cache] = m_nb_cpu; |
| 3070 | m_cpt_dcache_access [num_cache] ++; |
| 3071 | } |
| 3072 | |
| 3073 | }// end for num_cache |
| 3074 | |
| 3075 | /////////// execute one iss cycle ///////////////////////////////////////////// |
| 3076 | |
| 3077 | for (uint32_t num_cpu=0; num_cpu<m_nb_cpu; ++num_cpu) |
| 3078 | { |
| 3079 | // Test if the resquest is accepted |
| 3080 | typename iss_t::InstructionResponse _irsp = ISS_IRSP_INITIALIZER; |
| 3081 | typename iss_t::DataResponse _drsp = ISS_DRSP_INITIALIZER; |
| 3082 | |
| 3083 | if (ireq_num_cache[num_cpu]<m_nb_icache) |
| 3084 | _irsp = irsp[ireq_num_cache[num_cpu]]; |
| 3085 | if (dreq_num_cache[num_cpu]<m_nb_dcache) |
| 3086 | _drsp = drsp[dreq_num_cache[num_cpu]]; |
| 3087 | |
| 3088 | #if CC_XCACHE_WRAPPER_STOP_SIMULATION or CC_XCACHE_WRAPPER_DEBUG_FILE_TRANSACTION |
| 3089 | typename iss_t::InstructionRequest _ireq = ISS_IREQ_INITIALIZER; |
| 3090 | typename iss_t::DataRequest _dreq = ISS_DREQ_INITIALIZER; |
| 3091 | |
| 3092 | if (ireq_num_cache[num_cpu]<m_nb_icache) |
| 3093 | _ireq = ireq[ireq_num_cache[num_cpu]]; |
| 3094 | if (dreq_num_cache[num_cpu]<m_nb_dcache) |
| 3095 | _dreq = dreq[dreq_num_cache[num_cpu]]; |
| 3096 | #endif |
975 | | ////////////////////// |
976 | | #if CC_XCACHE_WRAPPER_SELECT_VICTIM |
977 | | case ICACHE_MISS_VICTIM: |
978 | | { |
979 | | if (not r_icache_cleanup_req) |
980 | | { |
981 | | size_t way; |
982 | | size_t set; |
983 | | vci_addr_t addr = (vci_addr_t) r_icache_addr_save.read(); |
984 | | vci_addr_t victim; |
985 | | |
986 | | r_icache_cleanup_req = r_icache.victim_select(addr, &victim, &way, &set ); |
987 | | r_icache_cleanup_line = (addr_40) victim; |
988 | | r_icache_miss_way = way; |
989 | | r_icache_miss_set = set; |
990 | | |
991 | | r_icache_fsm = ICACHE_MISS_WAIT; |
992 | | } |
993 | | break; |
994 | | } |
995 | | #endif |
996 | | ////////////////////// |
997 | | case ICACHE_MISS_WAIT: |
998 | | { |
999 | | m_cost_ins_miss_frz++; |
1000 | | if ( r_tgt_icache_req ) { // external request |
1001 | | r_icache_fsm = ICACHE_CC_CHECK; |
1002 | | r_icache_fsm_save = r_icache_fsm.read(); |
1003 | | break; |
1004 | | } |
1005 | | |
1006 | | bool val = CACHE_MISS_BUF_RSP_VAL(i,0); |
1007 | | |
1008 | | PRINTF(" * <ICACHE> val : %d\n",val); |
1009 | | |
1010 | | if (val) |
1011 | | { |
1012 | | PRINTF(" * <ICACHE> r_icache_inval_rsp : %d\n",(int) r_icache_inval_rsp ); |
1013 | | PRINTF(" * <ICACHE> r_vci_rsp_ins_error : %d\n",(int) r_vci_rsp_ins_error ); |
1014 | | PRINTF(" * <ICACHE> r_icache_cleanup_req : %d\n",(int) r_icache_cleanup_req); |
1015 | | |
1016 | | // if (not r_icache_inval_rsp ) |
1017 | | // { |
1018 | | // Miss read response and no invalidation |
1019 | | if ( r_vci_rsp_ins_error ) { |
1020 | | r_icache_fsm = ICACHE_ERROR; |
1021 | | } else { |
1022 | | #if not CC_XCACHE_WRAPPER_SELECT_VICTIM |
1023 | | if (not r_icache_cleanup_req.read()) |
1024 | | #endif |
1025 | | { |
1026 | | r_icache_update_addr = 0; |
1027 | | r_icache_fsm = ICACHE_MISS_UPDT; |
1028 | | } |
1029 | | } |
1030 | | // } |
1031 | | // else |
1032 | | // { |
1033 | | // r_icache_inval_rsp = false; |
1034 | | |
1035 | | // // Miss read response and invalidation |
1036 | | // if ( r_vci_rsp_ins_error ) |
1037 | | // r_icache_fsm = ICACHE_ERROR; |
1038 | | // else |
1039 | | // r_icache_fsm = ICACHE_CC_CLEANUP; |
1040 | | // } |
1041 | | } |
1042 | | break; |
1043 | | } |
1044 | | ///////////////////// |
1045 | | case ICACHE_UNC_WAIT: |
1046 | | { |
1047 | | m_cost_ins_miss_frz++; |
1048 | | if ( r_tgt_icache_req ) { // external request |
1049 | | r_icache_fsm = ICACHE_CC_CHECK; |
1050 | | r_icache_fsm_save = r_icache_fsm.read(); |
1051 | | break; |
1052 | | } |
1053 | | |
1054 | | bool ok = CACHE_MISS_BUF_RSP_VAL(i,0); |
1055 | | |
1056 | | if (ok) |
1057 | | { |
1058 | | if ( r_vci_rsp_ins_error ) { |
1059 | | r_icache_fsm = ICACHE_ERROR; |
1060 | | } else { |
1061 | | r_icache_fsm = ICACHE_IDLE; |
1062 | | r_icache_buf_unc_valid = true; |
1063 | | } |
1064 | | } |
1065 | | break; |
1066 | | } |
1067 | | ////////////////// |
1068 | | case ICACHE_ERROR: |
1069 | | { |
1070 | | if ( (addr_40)ireq.addr == (addr_40)r_icache_addr_save ) { |
1071 | | irsp.error = true; |
1072 | | irsp.valid = true; |
1073 | | } |
1074 | | r_icache_fsm = ICACHE_IDLE; |
1075 | | r_vci_rsp_ins_error = false; |
1076 | | break; |
1077 | | } |
1078 | | ////////////////////// |
1079 | | case ICACHE_MISS_UPDT: |
1080 | | { |
1081 | | size_t word = r_icache_update_addr.read(); |
1082 | | vci_addr_t addr = (vci_addr_t) r_icache_addr_save.read(); |
1083 | | size_t way = 0; |
1084 | | size_t set = 0; |
1085 | | |
1086 | | // need invalid rsp, don't select a victim |
1087 | | if (not r_icache_inval_rsp ) |
1088 | | { |
1089 | | #if CC_XCACHE_WRAPPER_SELECT_VICTIM |
1090 | | way = r_icache_miss_way.read(); |
1091 | | set = r_icache_miss_set.read(); |
1092 | | #else |
1093 | | |
1094 | | // First word : select an victim ! |
1095 | | if (word == 0) |
1096 | | { |
1097 | | vci_addr_t victim; |
1098 | | |
1099 | | // r_icache_cleanup_req is false because is the transition condition to go in ICACHE_MISS_UPDT state |
1100 | | r_icache_cleanup_req = r_icache.victim_select(addr, &victim, &way, &set ); |
1101 | | r_icache.victim_update_tag(addr, way, set); |
1102 | | |
1103 | | r_icache_cleanup_line = (addr_40) victim; |
1104 | | r_icache_miss_way = way; |
1105 | | r_icache_miss_set = set; |
1106 | | } |
1107 | | else |
1108 | | { |
1109 | | way = r_icache_miss_way.read(); |
1110 | | set = r_icache_miss_set.read(); |
1111 | | } |
1112 | | #endif |
1113 | | } |
1114 | | bool val = CACHE_MISS_BUF_RSP_VAL(i,word); |
1115 | | |
1116 | | if (val) |
1117 | | { |
1118 | | PRINTF(" * <ICACHE> rsp_val : %d/%d\n",(int)r_icache_update_addr,m_icache_words); |
1119 | | PRINTF(" * <ICACHE> r_icache_inval_rsp : %d\n",(int)r_icache_inval_rsp); |
1120 | | PRINTF(" * <ICACHE> ins : %x\n",(int)CACHE_MISS_BUF_RSP_DATA(i,word)); |
1121 | | |
1122 | | // m_cpt_icache_dir_write++; |
1123 | | // m_cpt_icache_data_write++; |
1124 | | // if ( ireq.valid ) m_cost_ins_miss_frz++; |
1125 | | |
1126 | | // if need invalid rsp, don't modify the cache, but pop the buf_rsp |
1127 | | if (not r_icache_inval_rsp ) |
1128 | | r_icache.write(way, set, word, CACHE_MISS_BUF_RSP_DATA(i,word)); |
1129 | | CACHE_MISS_BUF_RSP_POP(i); |
1130 | | |
1131 | | r_icache_update_addr = ++word; |
1132 | | |
1133 | | // if last word, finish the update |
1134 | | if (word >= m_icache_words) |
1135 | | { |
1136 | | // Last word : if previous invalid_rsp, can cleanup, else update the TAG |
1137 | | if (r_icache_inval_rsp) |
1138 | | { |
1139 | | r_icache_inval_rsp = false; |
1140 | | r_icache_fsm = ICACHE_CC_CLEANUP; |
1141 | | } |
1142 | | else |
1143 | | { |
1144 | | #if CC_XCACHE_WRAPPER_SELECT_VICTIM |
1145 | | r_icache.victim_update_tag(addr, way, set); |
1146 | | #endif |
1147 | | r_icache_fsm = ICACHE_IDLE; |
1148 | | } |
1149 | | } |
1150 | | } |
1151 | | |
1152 | | break; |
1153 | | } |
1154 | | //////////////////// |
1155 | | case ICACHE_CC_CLEANUP: |
1156 | | { |
1157 | | // external cache invalidate request |
1158 | | if ( r_tgt_icache_req ) |
1159 | | { |
1160 | | r_icache_fsm = ICACHE_CC_CHECK; |
1161 | | r_icache_fsm_save = r_icache_fsm.read(); |
1162 | | break; |
1163 | | } |
1164 | | // cleanup |
1165 | | if(not r_icache_cleanup_req){ |
1166 | | r_icache_cleanup_req = true; |
1167 | | r_icache_cleanup_line = r_icache_addr_save.read() >> m_icache_words_shift; |
1168 | | r_icache_fsm = ICACHE_IDLE; |
1169 | | } |
1170 | | break; |
1171 | | } |
1172 | | ///////////////////// |
1173 | | case ICACHE_CC_CHECK: // read directory in case of invalidate or update request |
1174 | | { |
1175 | | |
1176 | | m_cpt_icache_dir_read += m_icache_ways; |
1177 | | m_cpt_icache_data_read += m_icache_ways; |
1178 | | addr_40 ad = r_tgt_addr; |
1179 | | data_t icache_rdata = 0; |
1180 | | |
1181 | | if((r_icache_fsm_save == ICACHE_MISS_WAIT) and |
1182 | | ( (r_icache_addr_save.read() & ~((m_icache_words<<2)-1)) == (ad & ~((m_icache_words<<2)-1)))) { |
1183 | | r_icache_inval_rsp = true; |
1184 | | r_tgt_icache_req = false; |
1185 | | if(r_tgt_update){ // Also send a cleanup and answer |
1186 | | r_tgt_icache_rsp = true; |
1187 | | } else { // Also send a cleanup but don't answer |
1188 | | r_tgt_icache_rsp = false; |
1189 | | } |
1190 | | r_icache_fsm = r_icache_fsm_save; |
1191 | | } else { |
1192 | | bool icache_hit = r_icache.read(ad, &icache_rdata); |
1193 | | if ( icache_hit and r_tgt_update ) |
1194 | | { |
1195 | | #if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE |
1196 | | uint32_t word = r_cache_word; |
1197 | | data_t mask = vci_param::be2mask(r_tgt_be[word]); |
1198 | | data_t rdata = 0; |
1199 | | |
1200 | | r_icache.read(ad+word*4,&rdata); |
1201 | | r_tgt_buf[word] = (mask & r_tgt_buf[word]) | (~mask & rdata); |
1202 | | |
1203 | | word ++; |
1204 | | #if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT |
1205 | | for (; word<m_icache_words; ++word) |
1206 | | if (r_tgt_be[word] != 0) |
1207 | | break; |
1208 | | #endif |
1209 | | |
1210 | | if (word==m_icache_words) |
1211 | | { |
1212 | | r_icache_fsm = ICACHE_CC_UPDT; |
1213 | | |
1214 | | #if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT |
1215 | | for (word=0; word<m_icache_words; ++word) |
1216 | | if (r_tgt_be[word] != 0) |
1217 | | break; |
1218 | | #else |
1219 | | word = 0; |
1220 | | #endif |
1221 | | } |
1222 | | r_cache_word = word; |
1223 | | #else //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE |
1224 | | r_icache_fsm = ICACHE_CC_UPDT; |
1225 | | // complete the line buffer in case of update |
1226 | | for(size_t i=0; i<m_icache_words; i++){ |
1227 | | data_t rdata = 0; |
1228 | | r_icache.read(ad + i*4,&rdata); |
1229 | | data_t mask = vci_param::be2mask(r_tgt_be[i]); |
1230 | | r_tgt_buf[i] = (mask & r_tgt_buf[i]) | (~mask & rdata); |
1231 | | } |
1232 | | #endif //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE |
1233 | | } else if ( icache_hit and not r_tgt_update ) { |
1234 | | r_icache_fsm = ICACHE_CC_INVAL; |
1235 | | } else { // instruction not found (can happen) |
1236 | | r_tgt_icache_req = false; |
1237 | | if(r_tgt_update){ |
1238 | | r_tgt_icache_rsp = true; |
1239 | | } else { |
1240 | | r_tgt_icache_rsp = false; |
1241 | | } |
1242 | | r_icache_fsm = r_icache_fsm_save; |
1243 | | } |
1244 | | } |
1245 | | break; |
1246 | | } |
1247 | | ///////////////////// |
1248 | | case ICACHE_CC_INVAL: |
1249 | | { |
1250 | | addr_40 ad = r_tgt_addr; |
1251 | | if ( ireq.valid ) m_cost_ins_miss_frz++; |
1252 | | m_cpt_icache_dir_read += m_icache_ways; |
1253 | | r_tgt_icache_rsp = true; |
1254 | | r_icache.inval(ad); |
1255 | | r_tgt_icache_req = false; |
1256 | | r_icache_fsm = r_icache_fsm_save; |
1257 | | break; |
1258 | | } |
1259 | | ///////////////////// |
1260 | | case ICACHE_CC_UPDT: |
1261 | | { |
1262 | | addr_40 ad = r_tgt_addr.read(); |
1263 | | m_cpt_icache_dir_write++; |
1264 | | m_cpt_icache_data_write++; |
1265 | | |
1266 | | #if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE |
1267 | | uint32_t word = r_cache_word; |
1268 | | |
1269 | | if(r_tgt_be[word]) |
1270 | | r_icache.write(ad+word*4, r_tgt_buf[word]); |
1271 | | |
1272 | | word ++; |
1273 | | #if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT |
1274 | | for (; word<m_icache_words; ++word) |
1275 | | if (r_tgt_be[word] != 0) |
1276 | | break; |
1277 | | #endif |
1278 | | |
1279 | | if (word==m_icache_words) |
1280 | | { |
1281 | | r_tgt_icache_req = false; |
1282 | | r_tgt_icache_rsp = true; |
1283 | | r_icache_fsm = r_icache_fsm_save.read(); |
1284 | | word = 0; |
1285 | | } |
1286 | | r_cache_word = word; |
1287 | | #else //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE |
1288 | | data_t* buf = r_tgt_buf; |
1289 | | for(size_t i=0; i<m_icache_words;i++){ |
1290 | | if(r_tgt_be[i]) r_icache.write( ad + i*4, buf[i]); |
1291 | | } |
1292 | | r_tgt_icache_req = false; |
1293 | | r_tgt_icache_rsp = true; |
1294 | | r_icache_fsm = r_icache_fsm_save.read(); |
1295 | | #endif //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE |
1296 | | |
1297 | | break; |
1298 | | } |
1299 | | |
1300 | | } // end switch r_icache_fsm |
1301 | | |
1302 | | #if CC_XCACHE_WRAPPER_DEBUG |
1303 | | if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN) |
1304 | | std::cout << " * Instruction Response : " << irsp << std::endl; |
1305 | | #endif |
1306 | | |
1307 | | //////////////////////////////////////////////////////////////////////:///////////// |
1308 | | // The DCACHE FSM controls the following ressources: |
1309 | | // - r_dcache_fsm |
1310 | | // - r_dcache_fsm_save |
1311 | | // - r_dcache (data cache access) |
1312 | | // - r_dcache_addr_save |
1313 | | // - r_dcache_wdata_save |
1314 | | // - r_dcache_rdata_save |
1315 | | // - r_dcache_type_save |
1316 | | // - r_dcache_be_save |
1317 | | // - r_dcache_cached_save |
1318 | | // - r_dcache_miss_req set |
1319 | | // - r_dcache_unc_req set |
1320 | | // - r_dcache_cleanup_req set |
1321 | | // - r_vci_rsp_data_error reset |
1322 | | // - r_tgt_dcache_req reset |
1323 | | // - r_wbuf write |
1324 | | // - dreq & drsp structures for communication with the processor |
1325 | | // |
1326 | | // 1/ EXTERNAL REQUEST : |
1327 | | // There is an external request when the tgt_dcache req flip-flop is set, |
1328 | | // requesting a line invalidation or a line update. |
1329 | | // External requests are taken into account in the states IDLE, WRITE_REQ, |
1330 | | // UNC_WAIT, MISS_WAIT, and have the highest priority : |
1331 | | // The actions associated to the pre-empted state are not executed, the DCACHE FSM |
1332 | | // goes to the CC_CHECK state to execute the requested action, and returns to the |
1333 | | // pre-empted state. |
1334 | | // 2/ PROCESSOR REQUEST : |
1335 | | // In order to support VCI write burst, the processor requests are taken into account |
1336 | | // in the WRITE_REQ state as well as in the IDLE state. |
1337 | | // - In the IDLE state, the processor request cannot be satisfied if |
1338 | | // there is a cached read miss, or an uncached read. |
1339 | | // - In the WRITE_REQ state, the request cannot be satisfied if |
1340 | | // there is a cached read miss, or an uncached read, |
1341 | | // or when the write buffer is full. |
1342 | | // - In all other states, the processor request is not satisfied. |
1343 | | // |
1344 | | // The cache access takes into account the cacheability_table. |
1345 | | // In case of processor request, there is five conditions to exit the IDLE state: |
1346 | | // - CACHED READ MISS => to the MISS_WAIT state (waiting the r_miss_ok signal), |
1347 | | // then to the MISS_UPDT state, and finally to the IDLE state. |
1348 | | // - UNCACHED READ => to the UNC_WAIT state (waiting the r_miss_ok signal), |
1349 | | // and to the IDLE state. |
1350 | | // - CACHE INVALIDATE HIT => to the INVAL state for one cycle, then to IDLE state. |
1351 | | // - WRITE MISS => directly to the WRITE_REQ state to access the write buffer. |
1352 | | // - WRITE HIT => to the WRITE_UPDT state, then to the WRITE_REQ state. |
1353 | | // |
1354 | | // Error handling : Read Bus Errors are synchronous events, but |
1355 | | // Write Bus Errors are asynchronous events (processor is not frozen). |
1356 | | // - If a Read Bus Error is detected, the VCI_RSP FSM sets the |
1357 | | // r_vci_rsp_data_error flip-flop, and the synchronous error is signaled |
1358 | | // by the DCACHE FSM. |
1359 | | // - If a Write Bus Error is detected, the VCI_RSP FSM signals |
1360 | | // the asynchronous error using the setWriteBerr() method. |
1361 | | /////////////////////////////////////////////////////////////////////////////////// |
1362 | | |
1363 | | #if CC_XCACHE_WRAPPER_DEBUG |
1364 | | if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN) |
1365 | | std::cout << " * Data Request : " << dreq << std::endl; |
1366 | | #endif |
1367 | | |
1368 | | switch ( r_dcache_fsm ) { |
1369 | | |
1370 | | ///////////////// |
1371 | | case DCACHE_IDLE: |
1372 | | { |
1373 | | if ( r_tgt_dcache_req ) { // external request |
1374 | | r_dcache_fsm = DCACHE_CC_CHECK; |
1375 | | r_dcache_fsm_save = r_dcache_fsm; |
1376 | | break; |
1377 | | } |
1378 | | |
1379 | | if ( dreq.valid ) { |
1380 | | PRINTF(" * <DCACHE> Have dreq\n"); |
1381 | | |
1382 | | data_t dcache_rdata = 0; |
1383 | | // dcache_cached and dcache_hit don't used with dreq.type == {DATA_SC, XTN_READ, XTN_WRITE} |
1384 | | bool dcache_cached = m_cacheability_table[(vci_addr_t)dreq.addr]; |
1385 | | bool dcache_hit = r_dcache.read((vci_addr_t) dreq.addr, &dcache_rdata); |
1386 | | bool dcache_cleanup_hit = r_dcache_cleanup_req and (((addr_40)dreq.addr >> (addr_40)m_dcache_words_shift) == r_dcache_cleanup_line.read()); |
1387 | | |
1388 | | PRINTF(" * <DCACHE> hit %d - cached %d - cleanup_hit %d\n",dcache_hit, dcache_cached, dcache_cleanup_hit); |
1389 | | |
1390 | | m_cpt_dcache_data_read += m_dcache_ways; |
1391 | | m_cpt_dcache_dir_read += m_dcache_ways; |
1392 | | |
1393 | | switch( dreq.type ) { |
1394 | | case iss_t::DATA_READ: |
1395 | | case iss_t::DATA_LL: |
1396 | | { |
1397 | | m_cpt_data_read++; // new dcache read |
1398 | | |
1399 | | if (dcache_hit) // no special test for uncached read, because it's always miss |
1400 | | { |
1401 | | // address is in the cache : return the word |
1402 | | r_dcache_fsm = DCACHE_IDLE; |
1403 | | drsp.valid = true; |
1404 | | drsp.rdata = dcache_rdata; // return read data (cf dcache_hit) |
1405 | | |
1406 | | // if the request is a Load Linked instruction, save request information |
1407 | | if(dreq.type == iss_t::DATA_LL) |
1408 | | { |
1409 | | PRINTF(" * <DCACHE> ll_valid = true\n"); |
1410 | | |
1411 | | r_dcache_ll_valid = true; |
1412 | | r_dcache_ll_data = dcache_rdata; |
1413 | | r_dcache_ll_addr = (vci_addr_t) dreq.addr; |
1414 | | #ifdef COHERENCE_DEBUG |
1415 | | std::cout << "Value returned for LL at address : " << std::hex << dreq.addr << " data : " << std::dec << dcache_rdata<< std::endl; |
1416 | | r_dcache.read((vci_addr_t) dreq.addr, &dcache_rdata); |
1417 | | std::cout << "Value stored at this address : " << std::hex << dreq.addr << " data : " << std::dec << dcache_rdata<< std::endl; |
1418 | | #endif |
1419 | | } |
1420 | | } |
1421 | | else |
1422 | | { |
1423 | | if (not dcache_cleanup_hit) |
1424 | | { |
1425 | | CACHE_MISS_BUF_REQ_INIT(d); |
1426 | | |
1427 | | // Miss : send signal at the CMD_FSM (via r_dcache_miss_req or r_dcache_unc_req) |
1428 | | if ( dcache_cached ) { |
1429 | | m_cpt_data_read_miss++; |
1430 | | m_cost_data_miss_frz++; |
1431 | | r_dcache_miss_req = true; |
1432 | | #if CC_XCACHE_WRAPPER_SELECT_VICTIM |
1433 | | r_dcache_fsm = DCACHE_MISS_VICTIM; |
1434 | | #else |
1435 | | r_dcache_fsm = DCACHE_MISS_WAIT; |
1436 | | #endif |
1437 | | |
1438 | | } else { |
1439 | | if (not r_dcache_previous_unc.read()) // strongly order to the uncached access |
1440 | | { |
1441 | | r_dcache_previous_unc = true; |
1442 | | |
1443 | | m_cpt_data_read_uncached++; |
1444 | | m_cost_unc_read_frz++; |
1445 | | r_dcache_unc_req = true; |
1446 | | r_dcache_fsm = DCACHE_UNC_WAIT; |
1447 | | } |
1448 | | } |
1449 | | } |
1450 | | } |
1451 | | } |
1452 | | break; |
1453 | | case iss_t::DATA_SC: |
1454 | | { |
1455 | | PRINTF(" * <DCACHE> DATA_SC - ll_valid = %d\n",r_dcache_ll_valid.read()); |
1456 | | |
1457 | | if (not r_dcache_previous_unc.read() and not dcache_cleanup_hit) // strongly order to the uncached access |
1458 | | { |
1459 | | //m_cpt_data_read_unc++; // instruction must read the memory in uncached mode |
1460 | | m_cost_unc_read_frz++; |
1461 | | |
1462 | | // if previous load linked (with the same address), make a transaction |
1463 | | // else, keep in IDLE state and return 1 (no OK) |
1464 | | if(r_dcache_ll_valid.read() and (r_dcache_ll_addr.read() == (vci_addr_t)dreq.addr)){ |
1465 | | PRINTF(" * <DCACHE> have previous load linked\n"); |
1466 | | |
1467 | | r_dcache_previous_unc = true; |
1468 | | |
1469 | | r_dcache_sc_req = true; |
1470 | | |
1471 | | CACHE_MISS_BUF_REQ_INIT(d); |
1472 | | |
1473 | | r_dcache_fsm = DCACHE_SC_WAIT; |
1474 | | } else { |
1475 | | PRINTF(" * <DCACHE> don't have previous load linked\n"); |
1476 | | |
1477 | | drsp.valid = true; |
1478 | | drsp.rdata = 1; // SC rsp NOK |
1479 | | r_dcache_ll_valid = false; |
1480 | | } |
1481 | | } |
1482 | | |
1483 | | break; |
1484 | | } |
1485 | | case iss_t::XTN_READ: |
1486 | | case iss_t::XTN_WRITE: |
1487 | | { |
1488 | | bool drsp_valid = false; |
1489 | | // only DCACHE INVALIDATE and SYNC request are supported |
1490 | | switch (dreq.addr>>2) |
1491 | | { |
1492 | | case iss_t::XTN_DCACHE_INVAL : |
1493 | | { |
1494 | | drsp_valid = true; |
1495 | | r_dcache_fsm = DCACHE_INVAL; |
1496 | | break; |
1497 | | } |
1498 | | case iss_t::XTN_SYNC : |
1499 | | { |
1500 | | // Test if write buffer is already empty |
1501 | | // * gain : 1 cycle |
1502 | | // * cost : can be on the critical path |
1503 | | if (r_wbuf.empty()) |
1504 | | { |
1505 | | drsp_valid = true; |
1506 | | r_dcache_fsm = DCACHE_IDLE; |
1507 | | } |
1508 | | else |
1509 | | { |
1510 | | drsp_valid = false; |
1511 | | r_dcache_fsm = DCACHE_SYNC; |
1512 | | } |
1513 | | break; |
1514 | | } |
1515 | | default : |
1516 | | { |
1517 | | // std::cout << "Warning in VCI_CC_XCACHE_WRAPPER " << name() << std::endl; |
1518 | | // std::cout << "Unsupported external access : " << (dreq.addr>>2) << std::endl; |
1519 | | |
1520 | | r_dcache_fsm = DCACHE_IDLE; |
1521 | | } |
1522 | | }//end switch (dreq.addr>>2) |
1523 | | |
1524 | | drsp.valid = drsp_valid; |
1525 | | drsp.rdata = 0; |
1526 | | break; |
1527 | | } |
1528 | | case iss_t::DATA_WRITE: |
1529 | | |
1530 | | if (dcache_cached or not r_dcache_previous_unc.read()) // strongly order to the uncached access |
1531 | | { |
1532 | | bool drsp_valid; |
1533 | | |
1534 | | drsp_valid = r_wbuf.write((addr_40) dreq.addr, dreq.be, dreq.wdata, dcache_cached); |
1535 | | |
1536 | | if (drsp_valid) |
1537 | | { |
1538 | | m_cpt_data_write++; |
1539 | | |
1540 | | if (not dcache_cached) |
1541 | | { |
1542 | | r_dcache_previous_unc = true; |
1543 | | m_cpt_data_write_uncached++; |
1544 | | } |
1545 | | else if (not dcache_hit) |
1546 | | m_cpt_data_write_miss++; |
1547 | | |
1548 | | if ( dcache_hit) { |
1549 | | r_dcache_fsm = DCACHE_WRITE_UPDT; |
1550 | | } else { |
1551 | | r_dcache_fsm = DCACHE_IDLE; |
1552 | | } |
1553 | | } |
1554 | | |
1555 | | drsp.valid = drsp_valid; |
1556 | | drsp.rdata = 0; |
1557 | | } |
1558 | | break; |
1559 | | } // end switch dreq.type |
1560 | | |
1561 | | r_dcache_addr_save = (addr_40) dreq.addr; |
1562 | | r_dcache_type_save = dreq.type; |
1563 | | r_dcache_wdata_save = dreq.wdata; |
1564 | | r_dcache_be_save = dreq.be; |
1565 | | r_dcache_rdata_save = dcache_rdata; |
1566 | | r_dcache_cached_save = dcache_cached; |
1567 | | |
1568 | | } else { // end if dreq.valid |
1569 | | r_dcache_fsm = DCACHE_IDLE; |
1570 | | } |
1571 | | |
1572 | | break; |
1573 | | } |
1574 | | /////////////////////// |
1575 | | case DCACHE_WRITE_UPDT: |
1576 | | { |
1577 | | m_cpt_dcache_data_write++; |
1578 | | data_t mask = vci_param::be2mask(r_dcache_be_save); |
1579 | | data_t wdata = (mask & r_dcache_wdata_save) | (~mask & r_dcache_rdata_save); |
1580 | | vci_addr_t ad = r_dcache_addr_save.read(); |
1581 | | r_dcache.write(ad, wdata); |
1582 | | |
1583 | | r_dcache_fsm = DCACHE_IDLE; |
1584 | | |
1585 | | break; |
1586 | | } |
1587 | | ////////////////////// |
1588 | | #if CC_XCACHE_WRAPPER_SELECT_VICTIM |
1589 | | case DCACHE_MISS_VICTIM: |
1590 | | { |
1591 | | if (not r_dcache_cleanup_req.read()) |
1592 | | { |
1593 | | size_t way; |
1594 | | size_t set; |
1595 | | vci_addr_t addr = (vci_addr_t) r_dcache_addr_save.read(); |
1596 | | vci_addr_t victim; |
1597 | | |
1598 | | r_dcache_cleanup_req = r_dcache.victim_select(addr, &victim, &way, &set ); |
1599 | | r_dcache_cleanup_line = (addr_40) victim; |
1600 | | r_dcache_miss_way = way; |
1601 | | r_dcache_miss_set = set; |
1602 | | |
1603 | | r_dcache_fsm = DCACHE_MISS_WAIT; |
1604 | | } |
1605 | | |
1606 | | break; |
1607 | | } |
1608 | | #endif |
1609 | | ////////////////////// |
1610 | | case DCACHE_MISS_WAIT: |
1611 | | { |
1612 | | |
1613 | | if ( dreq.valid ) m_cost_data_miss_frz++; |
1614 | | if ( r_tgt_dcache_req.read() ) { // external request |
1615 | | r_dcache_fsm = DCACHE_CC_CHECK; |
1616 | | r_dcache_fsm_save = r_dcache_fsm; |
1617 | | break; |
1618 | | } |
1619 | | |
1620 | | bool val = CACHE_MISS_BUF_RSP_VAL(d,0); |
1621 | | if (val) |
1622 | | { |
1623 | | // if (not r_dcache_inval_rsp ) |
1624 | | // { |
1625 | | |
1626 | | // Miss read response and no invalidation |
1627 | | if ( r_vci_rsp_data_error ) |
1628 | | { |
1629 | | r_dcache_fsm = DCACHE_ERROR; |
1630 | | } |
1631 | | else |
1632 | | { |
1633 | | #if not CC_XCACHE_WRAPPER_SELECT_VICTIM |
1634 | | if (not r_dcache_cleanup_req.read()) |
1635 | | #endif |
1636 | | { |
1637 | | r_dcache_update_addr = 0; |
1638 | | r_dcache_fsm = DCACHE_MISS_UPDT; |
1639 | | } |
1640 | | } |
1641 | | // } |
1642 | | // else |
1643 | | // { |
1644 | | // r_dcache_inval_rsp = false; |
1645 | | |
1646 | | // // Miss read response and invalidation |
1647 | | // if ( r_vci_rsp_data_error ) { |
1648 | | // r_dcache_fsm = DCACHE_ERROR; |
1649 | | // } else { |
1650 | | // r_dcache_fsm = DCACHE_CC_CLEANUP; |
1651 | | // } |
1652 | | // } |
1653 | | } |
1654 | | break; |
1655 | | } |
1656 | | ////////////////////// |
1657 | | case DCACHE_MISS_UPDT: |
1658 | | { |
1659 | | size_t word = r_dcache_update_addr.read(); |
1660 | | vci_addr_t addr = (vci_addr_t) r_dcache_addr_sav |