399 | | // XMIN(5 bits) / XMAX(5 bits) / YMIN(5 bits) / YMAX(5 bits) |
400 | | // 0b00000 / 0b11111 / 0b00000 / 0b11111 |
401 | | m_broadcast_boundaries(0x7C1F), |
402 | | |
403 | | |
404 | | // FIFOs |
405 | | m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4), |
406 | | m_cmd_read_length_fifo("m_cmd_read_length_fifo", 4), |
407 | | m_cmd_read_srcid_fifo("m_cmd_read_srcid_fifo", 4), |
408 | | m_cmd_read_trdid_fifo("m_cmd_read_trdid_fifo", 4), |
409 | | m_cmd_read_pktid_fifo("m_cmd_read_pktid_fifo", 4), |
410 | | |
411 | | m_cmd_write_addr_fifo("m_cmd_write_addr_fifo",8), |
412 | | m_cmd_write_eop_fifo("m_cmd_write_eop_fifo",8), |
413 | | m_cmd_write_srcid_fifo("m_cmd_write_srcid_fifo",8), |
414 | | m_cmd_write_trdid_fifo("m_cmd_write_trdid_fifo",8), |
415 | | m_cmd_write_pktid_fifo("m_cmd_write_pktid_fifo",8), |
416 | | m_cmd_write_data_fifo("m_cmd_write_data_fifo",8), |
417 | | m_cmd_write_be_fifo("m_cmd_write_be_fifo",8), |
418 | | |
419 | | m_cmd_cas_addr_fifo("m_cmd_cas_addr_fifo",4), |
420 | | m_cmd_cas_eop_fifo("m_cmd_cas_eop_fifo",4), |
421 | | m_cmd_cas_srcid_fifo("m_cmd_cas_srcid_fifo",4), |
422 | | m_cmd_cas_trdid_fifo("m_cmd_cas_trdid_fifo",4), |
423 | | m_cmd_cas_pktid_fifo("m_cmd_cas_pktid_fifo",4), |
424 | | m_cmd_cas_wdata_fifo("m_cmd_cas_wdata_fifo",4), |
425 | | |
426 | | m_cc_receive_to_cleanup_fifo("m_cc_receive_to_cleanup_fifo", 4), |
427 | | m_cc_receive_to_multi_ack_fifo("m_cc_receive_to_multi_ack_fifo", 4), |
428 | | |
429 | | r_tgt_cmd_fsm("r_tgt_cmd_fsm"), |
430 | | |
431 | | r_config_fsm( "r_config_fsm" ), |
432 | | |
433 | | m_config_to_cc_send_inst_fifo( "m_config_to_cc_send_inst_fifo", 8 ), |
434 | | m_config_to_cc_send_srcid_fifo( "m_config_to_cc_send_srcid_fifo", 8 ), |
435 | | |
436 | | r_read_fsm( "r_read_fsm" ), |
437 | | |
438 | | r_write_fsm( "r_write_fsm" ), |
439 | | |
440 | | m_write_to_cc_send_inst_fifo("m_write_to_cc_send_inst_fifo",8), |
441 | | m_write_to_cc_send_srcid_fifo("m_write_to_cc_send_srcid_fifo",8), |
442 | | |
443 | | r_multi_ack_fsm("r_multi_ack_fsm"), |
444 | | |
445 | | r_cleanup_fsm("r_cleanup_fsm"), |
446 | | |
447 | | r_cas_fsm("r_cas_fsm"), |
448 | | |
449 | | m_cas_to_cc_send_inst_fifo("m_cas_to_cc_send_inst_fifo",8), |
450 | | m_cas_to_cc_send_srcid_fifo("m_cas_to_cc_send_srcid_fifo",8), |
451 | | |
452 | | r_ixr_rsp_fsm("r_ixr_rsp_fsm"), |
453 | | r_xram_rsp_fsm("r_xram_rsp_fsm"), |
454 | | |
455 | | m_xram_rsp_to_cc_send_inst_fifo("m_xram_rsp_to_cc_send_inst_fifo",8), |
456 | | m_xram_rsp_to_cc_send_srcid_fifo("m_xram_rsp_to_cc_send_srcid_fifo",8), |
457 | | |
458 | | r_ixr_cmd_fsm("r_ixr_cmd_fsm"), |
459 | | |
460 | | r_tgt_rsp_fsm("r_tgt_rsp_fsm"), |
461 | | |
462 | | r_cc_send_fsm("r_cc_send_fsm"), |
463 | | r_cc_receive_fsm("r_cc_receive_fsm"), |
464 | | |
465 | | r_alloc_dir_fsm("r_alloc_dir_fsm"), |
466 | | r_alloc_dir_reset_cpt("r_alloc_dir_reset_cpt"), |
467 | | r_alloc_trt_fsm("r_alloc_trt_fsm"), |
468 | | r_alloc_upt_fsm("r_alloc_upt_fsm"), |
469 | | r_alloc_ivt_fsm("r_alloc_ivt_fsm"), |
470 | | r_alloc_heap_fsm("r_alloc_heap_fsm"), |
471 | | r_alloc_heap_reset_cpt("r_alloc_heap_reset_cpt") |
472 | | { |
473 | | std::cout << " - Building VciMemCache : " << name << std::endl; |
474 | | |
475 | | assert(IS_POW_OF_2(nsets)); |
476 | | assert(IS_POW_OF_2(nwords)); |
477 | | assert(IS_POW_OF_2(nways)); |
478 | | assert(nsets); |
479 | | assert(nwords); |
480 | | assert(nways); |
481 | | |
482 | | // check Transaction table size |
483 | | assert((uint32_log2(trt_lines) <= vci_param_ext::T) and |
484 | | "MEMC ERROR : Need more bits for VCI TRDID field"); |
485 | | |
486 | | // check internal and external data width |
487 | | assert( (vci_param_int::B == 4 ) and |
488 | | "MEMC ERROR : VCI internal data width must be 32 bits"); |
489 | | |
490 | | assert( (vci_param_ext::B == 8) and |
491 | | "MEMC ERROR : VCI external data width must be 64 bits"); |
492 | | |
493 | | // Check coherence between internal & external addresses |
494 | | assert( (vci_param_int::N == vci_param_ext::N) and |
495 | | "MEMC ERROR : VCI internal & external addresses must have the same width"); |
496 | | |
497 | | // Get the segments associated to the MemCache |
498 | | std::list<soclib::common::Segment>::iterator seg; |
499 | | size_t i = 0; |
500 | | |
501 | | for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++) |
| 399 | // XMIN(5 bits) / XMAX(5 bits) / YMIN(5 bits) / YMAX(5 bits) |
| 400 | // 0b00000 / 0b11111 / 0b00000 / 0b11111 |
| 401 | m_broadcast_boundaries(0x7C1F), |
| 402 | |
| 403 | |
| 404 | // FIFOs |
| 405 | m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4), |
| 406 | m_cmd_read_length_fifo("m_cmd_read_length_fifo", 4), |
| 407 | m_cmd_read_srcid_fifo("m_cmd_read_srcid_fifo", 4), |
| 408 | m_cmd_read_trdid_fifo("m_cmd_read_trdid_fifo", 4), |
| 409 | m_cmd_read_pktid_fifo("m_cmd_read_pktid_fifo", 4), |
| 410 | |
| 411 | m_cmd_write_addr_fifo("m_cmd_write_addr_fifo",8), |
| 412 | m_cmd_write_eop_fifo("m_cmd_write_eop_fifo",8), |
| 413 | m_cmd_write_srcid_fifo("m_cmd_write_srcid_fifo",8), |
| 414 | m_cmd_write_trdid_fifo("m_cmd_write_trdid_fifo",8), |
| 415 | m_cmd_write_pktid_fifo("m_cmd_write_pktid_fifo",8), |
| 416 | m_cmd_write_data_fifo("m_cmd_write_data_fifo",8), |
| 417 | m_cmd_write_be_fifo("m_cmd_write_be_fifo",8), |
| 418 | |
| 419 | m_cmd_cas_addr_fifo("m_cmd_cas_addr_fifo",4), |
| 420 | m_cmd_cas_eop_fifo("m_cmd_cas_eop_fifo",4), |
| 421 | m_cmd_cas_srcid_fifo("m_cmd_cas_srcid_fifo",4), |
| 422 | m_cmd_cas_trdid_fifo("m_cmd_cas_trdid_fifo",4), |
| 423 | m_cmd_cas_pktid_fifo("m_cmd_cas_pktid_fifo",4), |
| 424 | m_cmd_cas_wdata_fifo("m_cmd_cas_wdata_fifo",4), |
| 425 | |
| 426 | m_cc_receive_to_cleanup_fifo("m_cc_receive_to_cleanup_fifo", 4), |
| 427 | m_cc_receive_to_multi_ack_fifo("m_cc_receive_to_multi_ack_fifo", 4), |
| 428 | |
| 429 | r_tgt_cmd_fsm("r_tgt_cmd_fsm"), |
| 430 | |
| 431 | r_config_fsm( "r_config_fsm" ), |
| 432 | |
| 433 | m_config_to_cc_send_inst_fifo( "m_config_to_cc_send_inst_fifo", 8 ), |
| 434 | m_config_to_cc_send_srcid_fifo( "m_config_to_cc_send_srcid_fifo", 8 ), |
| 435 | |
| 436 | r_read_fsm( "r_read_fsm" ), |
| 437 | |
| 438 | r_write_fsm( "r_write_fsm" ), |
| 439 | |
| 440 | m_write_to_cc_send_inst_fifo("m_write_to_cc_send_inst_fifo",8), |
| 441 | m_write_to_cc_send_srcid_fifo("m_write_to_cc_send_srcid_fifo",8), |
| 442 | |
| 443 | r_multi_ack_fsm("r_multi_ack_fsm"), |
| 444 | |
| 445 | r_cleanup_fsm("r_cleanup_fsm"), |
| 446 | |
| 447 | r_cas_fsm("r_cas_fsm"), |
| 448 | |
| 449 | m_cas_to_cc_send_inst_fifo("m_cas_to_cc_send_inst_fifo",8), |
| 450 | m_cas_to_cc_send_srcid_fifo("m_cas_to_cc_send_srcid_fifo",8), |
| 451 | |
| 452 | r_ixr_rsp_fsm("r_ixr_rsp_fsm"), |
| 453 | r_xram_rsp_fsm("r_xram_rsp_fsm"), |
| 454 | |
| 455 | m_xram_rsp_to_cc_send_inst_fifo("m_xram_rsp_to_cc_send_inst_fifo",8), |
| 456 | m_xram_rsp_to_cc_send_srcid_fifo("m_xram_rsp_to_cc_send_srcid_fifo",8), |
| 457 | |
| 458 | r_ixr_cmd_fsm("r_ixr_cmd_fsm"), |
| 459 | |
| 460 | r_tgt_rsp_fsm("r_tgt_rsp_fsm"), |
| 461 | |
| 462 | r_cc_send_fsm("r_cc_send_fsm"), |
| 463 | r_cc_receive_fsm("r_cc_receive_fsm"), |
| 464 | |
| 465 | r_alloc_dir_fsm("r_alloc_dir_fsm"), |
| 466 | r_alloc_dir_reset_cpt("r_alloc_dir_reset_cpt"), |
| 467 | r_alloc_trt_fsm("r_alloc_trt_fsm"), |
| 468 | r_alloc_upt_fsm("r_alloc_upt_fsm"), |
| 469 | r_alloc_ivt_fsm("r_alloc_ivt_fsm"), |
| 470 | r_alloc_heap_fsm("r_alloc_heap_fsm"), |
| 471 | r_alloc_heap_reset_cpt("r_alloc_heap_reset_cpt") |
| 472 | { |
| 473 | std::cout << " - Building VciMemCache : " << name << std::endl; |
| 474 | |
| 475 | assert(IS_POW_OF_2(nsets)); |
| 476 | assert(IS_POW_OF_2(nwords)); |
| 477 | assert(IS_POW_OF_2(nways)); |
| 478 | assert(nsets); |
| 479 | assert(nwords); |
| 480 | assert(nways); |
| 481 | |
| 482 | // check Transaction table size |
| 483 | assert((uint32_log2(trt_lines) <= vci_param_ext::T) and |
| 484 | "MEMC ERROR : Need more bits for VCI TRDID field"); |
| 485 | |
| 486 | // check internal and external data width |
| 487 | assert( (vci_param_int::B == 4 ) and |
| 488 | "MEMC ERROR : VCI internal data width must be 32 bits"); |
| 489 | |
| 490 | assert( (vci_param_ext::B == 8) and |
| 491 | "MEMC ERROR : VCI external data width must be 64 bits"); |
| 492 | |
| 493 | // Check coherence between internal & external addresses |
| 494 | assert( (vci_param_int::N == vci_param_ext::N) and |
| 495 | "MEMC ERROR : VCI internal & external addresses must have the same width"); |
| 496 | |
| 497 | // Get the segments associated to the MemCache |
| 498 | std::list<soclib::common::Segment>::iterator seg; |
| 499 | size_t i = 0; |
| 500 | |
| 501 | for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++) |
| 502 | { |
| 503 | std::cout << " => segment " << seg->name() |
| 504 | << " / base = " << std::hex << seg->baseAddress() |
| 505 | << " / size = " << seg->size() << std::endl; |
| 506 | m_nseg++; |
| 507 | } |
| 508 | |
| 509 | m_seg = new soclib::common::Segment*[m_nseg]; |
| 510 | |
| 511 | for(seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++) |
| 512 | { |
| 513 | if ( seg->special() ) m_seg_config = i; |
| 514 | m_seg[i] = & (*seg); |
| 515 | i++; |
| 516 | } |
| 517 | |
| 518 | // Allocation for IXR_RSP FSM |
| 519 | r_ixr_rsp_to_xram_rsp_rok = new sc_signal<bool>[m_trt_lines]; |
| 520 | //r_ixr_rsp_to_xram_rsp_no_coherent = new sc_signal<bool>[m_trt_lines]; |
| 521 | |
| 522 | // Allocation for XRAM_RSP FSM |
| 523 | r_xram_rsp_victim_data = new sc_signal<data_t>[nwords]; |
| 524 | r_xram_rsp_to_tgt_rsp_data = new sc_signal<data_t>[nwords]; |
| 525 | |
| 526 | // Allocation for READ FSM |
| 527 | r_read_data = new sc_signal<data_t>[nwords]; |
| 528 | r_read_to_tgt_rsp_data = new sc_signal<data_t>[nwords]; |
| 529 | |
| 530 | // Allocation for WRITE FSM |
| 531 | r_write_data = new sc_signal<data_t>[nwords]; |
| 532 | r_write_be = new sc_signal<be_t>[nwords]; |
| 533 | r_write_to_cc_send_data = new sc_signal<data_t>[nwords]; |
| 534 | r_write_to_cc_send_be = new sc_signal<be_t>[nwords]; |
| 535 | |
| 536 | // Allocation for CAS FSM |
| 537 | r_cas_data = new sc_signal<data_t>[nwords]; |
| 538 | r_cas_rdata = new sc_signal<data_t>[2]; |
| 539 | |
| 540 | // Allocation for ODCCP |
| 541 | r_cleanup_data = new sc_signal<data_t>[nwords]; |
| 542 | r_cleanup_to_ixr_cmd_data = new sc_signal<data_t>[nwords]; |
| 543 | |
| 544 | // Allocation for IXR_CMD FSM |
| 545 | r_ixr_cmd_wdata = new sc_signal<data_t>[nwords]; |
| 546 | |
| 547 | // Allocation for debug |
| 548 | m_debug_previous_data = new data_t[nwords]; |
| 549 | m_debug_data = new data_t[nwords]; |
| 550 | |
| 551 | SC_METHOD(transition); |
| 552 | dont_initialize(); |
| 553 | sensitive << p_clk.pos(); |
| 554 | |
| 555 | SC_METHOD(genMoore); |
| 556 | dont_initialize(); |
| 557 | sensitive << p_clk.neg(); |
| 558 | } // end constructor |
| 559 | |
| 560 | |
| 561 | ///////////////////////////////////////////////////// |
| 562 | tmpl(void) ::cache_monitor(addr_t addr) |
| 563 | ///////////////////////////////////////////////////// |
648 | | } |
649 | | |
650 | | ///////////////////////////////////////// |
651 | | tmpl(void) ::clear_stats() |
652 | | ///////////////////////////////////////// |
653 | | { |
654 | | m_cpt_cycles = 0; |
655 | | m_cpt_read = 0; |
656 | | m_cpt_read_miss = 0; |
657 | | m_cpt_write = 0; |
658 | | m_cpt_write_miss = 0; |
659 | | m_cpt_write_cells = 0; |
660 | | m_cpt_write_dirty = 0; |
661 | | m_cpt_update = 0; |
662 | | m_cpt_update_mult = 0; |
663 | | m_cpt_inval_brdcast = 0; |
664 | | m_cpt_inval = 0; |
665 | | m_cpt_inval_mult = 0; |
666 | | m_cpt_cleanup = 0; |
667 | | m_cpt_cleanup_data = 0; |
668 | | m_cpt_ll = 0; |
669 | | m_cpt_sc = 0; |
670 | | m_cpt_cas = 0; |
671 | | m_cpt_trt_full = 0; |
672 | | m_cpt_trt_rb = 0; |
673 | | m_cpt_dir_unused = 0; |
674 | | m_cpt_ivt_unused = 0; |
675 | | m_cpt_heap_unused = 0; |
676 | | m_cpt_trt_unused = 0; |
677 | | m_cpt_read_fsm_n_dir_lock = 0; |
678 | | m_cpt_read_fsm_dir_lock = 0; |
679 | | m_cpt_read_fsm_dir_used = 0; |
680 | | m_cpt_read_fsm_trt_lock = 0; |
681 | | m_cpt_read_fsm_heap_lock = 0; |
682 | | m_cpt_write_fsm_dir_lock = 0; |
683 | | m_cpt_write_fsm_n_dir_lock = 0; |
684 | | m_cpt_write_fsm_upt_lock = 0; |
685 | | m_cpt_write_fsm_heap_lock = 0; |
686 | | m_cpt_write_fsm_dir_used = 0; |
687 | | m_cpt_write_fsm_trt_lock = 0; |
688 | | m_cpt_cas_fsm_n_dir_lock = 0; |
689 | | m_cpt_cas_fsm_dir_lock = 0; |
690 | | m_cpt_cas_fsm_upt_lock = 0; |
691 | | m_cpt_cas_fsm_heap_lock = 0; |
692 | | m_cpt_cas_fsm_trt_lock = 0; |
693 | | m_cpt_cas_fsm_dir_used = 0; |
694 | | m_cpt_xram_rsp_fsm_n_dir_lock = 0; |
695 | | m_cpt_xram_rsp_fsm_dir_lock = 0; |
696 | | m_cpt_xram_rsp_fsm_trt_lock = 0; |
697 | | m_cpt_xram_rsp_fsm_upt_lock = 0; |
698 | | m_cpt_xram_rsp_fsm_heap_lock = 0; |
699 | | m_cpt_xram_rsp_fsm_dir_used = 0; |
700 | | m_cpt_cleanup_fsm_dir_lock = 0; |
701 | | m_cpt_cleanup_fsm_n_dir_lock = 0; |
702 | | m_cpt_cleanup_fsm_heap_lock = 0; |
703 | | m_cpt_cleanup_fsm_upt_lock = 0; |
704 | | m_cpt_cleanup_fsm_dir_used = 0; |
705 | | m_cpt_ixr_fsm_trt_lock = 0; |
706 | | m_cpt_multi_ack_fsm_upt_lock = 0; |
707 | | } |
708 | | ///////////////////////////////////////// |
709 | | tmpl(void) ::print_stats() |
710 | | ///////////////////////////////////////// |
711 | | { |
712 | | std::cout << "----------------------------------" << std::dec << std::endl; |
713 | | std::cout |
714 | | << "MEM_CACHE " << name() << " / Time = " << m_cpt_cycles << std::endl |
715 | | << "- READ RATE = " << (double) m_cpt_read/m_cpt_cycles << std::endl |
716 | | << "- READ TOTAL = " << m_cpt_read << std::endl |
717 | | << "- READ MISS RATE = " << (double) m_cpt_read_miss/m_cpt_read << std::endl |
718 | | << "- WRITE RATE = " << (double) m_cpt_write/m_cpt_cycles << std::endl |
719 | | << "- WRITE TOTAL = " << m_cpt_write << std::endl |
720 | | << "- WRITE MISS RATE = " << (double) m_cpt_write_miss/m_cpt_write << std::endl |
721 | | << "- WRITE BURST LENGTH = " << (double) m_cpt_write_cells/m_cpt_write << std::endl |
722 | | << "- WRITE BURST TOTAL = " << m_cpt_write_cells << std::endl |
723 | | << "- REQUESTS TRT FULL = " << m_cpt_trt_full << std::endl |
724 | | << "- READ TRT BLOKED HIT = " << m_cpt_trt_rb << std::endl |
725 | | << "- UPDATE RATE = " << (double) m_cpt_update/m_cpt_cycles << std::endl |
726 | | << "- UPDATE ARITY = " << (double) m_cpt_update_mult/m_cpt_update << std::endl |
727 | | << "- INVAL MULTICAST RATE = " << (double)(m_cpt_inval-m_cpt_inval_brdcast) /m_cpt_cycles << std::endl |
728 | | << "- INVAL MULTICAST ARITY = " << (double) m_cpt_inval_mult/ (m_cpt_inval-m_cpt_inval_brdcast) << std::endl |
729 | | << "- INVAL BROADCAST RATE = " << (double) m_cpt_inval_brdcast/m_cpt_cycles << std::endl |
730 | | << "- SAVE DIRTY RATE = " << (double) m_cpt_write_dirty/m_cpt_cycles << std::endl |
731 | | << "- CLEANUP RATE = " << (double) m_cpt_cleanup/m_cpt_cycles << std::endl |
732 | | << "- CLEANUP TOTAL = " << (double) m_cpt_cleanup << std::endl |
733 | | << "- CLEANUP WITH DATA RATE = " << (double) m_cpt_cleanup_data/m_cpt_cycles << std::endl |
734 | | << "- CLEANUP WITH DATA TOTAL = " << (double) m_cpt_cleanup_data << std::endl |
735 | | << "- LL RATE = " << (double) m_cpt_ll/m_cpt_cycles << std::endl |
736 | | << "- SC RATE = " << (double) m_cpt_sc/m_cpt_cycles << std::endl |
737 | | << "- CAS RATE = " << (double) m_cpt_cas/m_cpt_cycles << std::endl << std::endl; |
738 | | |
739 | | /* << "- WAIT DIR LOCK in READ_FSM = " << (double) m_cpt_read_fsm_dir_lock/m_cpt_read_fsm_n_dir_lock << std::endl |
740 | | << "- NB CYCLES IN DIR LOCK in READ_FSM = " << (double) m_cpt_read_fsm_dir_used/m_cpt_read_fsm_n_dir_lock << std::endl |
741 | | << "- WAIT DIR LOCK in WRITE_FSM = " << (double) m_cpt_write_fsm_dir_lock/m_cpt_write_fsm_n_dir_lock << std::endl |
742 | | << "- NB CYCLES IN DIR LOCK in WRITE_FSM = " << (double) m_cpt_write_fsm_dir_used/m_cpt_write_fsm_n_dir_lock << std::endl |
743 | | << "- WAIT DIR LOCK in XRAM_FSM = " << (double) m_cpt_xram_rsp_fsm_dir_lock/m_cpt_xram_rsp_fsm_n_dir_lock << std::endl |
744 | | << "- NB CYCLES IN DIR LOCK in XRAM_FSM = " << (double) m_cpt_xram_rsp_fsm_dir_used/m_cpt_xram_rsp_fsm_n_dir_lock << std::endl |
745 | | << "- WAIT DIR LOCK in CLEANUP_FSM = " << (double) m_cpt_cleanup_fsm_dir_lock/m_cpt_cleanup_fsm_n_dir_lock << std::endl |
746 | | << "- NB CYCLES IN DIR LOCK in CLEANUP_FSM = " << (double) m_cpt_cleanup_fsm_dir_used/m_cpt_cleanup_fsm_n_dir_lock << std::endl |
747 | | << "- WAIT DIR LOCK in CAS_FSM = " << (double) m_cpt_cas_fsm_dir_lock/m_cpt_cas_fsm_n_dir_lock << std::endl |
748 | | << "- NB CYCLES IN LOCK in CAS_FSM = " << (double) m_cpt_cas_fsm_dir_used/m_cpt_cas_fsm_n_dir_lock << std::endl |
749 | | << "- DIR UNUSED RATE = " << (double) m_cpt_dir_unused/m_cpt_cycles << std::endl << std::endl |
750 | | |
751 | | << "- WAIT TRT LOCK in READ_FSM = " << (double) m_cpt_read_fsm_trt_lock/m_cpt_read_fsm_n_trt_lock << std::endl |
752 | | << "- NB CYCLES IN TRT LOCK in READ_FSM = " << (double) m_cpt_read_fsm_trt_used/m_cpt_read_fsm_n_trt_lock << std::endl |
753 | | << "- WAIT TRT LOCK in WRITE_FSM = " << (double) m_cpt_write_fsm_trt_lock/m_cpt_write_fsm_n_trt_lock << std::endl |
754 | | << "- NB CYCLES IN TRT LOCK in WRITE_FSM = " << (double) m_cpt_write_fsm_trt_used/m_cpt_write_fsm_n_trt_lock << std::endl |
755 | | << "- WAIT TRT LOCK in CAS_FSM = " << (double) m_cpt_cas_fsm_trt_lock/m_cpt_cas_fsm_n_trt_lock << std::endl |
756 | | << "- NB CYCLES IN TRT LOCK in CAS_FSM = " << (double) m_cpt_cas_fsm_trt_used/m_cpt_cas_fsm_n_trt_lock << std::endl |
757 | | << "- WAIT TRT LOCK in XRAM_FSM = " << (double) m_cpt_xram_rsp_fsm_trt_lock/m_cpt_xram_rsp_fsm_n_trt_lock << std::endl |
758 | | << "- NB CYCLES IN TRT LOCK in XRAM_FSM = " << (double) m_cpt_xram_rsp_fsm_trt_used/m_cpt_xram_rsp_fsm_n_trt_lock << std::endl |
759 | | << "- WAIT TRT LOCK in IXR_FSM = " << (double) m_cpt_ixr_fsm_trt_lock/m_cpt_ixr_fsm_n_trt_lock << std::endl |
760 | | << "- NB CYCLES IN TRT LOCK in IXR_FSM = " << (double) m_cpt_ixr_fsm_trt_used/m_cpt_ixr_fsm_n_trt_lock << std::endl |
761 | | << "- TRT UNUSED RATE = " << (double) m_cpt_trt_unused/m_cpt_cycles << std::endl << std::endl |
762 | | |
763 | | << "- WAIT UPT LOCK in WRITE_FSM = " << (double) m_cpt_write_fsm_upt_lock/m_cpt_write_fsm_n_upt_lock << std::endl |
764 | | << "- NB CYCLES IN UPT LOCK in WRITE_FSM = " << (double) m_cpt_write_fsm_upt_used/m_cpt_write_fsm_n_upt_lock << std::endl |
765 | | << "- WAIT UPT LOCK in XRAM_FSM = " << (double) m_cpt_xram_rsp_fsm_upt_lock/m_cpt_xram_rsp_fsm_n_upt_lock << std::endl |
766 | | << "- NB CYCLES IN UPT LOCK in XRAM_FSM = " << (double) m_cpt_xram_rsp_fsm_upt_used/m_cpt_xram_rsp_fsm_n_upt_lock << std::endl |
767 | | << "- WAIT UPT LOCK in MULTIACK_FSM = " << (double) m_cpt_multi_ack_fsm_upt_lock/m_cpt_multi_ack_fsm_n_upt_lock << std::endl |
768 | | << "- NB CYCLES IN UPT LOCK in MULTIACK_FSM = " << (double) m_cpt_multi_ack_fsm_upt_used/m_cpt_multi_ack_fsm_n_upt_lock << std::endl |
769 | | << "- WAIT UPT LOCK in CLEANUP_FSM = " << (double) m_cpt_cleanup_fsm_upt_lock/m_cpt_cleanup_fsm_n_upt_lock << std::endl |
770 | | << "- NB CYCLES IN UPT LOCK in CLEANUP_FSM = " << (double) m_cpt_cleanup_fsm_upt_used/m_cpt_cleanup_fsm_n_upt_lock << std::endl |
771 | | << "- WAIT UPT LOCK in CAS_FSM = " << (double) m_cpt_cas_fsm_upt_lock/m_cpt_cas_fsm_n_upt_lock << std::endl |
772 | | << "- NB CYCLES IN UPT LOCK in CAS_FSM = " << (double) m_cpt_cas_fsm_upt_used/m_cpt_cas_fsm_n_upt_lock << std::endl |
773 | | << "- IVT UNUSED RATE = " << (double) m_cpt_ivt_unused/m_cpt_cycles << std::endl << std::endl |
774 | | |
775 | | << "- WAIT HEAP LOCK in READ_FSM = " << (double) m_cpt_read_fsm_heap_lock/m_cpt_read_fsm_n_heap_lock << std::endl |
776 | | << "- NB CYCLES IN HEAP LOCK in READ_FSM = " << (double) m_cpt_read_fsm_heap_used/m_cpt_read_fsm_n_heap_lock << std::endl |
777 | | << "- WAIT HEAP LOCK in WRITE_FSM = " << (double) m_cpt_write_fsm_heap_lock/m_cpt_write_fsm_n_heap_lock << std::endl |
778 | | << "- NB CYCLES IN HEAP LOCK in WRITE_FSM = " << (double) m_cpt_write_fsm_heap_used/m_cpt_write_fsm_n_heap_lock << std::endl |
779 | | << "- WAIT HEAP LOCK in XRAM_FSM = " << (double) m_cpt_xram_rsp_fsm_heap_lock/m_cpt_xram_rsp_fsm_n_heap_lock << std::endl |
780 | | << "- NB CYCLES IN HEAP LOCK in XRAM_FSM = " << (double) m_cpt_xram_rsp_fsm_heap_used/m_cpt_xram_rsp_fsm_n_heap_lock << std::endl |
781 | | << "- WAIT HEAP LOCK in CLEANUP_FSM = " << (double) m_cpt_cleanup_fsm_heap_lock/m_cpt_cleanup_fsm_n_heap_lock << std::endl |
782 | | << "- NB CYCLES IN HEAP LOCK in CLEANUP_FSM = " << (double) m_cpt_cleanup_fsm_heap_used/m_cpt_cleanup_fsm_n_heap_lock << std::endl |
783 | | << "- WAIT HEAP LOCK in CAS_FSM = " << (double) m_cpt_cas_fsm_heap_lock/m_cpt_cas_fsm_n_heap_lock << std::endl |
784 | | << "- NB CYCLES IN HEAP LOCK in CAS_FSM = " << (double) m_cpt_cas_fsm_heap_used/m_cpt_cas_fsm_n_heap_lock << std::endl |
785 | | << "- HEAP UNUSED RATE = " << (double) m_cpt_heap_unused/m_cpt_cycles << std::endl;*/ |
786 | | } |
787 | | |
788 | | ///////////////////////////////// |
789 | | tmpl(/**/) ::~VciMemCache() |
790 | | ///////////////////////////////// |
791 | | { |
792 | | delete [] r_ixr_rsp_to_xram_rsp_rok; |
793 | | //delete [] r_ixr_rsp_to_xram_rsp_no_coherent; |
794 | | |
795 | | delete [] r_xram_rsp_victim_data; |
796 | | delete [] r_xram_rsp_to_tgt_rsp_data; |
797 | | |
798 | | delete [] r_read_data; |
799 | | delete [] r_read_to_tgt_rsp_data; |
800 | | |
801 | | delete [] r_write_data; |
802 | | delete [] r_write_be; |
803 | | delete [] r_write_to_cc_send_data; |
804 | | |
805 | | delete [] r_cleanup_data; |
806 | | delete [] r_ixr_cmd_data; |
807 | | delete [] r_cleanup_to_ixr_cmd_data; |
808 | | } |
809 | | |
810 | | ////////////////////////////////// |
811 | | tmpl(void) ::transition() |
812 | | ////////////////////////////////// |
813 | | { |
814 | | using soclib::common::uint32_log2; |
815 | | |
816 | | // RESET |
817 | | if(! p_resetn.read()) |
818 | | { |
819 | | |
820 | | // Initializing FSMs |
821 | | r_tgt_cmd_fsm = TGT_CMD_IDLE; |
822 | | r_config_fsm = CONFIG_IDLE; |
823 | | r_tgt_rsp_fsm = TGT_RSP_TGT_CMD_IDLE; |
824 | | r_cc_send_fsm = CC_SEND_XRAM_RSP_IDLE; |
825 | | r_cc_receive_fsm = CC_RECEIVE_IDLE; |
826 | | r_multi_ack_fsm = MULTI_ACK_IDLE; |
827 | | r_read_fsm = READ_IDLE; |
828 | | r_write_fsm = WRITE_IDLE; |
829 | | r_cas_fsm = CAS_IDLE; |
830 | | r_cleanup_fsm = CLEANUP_IDLE; |
831 | | r_alloc_dir_fsm = ALLOC_DIR_RESET; |
832 | | r_alloc_heap_fsm = ALLOC_HEAP_RESET; |
833 | | r_alloc_trt_fsm = ALLOC_TRT_READ; |
834 | | r_alloc_upt_fsm = ALLOC_UPT_WRITE; |
835 | | r_alloc_ivt_fsm = ALLOC_IVT_XRAM_RSP; |
836 | | r_ixr_rsp_fsm = IXR_RSP_IDLE; |
837 | | r_xram_rsp_fsm = XRAM_RSP_IDLE; |
838 | | r_ixr_cmd_fsm = IXR_CMD_READ_IDLE; |
839 | | |
840 | | m_debug = false; |
841 | | m_debug_previous_valid = false; |
842 | | m_debug_previous_dirty = false; |
843 | | m_debug_previous_count = 0; |
844 | | |
845 | | // Initializing Tables |
846 | | m_trt.init(); |
847 | | m_upt.init(); |
848 | | m_ivt.init(); |
849 | | m_llsc_table.init(); |
850 | | |
851 | | // initializing FIFOs and communication Buffers |
852 | | |
853 | | m_cmd_read_addr_fifo.init(); |
854 | | m_cmd_read_length_fifo.init(); |
855 | | m_cmd_read_srcid_fifo.init(); |
856 | | m_cmd_read_trdid_fifo.init(); |
857 | | m_cmd_read_pktid_fifo.init(); |
858 | | |
859 | | m_cmd_write_addr_fifo.init(); |
860 | | m_cmd_write_eop_fifo.init(); |
861 | | m_cmd_write_srcid_fifo.init(); |
862 | | m_cmd_write_trdid_fifo.init(); |
863 | | m_cmd_write_pktid_fifo.init(); |
864 | | m_cmd_write_data_fifo.init(); |
865 | | |
866 | | m_cmd_cas_addr_fifo.init() ; |
867 | | m_cmd_cas_srcid_fifo.init() ; |
868 | | m_cmd_cas_trdid_fifo.init() ; |
869 | | m_cmd_cas_pktid_fifo.init() ; |
870 | | m_cmd_cas_wdata_fifo.init() ; |
871 | | m_cmd_cas_eop_fifo.init() ; |
872 | | |
873 | | r_config_cmd = MEMC_CMD_NOP; |
874 | | r_config_lock = false; |
875 | | |
876 | | m_config_to_cc_send_inst_fifo.init(); |
877 | | m_config_to_cc_send_srcid_fifo.init(); |
878 | | |
879 | | r_tgt_cmd_to_tgt_rsp_req = false; |
880 | | |
881 | | r_read_to_tgt_rsp_req = false; |
882 | | r_read_to_ixr_cmd_req = false; |
883 | | |
884 | | r_write_to_tgt_rsp_req = false; |
885 | | r_write_to_ixr_cmd_req = false; |
886 | | r_write_to_cc_send_multi_req = false; |
887 | | r_write_to_cc_send_brdcast_req = false; |
888 | | r_write_to_multi_ack_req = false; |
889 | | |
890 | | m_write_to_cc_send_inst_fifo.init(); |
891 | | m_write_to_cc_send_srcid_fifo.init(); |
892 | | |
893 | | r_cleanup_to_tgt_rsp_req = false; |
894 | | |
895 | | m_cc_receive_to_cleanup_fifo.init(); |
896 | | |
897 | | r_multi_ack_to_tgt_rsp_req = false; |
898 | | |
899 | | m_cc_receive_to_multi_ack_fifo.init(); |
900 | | |
901 | | r_cas_to_tgt_rsp_req = false; |
902 | | r_cas_cpt = 0 ; |
903 | | r_cas_lfsr = -1 ; |
904 | | r_cas_to_ixr_cmd_req = false; |
905 | | r_cas_to_cc_send_multi_req = false; |
906 | | r_cas_to_cc_send_brdcast_req = false; |
907 | | |
908 | | m_cas_to_cc_send_inst_fifo.init(); |
909 | | m_cas_to_cc_send_srcid_fifo.init(); |
910 | | |
911 | | for(size_t i=0; i<m_trt_lines ; i++) |
| 648 | } |
| 649 | |
| 650 | ///////////////////////////////////////// |
| 651 | tmpl(void) ::clear_stats() |
| 652 | ///////////////////////////////////////// |
950 | | |
951 | | // Activity counters |
952 | | m_cpt_cycles = 0; |
953 | | m_cpt_read = 0; |
954 | | m_cpt_read_miss = 0; |
955 | | m_cpt_write = 0; |
956 | | m_cpt_write_miss = 0; |
957 | | m_cpt_write_cells = 0; |
958 | | m_cpt_write_dirty = 0; |
959 | | m_cpt_update = 0; |
960 | | m_cpt_update_mult = 0; |
961 | | m_cpt_inval_brdcast = 0; |
962 | | m_cpt_inval = 0; |
963 | | m_cpt_inval_mult = 0; |
964 | | m_cpt_cleanup = 0; |
965 | | m_cpt_cleanup_data = 0; |
966 | | m_cpt_ll = 0; |
967 | | m_cpt_sc = 0; |
968 | | m_cpt_cas = 0; |
969 | | m_cpt_trt_full = 0; |
970 | | m_cpt_trt_rb = 0; |
971 | | m_cpt_dir_unused = 0; |
972 | | m_cpt_ivt_unused = 0; |
973 | | m_cpt_heap_unused = 0; |
974 | | m_cpt_trt_unused = 0; |
975 | | m_cpt_read_fsm_n_dir_lock = 0; |
976 | | m_cpt_read_fsm_dir_lock = 0; |
977 | | m_cpt_read_fsm_dir_used = 0; |
978 | | m_cpt_read_fsm_trt_lock = 0; |
979 | | m_cpt_read_fsm_heap_lock = 0; |
980 | | m_cpt_write_fsm_dir_lock = 0; |
981 | | m_cpt_write_fsm_n_dir_lock = 0; |
982 | | m_cpt_write_fsm_upt_lock = 0; |
983 | | m_cpt_write_fsm_heap_lock = 0; |
984 | | m_cpt_write_fsm_dir_used = 0; |
985 | | m_cpt_write_fsm_trt_lock = 0; |
986 | | m_cpt_cas_fsm_n_dir_lock = 0; |
987 | | m_cpt_cas_fsm_dir_lock = 0; |
988 | | m_cpt_cas_fsm_upt_lock = 0; |
989 | | m_cpt_cas_fsm_heap_lock = 0; |
990 | | m_cpt_cas_fsm_trt_lock = 0; |
991 | | m_cpt_cas_fsm_dir_used = 0; |
992 | | m_cpt_xram_rsp_fsm_n_dir_lock = 0; |
993 | | m_cpt_xram_rsp_fsm_dir_lock = 0; |
994 | | m_cpt_xram_rsp_fsm_trt_lock = 0; |
995 | | m_cpt_xram_rsp_fsm_upt_lock = 0; |
996 | | m_cpt_xram_rsp_fsm_heap_lock = 0; |
997 | | m_cpt_xram_rsp_fsm_dir_used = 0; |
998 | | m_cpt_cleanup_fsm_dir_lock = 0; |
999 | | m_cpt_cleanup_fsm_n_dir_lock = 0; |
1000 | | m_cpt_cleanup_fsm_heap_lock = 0; |
1001 | | m_cpt_cleanup_fsm_upt_lock = 0; |
1002 | | m_cpt_cleanup_fsm_dir_used = 0; |
1003 | | m_cpt_ixr_fsm_trt_lock = 0; |
1004 | | m_cpt_multi_ack_fsm_upt_lock = 0; |
1005 | | |
1006 | | return; |
1007 | | } |
1008 | | |
1009 | | bool cmd_read_fifo_put = false; |
1010 | | bool cmd_read_fifo_get = false; |
1011 | | |
1012 | | bool cmd_write_fifo_put = false; |
1013 | | bool cmd_write_fifo_get = false; |
1014 | | |
1015 | | bool cmd_cas_fifo_put = false; |
1016 | | bool cmd_cas_fifo_get = false; |
1017 | | |
1018 | | bool cc_receive_to_cleanup_fifo_get = false; |
1019 | | bool cc_receive_to_cleanup_fifo_put = false; |
1020 | | |
1021 | | bool cc_receive_to_multi_ack_fifo_get = false; |
1022 | | bool cc_receive_to_multi_ack_fifo_put = false; |
1023 | | |
1024 | | bool write_to_cc_send_fifo_put = false; |
1025 | | bool write_to_cc_send_fifo_get = false; |
1026 | | bool write_to_cc_send_fifo_inst = false; |
1027 | | size_t write_to_cc_send_fifo_srcid = 0; |
1028 | | |
1029 | | bool xram_rsp_to_cc_send_fifo_put = false; |
1030 | | bool xram_rsp_to_cc_send_fifo_get = false; |
1031 | | bool xram_rsp_to_cc_send_fifo_inst = false; |
1032 | | size_t xram_rsp_to_cc_send_fifo_srcid = 0; |
1033 | | |
1034 | | bool config_to_cc_send_fifo_put = false; |
1035 | | bool config_to_cc_send_fifo_get = false; |
1036 | | bool config_to_cc_send_fifo_inst = false; |
1037 | | size_t config_to_cc_send_fifo_srcid = 0; |
1038 | | |
1039 | | bool cas_to_cc_send_fifo_put = false; |
1040 | | bool cas_to_cc_send_fifo_get = false; |
1041 | | bool cas_to_cc_send_fifo_inst = false; |
1042 | | size_t cas_to_cc_send_fifo_srcid = 0; |
1043 | | |
1044 | | m_debug = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok; |
| 788 | ///////////////////////////////// |
| 789 | tmpl(/**/) ::~VciMemCache() |
| 790 | ///////////////////////////////// |
| 791 | { |
| 792 | delete [] r_ixr_rsp_to_xram_rsp_rok; |
| 793 | //delete [] r_ixr_rsp_to_xram_rsp_no_coherent; |
| 794 | |
| 795 | delete [] r_xram_rsp_victim_data; |
| 796 | delete [] r_xram_rsp_to_tgt_rsp_data; |
| 797 | |
| 798 | delete [] r_read_data; |
| 799 | delete [] r_read_to_tgt_rsp_data; |
| 800 | |
| 801 | delete [] r_write_data; |
| 802 | delete [] r_write_be; |
| 803 | delete [] r_write_to_cc_send_data; |
| 804 | |
| 805 | delete [] r_cleanup_data; |
| 806 | delete [] r_ixr_cmd_data; |
| 807 | delete [] r_cleanup_to_ixr_cmd_data; |
| 808 | } |
| 809 | |
| 810 | ////////////////////////////////// |
| 811 | tmpl(void) ::transition() |
| 812 | ////////////////////////////////// |
| 813 | { |
| 814 | using soclib::common::uint32_log2; |
| 815 | |
| 816 | // RESET |
| 817 | if(! p_resetn.read()) |
| 818 | { |
| 819 | |
| 820 | // Initializing FSMs |
| 821 | r_tgt_cmd_fsm = TGT_CMD_IDLE; |
| 822 | r_config_fsm = CONFIG_IDLE; |
| 823 | r_tgt_rsp_fsm = TGT_RSP_TGT_CMD_IDLE; |
| 824 | r_cc_send_fsm = CC_SEND_XRAM_RSP_IDLE; |
| 825 | r_cc_receive_fsm = CC_RECEIVE_IDLE; |
| 826 | r_multi_ack_fsm = MULTI_ACK_IDLE; |
| 827 | r_read_fsm = READ_IDLE; |
| 828 | r_write_fsm = WRITE_IDLE; |
| 829 | r_cas_fsm = CAS_IDLE; |
| 830 | r_cleanup_fsm = CLEANUP_IDLE; |
| 831 | r_alloc_dir_fsm = ALLOC_DIR_RESET; |
| 832 | r_alloc_heap_fsm = ALLOC_HEAP_RESET; |
| 833 | r_alloc_trt_fsm = ALLOC_TRT_READ; |
| 834 | r_alloc_upt_fsm = ALLOC_UPT_WRITE; |
| 835 | r_alloc_ivt_fsm = ALLOC_IVT_XRAM_RSP; |
| 836 | r_ixr_rsp_fsm = IXR_RSP_IDLE; |
| 837 | r_xram_rsp_fsm = XRAM_RSP_IDLE; |
| 838 | r_ixr_cmd_fsm = IXR_CMD_READ_IDLE; |
| 839 | |
| 840 | m_debug = false; |
| 841 | m_debug_previous_valid = false; |
| 842 | m_debug_previous_dirty = false; |
| 843 | m_debug_previous_count = 0; |
| 844 | |
| 845 | // Initializing Tables |
| 846 | m_trt.init(); |
| 847 | m_upt.init(); |
| 848 | m_ivt.init(); |
| 849 | m_llsc_table.init(); |
| 850 | |
| 851 | // initializing FIFOs and communication Buffers |
| 852 | |
| 853 | m_cmd_read_addr_fifo.init(); |
| 854 | m_cmd_read_length_fifo.init(); |
| 855 | m_cmd_read_srcid_fifo.init(); |
| 856 | m_cmd_read_trdid_fifo.init(); |
| 857 | m_cmd_read_pktid_fifo.init(); |
| 858 | |
| 859 | m_cmd_write_addr_fifo.init(); |
| 860 | m_cmd_write_eop_fifo.init(); |
| 861 | m_cmd_write_srcid_fifo.init(); |
| 862 | m_cmd_write_trdid_fifo.init(); |
| 863 | m_cmd_write_pktid_fifo.init(); |
| 864 | m_cmd_write_data_fifo.init(); |
| 865 | |
| 866 | m_cmd_cas_addr_fifo.init() ; |
| 867 | m_cmd_cas_srcid_fifo.init() ; |
| 868 | m_cmd_cas_trdid_fifo.init() ; |
| 869 | m_cmd_cas_pktid_fifo.init() ; |
| 870 | m_cmd_cas_wdata_fifo.init() ; |
| 871 | m_cmd_cas_eop_fifo.init() ; |
| 872 | |
| 873 | r_config_cmd = MEMC_CMD_NOP; |
| 874 | r_config_lock = false; |
| 875 | |
| 876 | m_config_to_cc_send_inst_fifo.init(); |
| 877 | m_config_to_cc_send_srcid_fifo.init(); |
| 878 | |
| 879 | r_tgt_cmd_to_tgt_rsp_req = false; |
| 880 | |
| 881 | r_read_to_tgt_rsp_req = false; |
| 882 | r_read_to_ixr_cmd_req = false; |
| 883 | |
| 884 | r_write_to_tgt_rsp_req = false; |
| 885 | r_write_to_ixr_cmd_req = false; |
| 886 | r_write_to_cc_send_multi_req = false; |
| 887 | r_write_to_cc_send_brdcast_req = false; |
| 888 | r_write_to_multi_ack_req = false; |
| 889 | |
| 890 | m_write_to_cc_send_inst_fifo.init(); |
| 891 | m_write_to_cc_send_srcid_fifo.init(); |
| 892 | |
| 893 | r_cleanup_to_tgt_rsp_req = false; |
| 894 | |
| 895 | m_cc_receive_to_cleanup_fifo.init(); |
| 896 | |
| 897 | r_multi_ack_to_tgt_rsp_req = false; |
| 898 | |
| 899 | m_cc_receive_to_multi_ack_fifo.init(); |
| 900 | |
| 901 | r_cas_to_tgt_rsp_req = false; |
| 902 | r_cas_cpt = 0 ; |
| 903 | r_cas_lfsr = -1 ; |
| 904 | r_cas_to_ixr_cmd_req = false; |
| 905 | r_cas_to_cc_send_multi_req = false; |
| 906 | r_cas_to_cc_send_brdcast_req = false; |
| 907 | |
| 908 | m_cas_to_cc_send_inst_fifo.init(); |
| 909 | m_cas_to_cc_send_srcid_fifo.init(); |
| 910 | |
| 911 | for(size_t i=0; i<m_trt_lines ; i++) |
| 912 | { |
| 913 | r_ixr_rsp_to_xram_rsp_rok[i] = false; |
| 914 | //r_ixr_rsp_to_xram_rsp_no_coherent[i] = false; |
| 915 | } |
| 916 | |
| 917 | r_xram_rsp_to_tgt_rsp_req = false; |
| 918 | r_xram_rsp_to_cc_send_multi_req = false; |
| 919 | r_xram_rsp_to_cc_send_brdcast_req = false; |
| 920 | r_xram_rsp_to_ixr_cmd_req = false; |
| 921 | r_xram_rsp_trt_index = 0; |
| 922 | |
| 923 | m_xram_rsp_to_cc_send_inst_fifo.init(); |
| 924 | m_xram_rsp_to_cc_send_srcid_fifo.init(); |
| 925 | |
| 926 | r_alloc_dir_reset_cpt = 0; |
| 927 | r_alloc_heap_reset_cpt = 0; |
| 928 | |
| 929 | r_tgt_rsp_key_sent = false; |
| 930 | |
| 931 | // ODCCP |
| 932 | r_cleanup_data_index = 0; |
| 933 | r_cleanup_trdid = 0; |
| 934 | r_cleanup_pktid = 0; |
| 935 | r_cleanup_contains_data = false; |
| 936 | r_cleanup_to_ixr_cmd_req = false; |
| 937 | //r_cleanup_to_ixr_cmd_l1_dirty_ncc = false; |
| 938 | //r_xram_rsp_to_ixr_cmd_inval_ncc_pending = false; |
| 939 | r_cleanup_to_ixr_cmd_srcid = 0; |
| 940 | r_cleanup_to_ixr_cmd_index = 0; |
| 941 | r_cleanup_to_ixr_cmd_pktid = 0; |
| 942 | r_cleanup_to_ixr_cmd_nline = 0; |
| 943 | for (size_t word = 0; word < m_words; word ++) |
| 944 | { |
| 945 | r_cleanup_to_ixr_cmd_data[word] = 0; |
| 946 | r_cleanup_data[word] = 0; |
| 947 | r_ixr_cmd_wdata[word] = 0; |
| 948 | } |
| 949 | |
| 950 | |
| 951 | // Activity counters |
| 952 | m_cpt_cycles = 0; |
| 953 | m_cpt_read = 0; |
| 954 | m_cpt_read_miss = 0; |
| 955 | m_cpt_write = 0; |
| 956 | m_cpt_write_miss = 0; |
| 957 | m_cpt_write_cells = 0; |
| 958 | m_cpt_write_dirty = 0; |
| 959 | m_cpt_update = 0; |
| 960 | m_cpt_update_mult = 0; |
| 961 | m_cpt_inval_brdcast = 0; |
| 962 | m_cpt_inval = 0; |
| 963 | m_cpt_inval_mult = 0; |
| 964 | m_cpt_cleanup = 0; |
| 965 | m_cpt_cleanup_data = 0; |
| 966 | m_cpt_ll = 0; |
| 967 | m_cpt_sc = 0; |
| 968 | m_cpt_cas = 0; |
| 969 | m_cpt_trt_full = 0; |
| 970 | m_cpt_trt_rb = 0; |
| 971 | m_cpt_dir_unused = 0; |
| 972 | m_cpt_ivt_unused = 0; |
| 973 | m_cpt_heap_unused = 0; |
| 974 | m_cpt_trt_unused = 0; |
| 975 | m_cpt_read_fsm_n_dir_lock = 0; |
| 976 | m_cpt_read_fsm_dir_lock = 0; |
| 977 | m_cpt_read_fsm_dir_used = 0; |
| 978 | m_cpt_read_fsm_trt_lock = 0; |
| 979 | m_cpt_read_fsm_heap_lock = 0; |
| 980 | m_cpt_write_fsm_dir_lock = 0; |
| 981 | m_cpt_write_fsm_n_dir_lock = 0; |
| 982 | m_cpt_write_fsm_upt_lock = 0; |
| 983 | m_cpt_write_fsm_heap_lock = 0; |
| 984 | m_cpt_write_fsm_dir_used = 0; |
| 985 | m_cpt_write_fsm_trt_lock = 0; |
| 986 | m_cpt_cas_fsm_n_dir_lock = 0; |
| 987 | m_cpt_cas_fsm_dir_lock = 0; |
| 988 | m_cpt_cas_fsm_upt_lock = 0; |
| 989 | m_cpt_cas_fsm_heap_lock = 0; |
| 990 | m_cpt_cas_fsm_trt_lock = 0; |
| 991 | m_cpt_cas_fsm_dir_used = 0; |
| 992 | m_cpt_xram_rsp_fsm_n_dir_lock = 0; |
| 993 | m_cpt_xram_rsp_fsm_dir_lock = 0; |
| 994 | m_cpt_xram_rsp_fsm_trt_lock = 0; |
| 995 | m_cpt_xram_rsp_fsm_upt_lock = 0; |
| 996 | m_cpt_xram_rsp_fsm_heap_lock = 0; |
| 997 | m_cpt_xram_rsp_fsm_dir_used = 0; |
| 998 | m_cpt_cleanup_fsm_dir_lock = 0; |
| 999 | m_cpt_cleanup_fsm_n_dir_lock = 0; |
| 1000 | m_cpt_cleanup_fsm_heap_lock = 0; |
| 1001 | m_cpt_cleanup_fsm_upt_lock = 0; |
| 1002 | m_cpt_cleanup_fsm_dir_used = 0; |
| 1003 | m_cpt_ixr_fsm_trt_lock = 0; |
| 1004 | m_cpt_multi_ack_fsm_upt_lock = 0; |
| 1005 | |
| 1006 | return; |
| 1007 | } |
| 1008 | |
| 1009 | bool cmd_read_fifo_put = false; |
| 1010 | bool cmd_read_fifo_get = false; |
| 1011 | |
| 1012 | bool cmd_write_fifo_put = false; |
| 1013 | bool cmd_write_fifo_get = false; |
| 1014 | |
| 1015 | bool cmd_cas_fifo_put = false; |
| 1016 | bool cmd_cas_fifo_get = false; |
| 1017 | |
| 1018 | bool cc_receive_to_cleanup_fifo_get = false; |
| 1019 | bool cc_receive_to_cleanup_fifo_put = false; |
| 1020 | |
| 1021 | bool cc_receive_to_multi_ack_fifo_get = false; |
| 1022 | bool cc_receive_to_multi_ack_fifo_put = false; |
| 1023 | |
| 1024 | bool write_to_cc_send_fifo_put = false; |
| 1025 | bool write_to_cc_send_fifo_get = false; |
| 1026 | bool write_to_cc_send_fifo_inst = false; |
| 1027 | size_t write_to_cc_send_fifo_srcid = 0; |
| 1028 | |
| 1029 | bool xram_rsp_to_cc_send_fifo_put = false; |
| 1030 | bool xram_rsp_to_cc_send_fifo_get = false; |
| 1031 | bool xram_rsp_to_cc_send_fifo_inst = false; |
| 1032 | size_t xram_rsp_to_cc_send_fifo_srcid = 0; |
| 1033 | |
| 1034 | bool config_to_cc_send_fifo_put = false; |
| 1035 | bool config_to_cc_send_fifo_get = false; |
| 1036 | bool config_to_cc_send_fifo_inst = false; |
| 1037 | size_t config_to_cc_send_fifo_srcid = 0; |
| 1038 | |
| 1039 | bool cas_to_cc_send_fifo_put = false; |
| 1040 | bool cas_to_cc_send_fifo_get = false; |
| 1041 | bool cas_to_cc_send_fifo_inst = false; |
| 1042 | size_t cas_to_cc_send_fifo_srcid = 0; |
| 1043 | |
| 1044 | m_debug = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok; |
1104 | | if(m_debug) |
1105 | | std::cout << " <MEMC " << name() |
1106 | | << " TGT_CMD_IDLE> Receive command from srcid " |
1107 | | << std::hex << p_vci_tgt.srcid.read() |
1108 | | << " / address " << std::hex << p_vci_tgt.address.read() << std::endl; |
1109 | | #endif |
1110 | | // checking segmentation violation |
1111 | | addr_t address = p_vci_tgt.address.read(); |
1112 | | uint32_t plen = p_vci_tgt.plen.read(); |
1113 | | bool found = false; |
1114 | | bool config = false; |
1115 | | |
1116 | | // register arguments for response (segmentation violation or config) |
1117 | | r_tgt_cmd_to_tgt_rsp_srcid = p_vci_tgt.srcid.read(); |
1118 | | r_tgt_cmd_to_tgt_rsp_trdid = p_vci_tgt.trdid.read(); |
1119 | | r_tgt_cmd_to_tgt_rsp_pktid = p_vci_tgt.pktid.read(); |
1120 | | |
1121 | | for(size_t seg_id = 0 ; (seg_id < m_nseg) and not found ; seg_id++) |
| 1104 | if(m_debug) |
| 1105 | std::cout << " <MEMC " << name() |
| 1106 | << " TGT_CMD_IDLE> Receive command from srcid " |
| 1107 | << std::hex << p_vci_tgt.srcid.read() |
| 1108 | << " / address " << std::hex << p_vci_tgt.address.read() << std::endl; |
| 1109 | #endif |
| 1110 | // checking segmentation violation |
| 1111 | addr_t address = p_vci_tgt.address.read(); |
| 1112 | uint32_t plen = p_vci_tgt.plen.read(); |
| 1113 | bool found = false; |
| 1114 | bool config = false; |
| 1115 | |
| 1116 | // register arguments for response (segmentation violation or config) |
| 1117 | r_tgt_cmd_to_tgt_rsp_srcid = p_vci_tgt.srcid.read(); |
| 1118 | r_tgt_cmd_to_tgt_rsp_trdid = p_vci_tgt.trdid.read(); |
| 1119 | r_tgt_cmd_to_tgt_rsp_pktid = p_vci_tgt.pktid.read(); |
| 1120 | |
| 1121 | for(size_t seg_id = 0 ; (seg_id < m_nseg) and not found ; seg_id++) |
| 1122 | { |
| 1123 | if( m_seg[seg_id]->contains(address) and |
| 1124 | m_seg[seg_id]->contains(address + plen - vci_param_int::B) ) |
| 1125 | { |
| 1126 | found = true; |
| 1127 | if ( m_seg[seg_id]->special() ) config = true; |
| 1128 | } |
| 1129 | } |
| 1130 | |
| 1131 | if ( not found ) /////////// out of segment error |
| 1132 | { |
| 1133 | r_tgt_cmd_fsm = TGT_CMD_ERROR; |
| 1134 | } |
| 1135 | else if ( config ) /////////// configuration command |
| 1136 | { |
| 1137 | if ( not p_vci_tgt.eop.read() ) r_tgt_cmd_fsm = TGT_CMD_ERROR; |
| 1138 | else r_tgt_cmd_fsm = TGT_CMD_CONFIG; |
| 1139 | } |
| 1140 | else //////////// memory access |
| 1141 | { |
| 1142 | if ( p_vci_tgt.cmd.read() == vci_param_int::CMD_READ ) |
| 1143 | { |
| 1144 | // check that the pktid is either : |
| 1145 | // TYPE_READ_DATA_UNC |
| 1146 | // TYPE_READ_DATA_MISS |
| 1147 | // TYPE_READ_INS_UNC |
| 1148 | // TYPE_READ_INS_MISS |
| 1149 | // ==> bit2 must be zero with the TSAR encoding |
| 1150 | // ==> mask = 0b0100 = 0x4 |
| 1151 | assert( ((p_vci_tgt.pktid.read() & 0x4) == 0x0) and |
| 1152 | "The type specified in the pktid field is incompatible with the READ CMD"); |
| 1153 | r_tgt_cmd_fsm = TGT_CMD_READ; |
| 1154 | } |
| 1155 | else if(p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE) |
| 1156 | { |
| 1157 | // check that the pktid is TYPE_WRITE |
| 1158 | // ==> TYPE_WRITE = X100 with the TSAR encoding |
| 1159 | // ==> mask = 0b0111 = 0x7 |
| 1160 | assert(((p_vci_tgt.pktid.read() & 0x7) == 0x4) and |
| 1161 | "The type specified in the pktid field is incompatible with the WRITE CMD"); |
| 1162 | r_tgt_cmd_fsm = TGT_CMD_WRITE; |
| 1163 | } |
| 1164 | else if(p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ) |
| 1165 | { |
| 1166 | // check that the pktid is TYPE_LL |
| 1167 | // ==> TYPE_LL = X110 with the TSAR encoding |
| 1168 | // ==> mask = 0b0111 = 0x7 |
| 1169 | assert(((p_vci_tgt.pktid.read() & 0x7) == 0x6) and |
| 1170 | "The type specified in the pktid field is incompatible with the LL CMD"); |
| 1171 | r_tgt_cmd_fsm = TGT_CMD_READ; |
| 1172 | } |
| 1173 | else if(p_vci_tgt.cmd.read() == vci_param_int::CMD_NOP) |
| 1174 | { |
| 1175 | // check that the pktid is either : |
| 1176 | // TYPE_CAS |
| 1177 | // TYPE_SC |
| 1178 | // ==> TYPE_CAS = X101 with the TSAR encoding |
| 1179 | // ==> TYPE_SC = X111 with the TSAR encoding |
| 1180 | // ==> mask = 0b0101 = 0x5 |
| 1181 | assert(((p_vci_tgt.pktid.read() & 0x5) == 0x5) and |
| 1182 | "The type specified in the pktid field is incompatible with the NOP CMD"); |
| 1183 | |
| 1184 | if((p_vci_tgt.pktid.read() & 0x7) == TYPE_CAS) r_tgt_cmd_fsm = TGT_CMD_CAS; |
| 1185 | else r_tgt_cmd_fsm = TGT_CMD_WRITE; |
| 1186 | } |
| 1187 | else |
| 1188 | { |
| 1189 | r_tgt_cmd_fsm = TGT_CMD_ERROR; |
| 1190 | } |
| 1191 | } |
| 1192 | } |
| 1193 | break; |
| 1194 | |
| 1195 | /////////////////// |
| 1196 | case TGT_CMD_ERROR: // response error must be sent |
| 1197 | |
| 1198 | // wait if pending request |
| 1199 | if(r_tgt_cmd_to_tgt_rsp_req.read()) break; |
| 1200 | |
| 1201 | // consume all the command packet flits before sending response error |
| 1202 | if ( p_vci_tgt.cmdval and p_vci_tgt.eop ) |
| 1203 | { |
| 1204 | r_tgt_cmd_to_tgt_rsp_req = true; |
| 1205 | r_tgt_cmd_to_tgt_rsp_error = 1; |
| 1206 | r_tgt_cmd_fsm = TGT_CMD_IDLE; |
| 1207 | |
| 1208 | #if DEBUG_MEMC_TGT_CMD |
| 1209 | if(m_debug) |
| 1210 | std::cout << " <MEMC " << name() |
| 1211 | << " TGT_CMD_ERROR> Segmentation violation:" |
| 1212 | << " address = " << std::hex << p_vci_tgt.address.read() |
| 1213 | << " / srcid = " << p_vci_tgt.srcid.read() |
| 1214 | << " / trdid = " << p_vci_tgt.trdid.read() |
| 1215 | << " / pktid = " << p_vci_tgt.pktid.read() |
| 1216 | << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl; |
| 1217 | #endif |
| 1218 | |
| 1219 | } |
| 1220 | break; |
| 1221 | |
| 1222 | //////////////////// |
| 1223 | case TGT_CMD_CONFIG: // execute config request and return response |
| 1224 | { |
| 1225 | addr_t seg_base = m_seg[m_seg_config]->baseAddress(); |
| 1226 | addr_t address = p_vci_tgt.address.read(); |
| 1227 | size_t cell = (address - seg_base)/vci_param_int::B; |
| 1228 | |
| 1229 | bool need_rsp; |
| 1230 | size_t error; |
| 1231 | uint32_t rdata = 0; // default value |
| 1232 | uint32_t wdata = p_vci_tgt.wdata.read(); |
| 1233 | |
| 1234 | if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_READ) // get lock |
| 1235 | and (cell == MEMC_LOCK) ) |
| 1236 | { |
| 1237 | rdata = (uint32_t)r_config_lock.read(); |
| 1238 | need_rsp = true; |
| 1239 | error = 0; |
| 1240 | r_config_lock = true; |
| 1241 | if ( rdata == 0 ) |
| 1242 | { |
| 1243 | r_tgt_cmd_srcid = p_vci_tgt.srcid.read(); |
| 1244 | r_tgt_cmd_trdid = p_vci_tgt.trdid.read(); |
| 1245 | r_tgt_cmd_pktid = p_vci_tgt.pktid.read(); |
| 1246 | } |
| 1247 | } |
| 1248 | else if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE) // release lock |
| 1249 | and (cell == MEMC_LOCK) |
| 1250 | and (p_vci_tgt.srcid.read() == r_tgt_cmd_srcid.read()) ) |
| 1251 | { |
| 1252 | need_rsp = true; |
| 1253 | error = 0; |
| 1254 | r_config_lock = false; |
| 1255 | } |
| 1256 | else if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE) // set addr_lo |
| 1257 | and (cell == MEMC_ADDR_LO) |
| 1258 | and (p_vci_tgt.srcid.read() == r_tgt_cmd_srcid.read()) ) |
| 1259 | { |
| 1260 | assert( ((wdata % (m_words*vci_param_int::B)) == 0) and |
| 1261 | "VCI_MEM_CACHE CONFIG ERROR: The buffer must be aligned on a cache line"); |
| 1262 | |
| 1263 | need_rsp = true; |
| 1264 | error = 0; |
| 1265 | r_config_address = (r_config_address.read() & 0xFFFFFFFF00000000LL) | |
| 1266 | (addr_t)p_vci_tgt.wdata.read(); |
| 1267 | } |
| 1268 | else if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE) // set addr_hi |
| 1269 | and (cell == MEMC_ADDR_HI) |
| 1270 | and (p_vci_tgt.srcid.read() == r_tgt_cmd_srcid.read()) ) |
| 1271 | |
| 1272 | { |
| 1273 | need_rsp = true; |
| 1274 | error = 0; |
| 1275 | r_config_address = (r_config_address.read() & 0x00000000FFFFFFFFLL) | |
| 1276 | ((addr_t)p_vci_tgt.wdata.read())<<32; |
| 1277 | } |
| 1278 | else if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE) // set buf_lines |
| 1279 | and (cell == MEMC_BUF_LENGTH) |
| 1280 | and (p_vci_tgt.srcid.read() == r_tgt_cmd_srcid.read()) ) |
| 1281 | { |
| 1282 | need_rsp = true; |
| 1283 | error = 0; |
| 1284 | size_t lines = (size_t)(p_vci_tgt.wdata.read()/(m_words<<2)); |
| 1285 | if ( r_config_address.read()%(m_words*4) ) lines++; |
| 1286 | r_config_cmd_lines = lines; |
| 1287 | r_config_rsp_lines = lines; |
| 1288 | } |
| 1289 | else if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE) // set cmd type |
| 1290 | and (cell == MEMC_CMD_TYPE) |
| 1291 | and (p_vci_tgt.srcid.read() == r_tgt_cmd_srcid.read()) ) |
| 1292 | { |
| 1293 | need_rsp = false; |
| 1294 | error = 0; |
| 1295 | r_config_cmd = p_vci_tgt.wdata.read(); |
| 1296 | |
| 1297 | // prepare delayed response from CONFIG FSM |
| 1298 | r_config_srcid = p_vci_tgt.srcid.read(); |
| 1299 | r_config_trdid = p_vci_tgt.trdid.read(); |
| 1300 | r_config_pktid = p_vci_tgt.pktid.read(); |
| 1301 | } |
| 1302 | else |
| 1303 | { |
| 1304 | need_rsp = true; |
| 1305 | error = 1; |
| 1306 | } |
| 1307 | |
| 1308 | if ( need_rsp ) |
| 1309 | { |
| 1310 | // blocked if previous pending request to TGT_RSP FSM |
| 1311 | if ( r_tgt_cmd_to_tgt_rsp_req.read() ) break; |
| 1312 | |
| 1313 | r_tgt_cmd_to_tgt_rsp_req = true; |
| 1314 | r_tgt_cmd_to_tgt_rsp_error = error; |
| 1315 | r_tgt_cmd_to_tgt_rsp_rdata = rdata; |
| 1316 | r_tgt_cmd_fsm = TGT_CMD_IDLE; |
| 1317 | } |
| 1318 | else |
| 1319 | { |
| 1320 | r_tgt_cmd_fsm = TGT_CMD_IDLE; |
| 1321 | } |
| 1322 | |
| 1323 | #if DEBUG_MEMC_TGT_CMD |
| 1324 | if(m_debug) |
| 1325 | std::cout << " <MEMC " << name() << " TGT_CMD_CONFIG> Configuration request:" |
| 1326 | << " address = " << std::hex << p_vci_tgt.address.read() |
| 1327 | << " / wdata = " << p_vci_tgt.wdata.read() |
| 1328 | << " / need_rsp = " << need_rsp |
| 1329 | << " / error = " << error << std::endl; |
| 1330 | #endif |
| 1331 | break; |
| 1332 | } |
| 1333 | ////////////////// |
| 1334 | case TGT_CMD_READ: // Push a read request into read fifo |
| 1335 | |
| 1336 | // check that the read does not cross a cache line limit. |
| 1337 | if ( ((m_x[(addr_t) p_vci_tgt.address.read()]+ (p_vci_tgt.plen.read() >>2)) > 16) and |
| 1338 | (p_vci_tgt.cmd.read() != vci_param_int::CMD_LOCKED_READ)) |
| 1339 | { |
| 1340 | std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state" |
| 1341 | << " illegal address/plen for VCI read command" << std::endl; |
| 1342 | exit(0); |
| 1343 | } |
| 1344 | // check single flit |
| 1345 | if(!p_vci_tgt.eop.read()) |
| 1346 | { |
| 1347 | std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state" |
| 1348 | << " read command packet must contain one single flit" << std::endl; |
| 1349 | exit(0); |
| 1350 | } |
| 1351 | // check plen for LL |
| 1352 | if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ) and |
| 1353 | (p_vci_tgt.plen.read() != 8) ) |
| 1354 | { |
| 1355 | std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state" |
| 1356 | << " ll command packets must have a plen of 8" << std::endl; |
| 1357 | exit(0); |
| 1358 | } |
| 1359 | |
| 1360 | if ( p_vci_tgt.cmdval and m_cmd_read_addr_fifo.wok() ) |
| 1361 | { |
| 1362 | |
| 1363 | #if DEBUG_MEMC_TGT_CMD |
| 1364 | if(m_debug) |
| 1365 | std::cout << " <MEMC " << name() << " TGT_CMD_READ> Push into read_fifo:" |
| 1366 | << " address = " << std::hex << p_vci_tgt.address.read() |
| 1367 | << " / srcid = " << p_vci_tgt.srcid.read() |
| 1368 | << " / trdid = " << p_vci_tgt.trdid.read() |
| 1369 | << " / pktid = " << p_vci_tgt.pktid.read() |
| 1370 | << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl; |
| 1371 | #endif |
| 1372 | cmd_read_fifo_put = true; |
| 1373 | if(p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ) m_cpt_ll++; |
| 1374 | else m_cpt_read++; |
| 1375 | r_tgt_cmd_fsm = TGT_CMD_IDLE; |
| 1376 | } |
| 1377 | break; |
| 1378 | |
| 1379 | /////////////////// |
| 1380 | case TGT_CMD_WRITE: |
| 1381 | if(p_vci_tgt.cmdval and m_cmd_write_addr_fifo.wok()) |
| 1382 | { |
| 1383 | |
| 1384 | #if DEBUG_MEMC_TGT_CMD |
| 1385 | if(m_debug) |
| 1386 | std::cout << " <MEMC " << name() << " TGT_CMD_WRITE> Push into write_fifo:" |
| 1387 | << " address = " << std::hex << p_vci_tgt.address.read() |
| 1388 | << " / srcid = " << p_vci_tgt.srcid.read() |
| 1389 | << " / trdid = " << p_vci_tgt.trdid.read() |
| 1390 | << " / pktid = " << p_vci_tgt.pktid.read() |
| 1391 | << " / wdata = " << p_vci_tgt.wdata.read() |
| 1392 | << " / be = " << p_vci_tgt.be.read() |
| 1393 | << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl; |
| 1394 | #endif |
| 1395 | cmd_write_fifo_put = true; |
| 1396 | if(p_vci_tgt.eop) r_tgt_cmd_fsm = TGT_CMD_IDLE; |
| 1397 | } |
| 1398 | break; |
| 1399 | |
| 1400 | ///////////////// |
| 1401 | case TGT_CMD_CAS: |
| 1402 | if((p_vci_tgt.plen.read() != 8) and (p_vci_tgt.plen.read() != 16)) |
| 1403 | { |
| 1404 | std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_CAS state" |
| 1405 | << "illegal format for CAS command " << std::endl; |
| 1406 | exit(0); |
| 1407 | } |
| 1408 | |
| 1409 | if(p_vci_tgt.cmdval and m_cmd_cas_addr_fifo.wok()) |
| 1410 | { |
| 1411 | |
| 1412 | #if DEBUG_MEMC_TGT_CMD |
| 1413 | if(m_debug) |
| 1414 | std::cout << " <MEMC " << name() << " TGT_CMD_CAS> Pushing command into cmd_cas_fifo:" |
| 1415 | << " address = " << std::hex << p_vci_tgt.address.read() |
| 1416 | << " srcid = " << p_vci_tgt.srcid.read() |
| 1417 | << " trdid = " << p_vci_tgt.trdid.read() |
| 1418 | << " pktid = " << p_vci_tgt.pktid.read() |
| 1419 | << " wdata = " << p_vci_tgt.wdata.read() |
| 1420 | << " be = " << p_vci_tgt.be.read() |
| 1421 | << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl; |
| 1422 | #endif |
| 1423 | cmd_cas_fifo_put = true; |
| 1424 | if(p_vci_tgt.eop) r_tgt_cmd_fsm = TGT_CMD_IDLE; |
| 1425 | } |
| 1426 | break; |
| 1427 | } // end switch tgt_cmd_fsm |
| 1428 | |
| 1429 | ///////////////////////////////////////////////////////////////////////// |
| 1430 | // MULTI_ACK FSM |
| 1431 | ///////////////////////////////////////////////////////////////////////// |
| 1432 | // This FSM controls the response to the multicast update requests sent |
| 1433 | // by the memory cache to the L1 caches and update the UPT. |
| 1434 | // |
| 1435 | // - The FSM decrements the proper entry in UPT, |
| 1436 | // and clear the UPT entry when all responses have been received. |
| 1437 | // - If required, it sends a request to the TGT_RSP FSM to complete |
| 1438 | // a pending write transaction. |
| 1439 | // |
| 1440 | // All those multi-ack packets are one flit packet. |
| 1441 | // The index in the UPT is defined in the TRDID field. |
| 1442 | //////////////////////////////////////////////////////////////////////// |
| 1443 | |
| 1444 | //std::cout << std::endl << "multi_ack_fsm" << std::endl; |
| 1445 | |
| 1446 | switch(r_multi_ack_fsm.read()) |
1123 | | if( m_seg[seg_id]->contains(address) and |
1124 | | m_seg[seg_id]->contains(address + plen - vci_param_int::B) ) |
1125 | | { |
1126 | | found = true; |
1127 | | if ( m_seg[seg_id]->special() ) config = true; |
1128 | | } |
1129 | | } |
1130 | | |
1131 | | if ( not found ) /////////// out of segment error |
| 1448 | //////////////////// |
| 1449 | case MULTI_ACK_IDLE: |
| 1450 | { |
| 1451 | bool multi_ack_fifo_rok = m_cc_receive_to_multi_ack_fifo.rok(); |
| 1452 | |
| 1453 | // No CC_RECEIVE FSM request and no WRITE FSM request |
| 1454 | if( not multi_ack_fifo_rok and not r_write_to_multi_ack_req.read()) |
| 1455 | break; |
| 1456 | |
| 1457 | uint8_t updt_index; |
| 1458 | |
| 1459 | // handling WRITE FSM request to decrement update table response |
| 1460 | // counter if no CC_RECEIVE FSM request |
| 1461 | if(not multi_ack_fifo_rok) |
| 1462 | { |
| 1463 | updt_index = r_write_to_multi_ack_upt_index.read(); |
| 1464 | r_write_to_multi_ack_req = false; |
| 1465 | } |
| 1466 | // Handling CC_RECEIVE FSM request |
| 1467 | else |
| 1468 | { |
| 1469 | uint64_t flit = m_cc_receive_to_multi_ack_fifo.read(); |
| 1470 | updt_index = DspinDhccpParam::dspin_get(flit, |
| 1471 | DspinDhccpParam::MULTI_ACK_UPDT_INDEX); |
| 1472 | |
| 1473 | cc_receive_to_multi_ack_fifo_get = true; |
| 1474 | } |
| 1475 | |
| 1476 | assert((updt_index < m_upt.size()) and |
| 1477 | "VCI_MEM_CACHE ERROR in MULTI_ACK_IDLE : " |
| 1478 | "index too large for UPT"); |
| 1479 | |
| 1480 | r_multi_ack_upt_index = updt_index; |
| 1481 | r_multi_ack_fsm = MULTI_ACK_UPT_LOCK; |
| 1482 | |
| 1483 | #if DEBUG_MEMC_MULTI_ACK |
| 1484 | if(m_debug) |
| 1485 | { |
| 1486 | if (multi_ack_fifo_rok) |
| 1487 | { |
| 1488 | std::cout << " <MEMC " << name() |
| 1489 | << " MULTI_ACK_IDLE> Response for UPT entry " |
| 1490 | << (size_t)updt_index << std::endl; |
| 1491 | } |
| 1492 | else |
| 1493 | { |
| 1494 | std::cout << " <MEMC " << name() |
| 1495 | << " MULTI_ACK_IDLE> Write FSM request to decrement UPT entry " |
| 1496 | << updt_index << std::endl; |
| 1497 | } |
| 1498 | } |
| 1499 | #endif |
| 1500 | break; |
| 1501 | } |
| 1502 | |
| 1503 | //////////////////////// |
| 1504 | case MULTI_ACK_UPT_LOCK: |
| 1505 | { |
| 1506 | m_cpt_multi_ack_fsm_upt_lock++; |
| 1507 | // get lock to the UPDATE table |
| 1508 | if(r_alloc_upt_fsm.read() != ALLOC_UPT_MULTI_ACK) break; |
| 1509 | |
| 1510 | // decrement the number of expected responses |
| 1511 | size_t count = 0; |
| 1512 | bool valid = m_upt.decrement(r_multi_ack_upt_index.read(), count); |
| 1513 | |
| 1514 | |
| 1515 | if(not valid) |
| 1516 | { |
| 1517 | std::cout << "VCI_MEM_CACHE ERROR " << name() |
| 1518 | << " MULTI_ACK_UPT_LOCK state" << std::endl |
| 1519 | << "unsuccessful access to decrement the UPT" << std::endl; |
| 1520 | exit(0); |
| 1521 | } |
| 1522 | |
| 1523 | if(count == 0) |
| 1524 | { |
| 1525 | r_multi_ack_fsm = MULTI_ACK_UPT_CLEAR; |
| 1526 | } |
| 1527 | else |
| 1528 | { |
| 1529 | r_multi_ack_fsm = MULTI_ACK_IDLE; |
| 1530 | } |
| 1531 | |
| 1532 | #if DEBUG_MEMC_MULTI_ACK |
| 1533 | if(m_debug) |
| 1534 | std::cout << " <MEMC " << name() |
| 1535 | << " MULTI_ACK_UPT_LOCK> Decrement the responses counter for UPT:" |
| 1536 | << " entry = " << r_multi_ack_upt_index.read() |
| 1537 | << " / rsp_count = " << std::dec << count << std::endl; |
| 1538 | m_cpt_multi_ack_fsm_n_upt_lock++; |
| 1539 | #endif |
| 1540 | break; |
| 1541 | } |
| 1542 | |
| 1543 | ///////////////////////// |
| 1544 | case MULTI_ACK_UPT_CLEAR: // Clear UPT entry / Test if rsp or ack required |
| 1545 | { |
| 1546 | if(r_alloc_upt_fsm.read() != ALLOC_UPT_MULTI_ACK) |
| 1547 | { |
| 1548 | std::cout << "VCI_MEM_CACHE ERROR " << name() |
| 1549 | << " MULTI_ACK_UPT_CLEAR state" |
| 1550 | << " bad UPT allocation" << std::endl; |
| 1551 | exit(0); |
| 1552 | } |
| 1553 | |
| 1554 | r_multi_ack_srcid = m_upt.srcid(r_multi_ack_upt_index.read()); |
| 1555 | r_multi_ack_trdid = m_upt.trdid(r_multi_ack_upt_index.read()); |
| 1556 | r_multi_ack_pktid = m_upt.pktid(r_multi_ack_upt_index.read()); |
| 1557 | r_multi_ack_nline = m_upt.nline(r_multi_ack_upt_index.read()); |
| 1558 | bool need_rsp = m_upt.need_rsp(r_multi_ack_upt_index.read()); |
| 1559 | |
| 1560 | // clear the UPT entry |
| 1561 | m_upt.clear(r_multi_ack_upt_index.read()); |
| 1562 | |
| 1563 | if ( need_rsp ) r_multi_ack_fsm = MULTI_ACK_WRITE_RSP; |
| 1564 | else r_multi_ack_fsm = MULTI_ACK_IDLE; |
| 1565 | |
| 1566 | #if DEBUG_MEMC_MULTI_ACK |
| 1567 | if(m_debug) |
| 1568 | std::cout << " <MEMC " << name() |
| 1569 | << " MULTI_ACK_UPT_CLEAR> Clear UPT entry " |
| 1570 | << std::dec << r_multi_ack_upt_index.read() << std::endl; |
| 1571 | #endif |
| 1572 | break; |
| 1573 | } |
| 1574 | ///////////////////////// |
| 1575 | case MULTI_ACK_WRITE_RSP: // Post a response request to TGT_RSP FSM |
| 1576 | // Wait if pending request |
| 1577 | { |
| 1578 | if ( r_multi_ack_to_tgt_rsp_req.read() ) break; |
| 1579 | |
| 1580 | r_multi_ack_to_tgt_rsp_req = true; |
| 1581 | r_multi_ack_to_tgt_rsp_srcid = r_multi_ack_srcid.read(); |
| 1582 | r_multi_ack_to_tgt_rsp_trdid = r_multi_ack_trdid.read(); |
| 1583 | r_multi_ack_to_tgt_rsp_pktid = r_multi_ack_pktid.read(); |
| 1584 | r_multi_ack_fsm = MULTI_ACK_IDLE; |
| 1585 | |
| 1586 | #if DEBUG_MEMC_MULTI_ACK |
| 1587 | if(m_debug) |
| 1588 | std::cout << " <MEMC " << name() << " MULTI_ACK_WRITE_RSP>" |
| 1589 | << " Request TGT_RSP FSM to send a response to srcid " |
| 1590 | << std::hex << r_multi_ack_srcid.read() << std::endl; |
| 1591 | #endif |
| 1592 | break; |
| 1593 | } |
| 1594 | } // end switch r_multi_ack_fsm |
| 1595 | |
| 1596 | //////////////////////////////////////////////////////////////////////////////////// |
| 1597 | // CONFIG FSM |
| 1598 | //////////////////////////////////////////////////////////////////////////////////// |
| 1599 | // The CONFIG FSM handles the VCI configuration requests (INVAL & SYNC). |
| 1600 | // The target buffer can have any size, and there is one single command for |
| 1601 | // all cache lines covered by the target buffer. |
| 1602 | // |
| 1603 | // An INVAL or SYNC configuration operation is defined by the following registers: |
| 1604 | // - bool r_config_cmd : INVAL / SYNC / NOP |
| 1605 | // - uint64_t r_config_address : buffer base address |
| 1606 | // - uint32_t r_config_cmd_lines : number of lines to be handled |
| 1607 | // - uint32_t r_config_rsp_lines : number of lines not completed |
| 1608 | // |
| 1609 | // For both INVAL and SYNC commands, the CONFIG FSM contains the loop handling |
| 1610 | // all cache lines covered by the buffer. The various lines of a given buffer |
| 1611 | // can be pipelined: the CONFIG FSM does not wait the response for line (n) to send |
| 1612 | // the command for line (n+1). It decrements the r_config_cmd_lines counter until |
| 1613 | // the last request has been registered in TRT (for a SYNC), or in IVT (for an INVAL). |
| 1614 | // |
| 1615 | // - INVAL request: |
| 1616 | // For each line, it access to the DIR. |
| 1617 | // In case of miss, it does nothing, and a response is requested to TGT_RSP FSM. |
| 1618 | // In case of hit, with no copies in L1 caches, the line is invalidated and |
| 1619 | // a response is requested to TGT_RSP FSM. |
| 1620 | // If there is copies, a multi-inval, or a broadcast-inval coherence transaction |
| 1621 | // is launched and registered in UPT. The multi-inval transaction completion |
| 1622 | // is signaled by the CLEANUP FSM by decrementing the r_config_rsp_lines counter. |
| 1623 | // The CONFIG INVAL response is sent only when the last line has been invalidated. |
| 1624 | // TODO : The target buffer address must be aligned on a cache line boundary. |
| 1625 | // This constraint can be released, but it requires to make 2 PUT transactions |
| 1626 | // for the first and the last line... |
| 1627 | // |
| 1628 | // - SYNC request: |
| 1629 | // For each line, it access to the DIR. |
| 1630 | // In case of miss, it does nothing, and a response is requested to TGT_RSP FSM. |
| 1631 | // In case of hit, a PUT transaction is registered in TRT and a request is sent |
| 1632 | // to IXR_CMD FSM. The IXR_RSP FSM decrements the r_config_rsp_lines counter |
| 1633 | // when a PUT response is received. |
| 1634 | // The CONFIG SYNC response is sent only when the last PUT response is received. |
| 1635 | // |
| 1636 | // From the software point of view, a configuration request is a sequence |
| 1637 | // of 6 atomic accesses in an uncached segment. A dedicated lock is used |
| 1638 | // to handle only one configuration command at a given time: |
| 1639 | // - Read MEMC_LOCK : Get the lock |
| 1640 | // - Write MEMC_ADDR_LO : Set the buffer address LSB |
| 1641 | // - Write MEMC_ADDR_HI : Set the buffer address MSB |
| 1642 | // - Write MEMC_BUF_LENGTH : set buffer length (bytes) |
| 1643 | // - Write MEMC_CMD_TYPE : launch the actual operation |
| 1644 | // - WRITE MEMC_LOCK : release the lock |
| 1645 | //////////////////////////////////////////////////////////////////////////////////// |
| 1646 | |
| 1647 | //std::cout << std::endl << "config_fsm" << std::endl; |
| 1648 | |
| 1649 | switch( r_config_fsm.read() ) |
1133 | | r_tgt_cmd_fsm = TGT_CMD_ERROR; |
1134 | | } |
1135 | | else if ( config ) /////////// configuration command |
| 1651 | ///////////////// |
| 1652 | case CONFIG_IDLE: // waiting a config request |
| 1653 | { |
| 1654 | if ( r_config_cmd.read() != MEMC_CMD_NOP ) |
| 1655 | { |
| 1656 | r_config_fsm = CONFIG_LOOP; |
| 1657 | |
| 1658 | #if DEBUG_MEMC_CONFIG |
| 1659 | if(m_debug) |
| 1660 | std::cout << " <MEMC " << name() << " CONFIG_IDLE> Config Request received" |
| 1661 | << " / address = " << std::hex << r_config_address.read() |
| 1662 | << " / lines = " << std::dec << r_config_cmd_lines.read() |
| 1663 | << " / type = " << r_config_cmd.read() << std::endl; |
| 1664 | #endif |
| 1665 | } |
| 1666 | break; |
| 1667 | } |
| 1668 | ///////////////// |
| 1669 | case CONFIG_LOOP: // test if last line to be handled |
| 1670 | { |
| 1671 | if ( r_config_cmd_lines.read() == 0 ) |
| 1672 | { |
| 1673 | r_config_cmd = MEMC_CMD_NOP; |
| 1674 | r_config_fsm = CONFIG_WAIT; |
| 1675 | } |
| 1676 | else |
| 1677 | { |
| 1678 | r_config_fsm = CONFIG_DIR_REQ; |
| 1679 | } |
| 1680 | |
| 1681 | #if DEBUG_MEMC_CONFIG |
| 1682 | if(m_debug) |
| 1683 | std::cout << " <MEMC " << name() << " CONFIG_LOOP>" |
| 1684 | << " / address = " << std::hex << r_config_address.read() |
| 1685 | << " / lines not handled = " << std::dec << r_config_cmd_lines.read() |
| 1686 | << " / command = " << r_config_cmd.read() << std::endl; |
| 1687 | #endif |
| 1688 | break; |
| 1689 | } |
| 1690 | ///////////////// |
| 1691 | case CONFIG_WAIT: // wait completion (last response) |
| 1692 | { |
| 1693 | if ( r_config_rsp_lines.read() == 0 ) // last response received |
| 1694 | { |
| 1695 | r_config_fsm = CONFIG_RSP; |
| 1696 | } |
| 1697 | |
| 1698 | #if DEBUG_MEMC_CONFIG |
| 1699 | if(m_debug) |
| 1700 | std::cout << " <MEMC " << name() << " CONFIG_WAIT>" |
| 1701 | << " / lines to do = " << std::dec << r_config_rsp_lines.read() << std::endl; |
| 1702 | #endif |
| 1703 | break; |
| 1704 | } |
| 1705 | //////////////// |
| 1706 | case CONFIG_RSP: // request TGT_RSP FSM to return response |
| 1707 | { |
| 1708 | if ( not r_config_to_tgt_rsp_req.read() ) |
| 1709 | { |
| 1710 | r_config_to_tgt_rsp_srcid = r_config_srcid.read(); |
| 1711 | r_config_to_tgt_rsp_trdid = r_config_trdid.read(); |
| 1712 | r_config_to_tgt_rsp_pktid = r_config_pktid.read(); |
| 1713 | r_config_to_tgt_rsp_error = false; |
| 1714 | r_config_to_tgt_rsp_req = true; |
| 1715 | r_config_fsm = CONFIG_IDLE; |
| 1716 | |
| 1717 | #if DEBUG_MEMC_CONFIG |
| 1718 | if(m_debug) |
| 1719 | std::cout << " <MEMC " << name() << " CONFIG_RSP> Request TGT_RSP FSM to return response:" |
| 1720 | << " error = " << r_config_to_tgt_rsp_error.read() |
| 1721 | << " / rsrcid = " << std::hex << r_config_srcid.read() |
| 1722 | << " / rtrdid = " << std::hex << r_config_trdid.read() |
| 1723 | << " / rpktid = " << std::hex << r_config_pktid.read() << std::endl; |
| 1724 | #endif |
| 1725 | } |
| 1726 | break; |
| 1727 | |
| 1728 | } |
| 1729 | //////////////////// |
| 1730 | case CONFIG_DIR_REQ: // Request directory lock |
| 1731 | { |
| 1732 | if ( r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG ) |
| 1733 | { |
| 1734 | r_config_fsm = CONFIG_DIR_ACCESS; |
| 1735 | } |
| 1736 | |
| 1737 | #if DEBUG_MEMC_CONFIG |
| 1738 | if(m_debug) |
| 1739 | std::cout << " <MEMC " << name() << " CONFIG_DIR_REQ>" |
| 1740 | << " Request DIR access" << std::endl; |
| 1741 | #endif |
| 1742 | break; |
| 1743 | } |
| 1744 | /////////////////////// |
| 1745 | case CONFIG_DIR_ACCESS: // Access directory and decode config command |
| 1746 | { |
| 1747 | assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and |
| 1748 | "MEMC ERROR in CONFIG_DIR_ACCESS state: bad DIR allocation"); |
| 1749 | |
| 1750 | size_t way = 0; |
| 1751 | DirectoryEntry entry = m_cache_directory.read(r_config_address.read(), way); |
| 1752 | |
| 1753 | if ( entry.valid and // hit & inval command |
| 1754 | (r_config_cmd.read() == MEMC_CMD_INVAL) ) |
| 1755 | { |
| 1756 | r_config_dir_way = way; |
| 1757 | r_config_dir_copy_inst = entry.owner.inst; |
| 1758 | r_config_dir_copy_srcid = entry.owner.srcid; |
| 1759 | r_config_dir_is_cnt = entry.is_cnt; |
| 1760 | r_config_dir_lock = entry.lock; |
| 1761 | r_config_dir_count = entry.count; |
| 1762 | r_config_dir_ptr = entry.ptr; |
| 1763 | |
| 1764 | r_config_fsm = CONFIG_IVT_LOCK; |
| 1765 | } |
| 1766 | else if ( entry.valid and // hit & sync command |
| 1767 | entry.dirty and |
| 1768 | (r_config_cmd.read() == MEMC_CMD_SYNC) ) |
| 1769 | { |
| 1770 | r_config_fsm = CONFIG_TRT_LOCK; |
| 1771 | } |
| 1772 | else // miss : return to LOOP |
| 1773 | { |
| 1774 | r_config_cmd_lines = r_config_cmd_lines.read() - 1; |
| 1775 | r_config_rsp_lines = r_config_rsp_lines.read() - 1; |
| 1776 | r_config_cmd_lines = r_config_cmd_lines.read() - 1; |
| 1777 | r_config_address = r_config_address.read() + (m_words<<2); |
| 1778 | r_config_fsm = CONFIG_LOOP; |
| 1779 | } |
| 1780 | |
| 1781 | #if DEBUG_MEMC_CONFIG |
| 1782 | if(m_debug) |
| 1783 | std::cout << " <MEMC " << name() << " CONFIG_DIR_ACCESS> Accessing directory: " |
| 1784 | << " address = " << std::hex << r_config_address.read() |
| 1785 | << " / hit = " << std::dec << entry.valid |
| 1786 | << " / dirty = " << entry.dirty |
| 1787 | << " / count = " << entry.count |
| 1788 | << " / is_cnt = " << entry.is_cnt << std::endl; |
| 1789 | #endif |
| 1790 | break; |
| 1791 | } |
| 1792 | ///////////////////// |
| 1793 | case CONFIG_TRT_LOCK: // enter this state in case of SYNC command |
| 1794 | // to a dirty cache line |
| 1795 | // keep DIR lock, and try to get TRT lock |
| 1796 | // return to LOOP state if TRT full |
| 1797 | // reset dirty bit in DIR and register a PUT |
| 1798 | // trabsaction in TRT if not full. |
| 1799 | { |
| 1800 | assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and |
| 1801 | "MEMC ERROR in CONFIG_TRT_LOCK state: bad DIR allocation"); |
| 1802 | |
| 1803 | if ( r_alloc_trt_fsm.read() == ALLOC_TRT_CONFIG ) |
| 1804 | { |
| 1805 | size_t index = 0; |
| 1806 | bool wok = not m_trt.full(index); |
| 1807 | |
| 1808 | if ( not wok ) |
| 1809 | { |
| 1810 | r_config_fsm = CONFIG_LOOP; |
| 1811 | } |
| 1812 | else |
| 1813 | { |
| 1814 | size_t way = r_config_dir_way.read(); |
| 1815 | size_t set = m_y[r_config_address.read()]; |
| 1816 | |
| 1817 | // reset dirty bit in DIR |
| 1818 | DirectoryEntry entry; |
| 1819 | entry.valid = true; |
| 1820 | entry.dirty = false; |
| 1821 | entry.tag = m_z[r_config_address.read()]; |
| 1822 | entry.is_cnt = r_config_dir_is_cnt.read(); |
| 1823 | entry.lock = r_config_dir_lock.read(); |
| 1824 | entry.ptr = r_config_dir_ptr.read(); |
| 1825 | entry.count = r_config_dir_count.read(); |
| 1826 | entry.owner.inst = r_config_dir_copy_inst.read(); |
| 1827 | entry.owner.srcid = r_config_dir_copy_srcid.read(); |
| 1828 | m_cache_directory.write( set, |
| 1829 | way, |
| 1830 | entry ); |
| 1831 | |
| 1832 | r_config_trt_index = index; |
| 1833 | r_config_fsm = CONFIG_TRT_SET; |
| 1834 | } |
| 1835 | |
| 1836 | #if DEBUG_MEMC_CONFIG |
| 1837 | if(m_debug) |
| 1838 | std::cout << " <MEMC " << name() << " CONFIG_TRT_LOCK> Access TRT: " |
| 1839 | << " wok = " << std::dec << wok |
| 1840 | << " index = " << index << std::endl; |
| 1841 | #endif |
| 1842 | } |
| 1843 | break; |
| 1844 | } |
| 1845 | //////////////////// |
| 1846 | case CONFIG_TRT_SET: // read data in cache |
| 1847 | // and post a PUT request in TRT |
| 1848 | { |
| 1849 | assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and |
| 1850 | "MEMC ERROR in CONFIG_TRT_SET state: bad DIR allocation"); |
| 1851 | |
| 1852 | assert( (r_alloc_trt_fsm.read() == ALLOC_TRT_CONFIG) and |
| 1853 | "MEMC ERROR in CONFIG_TRT_SET state: bad TRT allocation"); |
| 1854 | |
| 1855 | // read data into cache |
| 1856 | size_t way = r_config_dir_way.read(); |
| 1857 | size_t set = m_y[r_config_address.read()]; |
| 1858 | |
| 1859 | sc_signal<data_t> config_data[16]; |
| 1860 | m_cache_data.read_line( way, |
| 1861 | set, |
| 1862 | config_data ); |
| 1863 | |
| 1864 | // post a PUT request in TRT |
| 1865 | std::vector<data_t> data_vector; |
| 1866 | data_vector.clear(); |
| 1867 | for(size_t i=0; i<m_words; i++) data_vector.push_back(config_data[i].read()); |
| 1868 | m_trt.set( r_config_trt_index.read(), |
| 1869 | false, // PUT |
| 1870 | m_nline[r_config_address.read()], // nline |
| 1871 | 0, // srcid: unused |
| 1872 | 0, // trdid: unused |
| 1873 | 0, // pktid: unused |
| 1874 | false, // not proc_read |
| 1875 | 0, // read_length: unused |
| 1876 | 0, // word_index: unused |
| 1877 | std::vector<be_t>(m_words,0xF), |
| 1878 | data_vector); |
| 1879 | |
| 1880 | #if DEBUG_MEMC_CONFIG |
| 1881 | if(m_debug) |
| 1882 | std::cout << " <MEMC " << name() << " CONFIG_TRT_SET> PUT request in TRT:" |
| 1883 | << " address = " << std::hex << r_config_address.read() |
| 1884 | << " index = " << std::dec << r_config_trt_index.read() << std::endl; |
| 1885 | #endif |
| 1886 | break; |
| 1887 | } |
| 1888 | //////////////////// |
| 1889 | case CONFIG_PUT_REQ: // PUT request to IXR_CMD_FSM |
| 1890 | { |
| 1891 | if ( not r_config_to_ixr_cmd_req.read() ) |
| 1892 | { |
| 1893 | r_config_to_ixr_cmd_req = true; |
| 1894 | r_config_to_ixr_cmd_index = r_config_trt_index.read(); |
| 1895 | |
| 1896 | // prepare next iteration |
| 1897 | r_config_cmd_lines = r_config_cmd_lines.read() - 1; |
| 1898 | r_config_address = r_config_address.read() + (m_words<<2); |
| 1899 | r_config_fsm = CONFIG_LOOP; |
| 1900 | |
| 1901 | #if DEBUG_MEMC_CONFIG |
| 1902 | if(m_debug) |
| 1903 | std::cout << " <MEMC " << name() << " CONFIG_PUT_REQ> PUT request to IXR_CMD_FSM" |
| 1904 | << " / address = " << std::hex << r_config_address.read() << std::endl; |
| 1905 | #endif |
| 1906 | } |
| 1907 | break; |
| 1908 | } |
| 1909 | ///////////////////// |
| 1910 | case CONFIG_IVT_LOCK: // enter this state in case of INVAL command |
| 1911 | // Keep DIR lock and Try to get IVT lock. |
| 1912 | // Return to LOOP state if IVT full. |
| 1913 | // Register inval in IVT, and invalidate the |
| 1914 | // directory if IVT not full. |
| 1915 | { |
| 1916 | assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and |
| 1917 | "MEMC ERROR in CONFIG_IVT_LOCK state: bad DIR allocation"); |
| 1918 | |
| 1919 | if ( r_alloc_ivt_fsm.read() == ALLOC_IVT_CONFIG ) |
| 1920 | { |
| 1921 | size_t set = m_y[(addr_t)(r_config_address.read())]; |
| 1922 | size_t way = r_config_dir_way.read(); |
| 1923 | |
| 1924 | if ( r_config_dir_count.read() == 0 ) // inval DIR and return to LOOP |
| 1925 | { |
| 1926 | m_cache_directory.inval( way, set ); |
| 1927 | r_config_cmd_lines = r_config_cmd_lines.read() - 1; |
| 1928 | r_config_rsp_lines = r_config_rsp_lines.read() - 1; |
| 1929 | r_config_address = r_config_address.read() + (m_words<<2); |
| 1930 | r_config_fsm = CONFIG_LOOP; |
| 1931 | |
| 1932 | #if DEBUG_MEMC_CONFIG |
| 1933 | if(m_debug) |
| 1934 | std::cout << " <MEMC " << name() << " CONFIG_IVT_LOCK>" |
| 1935 | << " No copies in L1 : inval DIR entry" << std::endl; |
| 1936 | #endif |
| 1937 | } |
| 1938 | else // try to register inval in IVT |
| 1939 | { |
| 1940 | bool wok = false; |
| 1941 | size_t index = 0; |
| 1942 | bool broadcast = r_config_dir_is_cnt.read(); |
| 1943 | size_t srcid = r_config_srcid.read(); |
| 1944 | size_t trdid = r_config_trdid.read(); |
| 1945 | size_t pktid = r_config_pktid.read(); |
| 1946 | addr_t nline = m_nline[(addr_t)(r_config_address.read())]; |
| 1947 | size_t nb_copies = r_config_dir_count.read(); |
| 1948 | |
| 1949 | wok = m_ivt.set(false, // it's an inval transaction |
| 1950 | broadcast, |
| 1951 | false, // no response required |
| 1952 | true, // acknowledge required |
| 1953 | srcid, |
| 1954 | trdid, |
| 1955 | pktid, |
| 1956 | nline, |
| 1957 | nb_copies, |
| 1958 | index); |
| 1959 | |
| 1960 | if ( wok ) // IVT success => inval DIR slot |
| 1961 | { |
| 1962 | m_cache_directory.inval( way, set ); |
| 1963 | r_config_ivt_index = index; |
| 1964 | if ( broadcast ) r_config_fsm = CONFIG_BC_SEND; |
| 1965 | else r_config_fsm = CONFIG_INVAL_SEND; |
| 1966 | |
| 1967 | #if DEBUG_MEMC_CONFIG |
| 1968 | if(m_debug) |
| 1969 | std::cout << " <MEMC " << name() << " CONFIG_IVT_LOCK>" |
| 1970 | << " Inval DIR entry and register inval in IVT" |
| 1971 | << " / index = " << std::dec << index |
| 1972 | << " / broadcast = " << broadcast << std::endl; |
| 1973 | #endif |
| 1974 | } |
| 1975 | else // IVT full => release both DIR and IVT locks |
| 1976 | { |
| 1977 | r_config_fsm = CONFIG_LOOP; |
| 1978 | |
| 1979 | #if DEBUG_MEMC_CONFIG |
| 1980 | if(m_debug) |
| 1981 | std::cout << " <MEMC " << name() << " CONFIG_IVT_LOCK>" |
| 1982 | << " IVT full : release DIR & IVT locks and retry" << std::endl; |
| 1983 | #endif |
| 1984 | } |
| 1985 | } |
| 1986 | } |
| 1987 | break; |
| 1988 | } |
| 1989 | //////////////////// |
| 1990 | case CONFIG_BC_SEND: // Post a broadcast inval request to CC_SEND FSM |
| 1991 | { |
| 1992 | if( not r_config_to_cc_send_multi_req.read() and |
| 1993 | not r_config_to_cc_send_brdcast_req.read() ) |
| 1994 | { |
| 1995 | // post bc inval request |
| 1996 | r_config_to_cc_send_multi_req = false; |
| 1997 | r_config_to_cc_send_brdcast_req = true; |
| 1998 | r_config_to_cc_send_trdid = r_config_ivt_index.read(); |
| 1999 | r_config_to_cc_send_nline = m_nline[(addr_t)(r_config_address.read())]; |
| 2000 | |
| 2001 | // prepare next iteration |
| 2002 | r_config_cmd_lines = r_config_cmd_lines.read() - 1; |
| 2003 | r_config_address = r_config_address.read() + (m_words<<2); |
| 2004 | r_config_fsm = CONFIG_LOOP; |
| 2005 | |
| 2006 | #if DEBUG_MEMC_CONFIG |
| 2007 | if(m_debug) |
| 2008 | std::cout << " <MEMC " << name() << " CONFIG_BC_SEND>" |
| 2009 | << " Post a broadcast inval request to CC_SEND FSM" |
| 2010 | << " / address = " << r_config_address.read() <<std::endl; |
| 2011 | #endif |
| 2012 | } |
| 2013 | break; |
| 2014 | } |
| 2015 | /////////////////////// |
| 2016 | case CONFIG_INVAL_SEND: // Post a multi inval request to CC_SEND FSM |
| 2017 | { |
| 2018 | if( not r_config_to_cc_send_multi_req.read() and |
| 2019 | not r_config_to_cc_send_brdcast_req.read() ) |
| 2020 | { |
| 2021 | // post multi inval request |
| 2022 | r_config_to_cc_send_multi_req = true; |
| 2023 | r_config_to_cc_send_brdcast_req = false; |
| 2024 | r_config_to_cc_send_trdid = r_config_ivt_index.read(); |
| 2025 | r_config_to_cc_send_nline = m_nline[(addr_t)(r_config_address.read())]; |
| 2026 | |
| 2027 | // post data into FIFO |
| 2028 | config_to_cc_send_fifo_srcid = r_config_dir_copy_srcid.read(); |
| 2029 | config_to_cc_send_fifo_inst = r_config_dir_copy_inst.read(); |
| 2030 | config_to_cc_send_fifo_put = true; |
| 2031 | |
| 2032 | if ( r_config_dir_count.read() == 1 ) // one copy |
| 2033 | { |
| 2034 | // prepare next iteration |
| 2035 | r_config_cmd_lines = r_config_cmd_lines.read() - 1; |
| 2036 | r_config_address = r_config_address.read() + (m_words<<2); |
| 2037 | r_config_fsm = CONFIG_LOOP; |
| 2038 | } |
| 2039 | else // several copies |
| 2040 | { |
| 2041 | r_config_fsm = CONFIG_HEAP_REQ; |
| 2042 | } |
| 2043 | |
| 2044 | #if DEBUG_MEMC_CONFIG |
| 2045 | if(m_debug) |
| 2046 | std::cout << " <MEMC " << name() << " CONFIG_INVAL_SEND>" |
| 2047 | << " Post multi inval request to CC_SEND FSM" |
| 2048 | << " / address = " << std::hex << r_config_address.read() |
| 2049 | << " / copy = " << r_config_dir_copy_srcid.read() |
| 2050 | << " / inst = " << std::dec << r_config_dir_copy_inst.read() << std::endl; |
| 2051 | #endif |
| 2052 | } |
| 2053 | break; |
| 2054 | } |
| 2055 | ///////////////////// |
| 2056 | case CONFIG_HEAP_REQ: // Try to get access to Heap |
| 2057 | { |
| 2058 | if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CONFIG ) |
| 2059 | { |
| 2060 | r_config_fsm = CONFIG_HEAP_SCAN; |
| 2061 | r_config_heap_next = r_config_dir_ptr.read(); |
| 2062 | } |
| 2063 | |
| 2064 | #if DEBUG_MEMC_CONFIG |
| 2065 | if(m_debug) |
| 2066 | std::cout << " <MEMC " << name() << " CONFIG_HEAP_REQ>" |
| 2067 | << " Requesting HEAP lock" << std::endl; |
| 2068 | #endif |
| 2069 | break; |
| 2070 | } |
| 2071 | ////////////////////// |
| 2072 | case CONFIG_HEAP_SCAN: // scan HEAP and send inval to CC_SEND FSM |
| 2073 | { |
| 2074 | HeapEntry entry = m_heap.read( r_config_heap_next.read() ); |
| 2075 | bool last_copy = (entry.next == r_config_heap_next.read()); |
| 2076 | |
| 2077 | config_to_cc_send_fifo_srcid = entry.owner.srcid; |
| 2078 | config_to_cc_send_fifo_inst = entry.owner.inst; |
| 2079 | // config_to_cc_send_fifo_last = last_copy; |
| 2080 | config_to_cc_send_fifo_put = true; |
| 2081 | |
| 2082 | if ( m_config_to_cc_send_inst_fifo.wok() ) // inval request accepted |
| 2083 | { |
| 2084 | r_config_heap_next = entry.next; |
| 2085 | if ( last_copy ) r_config_fsm = CONFIG_HEAP_LAST; |
| 2086 | } |
| 2087 | |
| 2088 | #if DEBUG_MEMC_CONFIG |
| 2089 | if(m_debug) |
| 2090 | std::cout << " <MEMC " << name() << " CONFIG_HEAP_SCAN>" |
| 2091 | << " Post multi inval request to CC_SEND FSM" |
| 2092 | << " / address = " << std::hex << r_config_address.read() |
| 2093 | << " / copy = " << entry.owner.srcid |
| 2094 | << " / inst = " << std::dec << entry.owner.inst << std::endl; |
| 2095 | #endif |
| 2096 | break; |
| 2097 | } |
| 2098 | ////////////////////// |
| 2099 | case CONFIG_HEAP_LAST: // HEAP housekeeping |
| 2100 | { |
| 2101 | size_t free_pointer = m_heap.next_free_ptr(); |
| 2102 | HeapEntry last_entry; |
| 2103 | last_entry.owner.srcid = 0; |
| 2104 | last_entry.owner.inst = false; |
| 2105 | |
| 2106 | if ( m_heap.is_full() ) |
| 2107 | { |
| 2108 | last_entry.next = r_config_dir_ptr.read(); |
| 2109 | m_heap.unset_full(); |
| 2110 | } |
| 2111 | else |
| 2112 | { |
| 2113 | last_entry.next = free_pointer; |
| 2114 | } |
| 2115 | |
| 2116 | m_heap.write_free_ptr( r_config_dir_ptr.read() ); |
| 2117 | m_heap.write( r_config_heap_next.read(), last_entry ); |
| 2118 | |
| 2119 | // prepare next iteration |
| 2120 | r_config_cmd_lines = r_config_cmd_lines.read() - 1; |
| 2121 | r_config_address = r_config_address.read() + (m_words<<2); |
| 2122 | r_config_fsm = CONFIG_LOOP; |
| 2123 | |
| 2124 | #if DEBUG_MEMC_CONFIG |
| 2125 | if(m_debug) |
| 2126 | std::cout << " <MEMC " << name() << " CONFIG_HEAP_LAST>" |
| 2127 | << " Heap housekeeping" << std::endl; |
| 2128 | #endif |
| 2129 | break; |
| 2130 | } |
| 2131 | } // end switch r_config_fsm |
| 2132 | |
| 2133 | //////////////////////////////////////////////////////////////////////////////////// |
| 2134 | // READ FSM |
| 2135 | //////////////////////////////////////////////////////////////////////////////////// |
| 2136 | // The READ FSM controls the VCI read and ll requests. |
| 2137 | // It takes the lock protecting the cache directory to check the cache line status: |
| 2138 | // - In case of HIT |
| 2139 | // The fsm copies the data (one line, or one single word) |
| 2140 | // in the r_read_to_tgt_rsp buffer. It waits if this buffer is not empty. |
| 2141 | // The requesting initiator is registered in the cache directory. |
| 2142 | // If the number of copy is larger than 1, the new copy is registered |
| 2143 | // in the HEAP. |
| 2144 | // If the number of copy is larger than the threshold, the HEAP is cleared, |
| 2145 | // and the corresponding line switches to the counter mode. |
| 2146 | // - In case of MISS |
| 2147 | // The READ fsm takes the lock protecting the transaction tab. |
| 2148 | // If a read transaction to the XRAM for this line already exists, |
| 2149 | // or if the transaction tab is full, the fsm is stalled. |
| 2150 | // If a TRT entry is free, the READ request is registered in TRT, |
| 2151 | // it is consumed in the request FIFO, and transmited to the IXR_CMD FSM. |
| 2152 | // The READ FSM returns in the IDLE state as the read transaction will be |
| 2153 | // completed when the missing line will be received. |
| 2154 | //////////////////////////////////////////////////////////////////////////////////// |
| 2155 | |
| 2156 | //std::cout << std::endl << "read_fsm" << std::endl; |
| 2157 | |
| 2158 | switch(r_read_fsm.read()) |
1137 | | if ( not p_vci_tgt.eop.read() ) r_tgt_cmd_fsm = TGT_CMD_ERROR; |
1138 | | else r_tgt_cmd_fsm = TGT_CMD_CONFIG; |
1139 | | } |
1140 | | else //////////// memory access |
1141 | | { |
1142 | | if ( p_vci_tgt.cmd.read() == vci_param_int::CMD_READ ) |
1143 | | { |
1144 | | // check that the pktid is either : |
1145 | | // TYPE_READ_DATA_UNC |
1146 | | // TYPE_READ_DATA_MISS |
1147 | | // TYPE_READ_INS_UNC |
1148 | | // TYPE_READ_INS_MISS |
1149 | | // ==> bit2 must be zero with the TSAR encoding |
1150 | | // ==> mask = 0b0100 = 0x4 |
1151 | | assert( ((p_vci_tgt.pktid.read() & 0x4) == 0x0) and |
1152 | | "The type specified in the pktid field is incompatible with the READ CMD"); |
1153 | | r_tgt_cmd_fsm = TGT_CMD_READ; |
1154 | | } |
1155 | | else if(p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE) |
1156 | | { |
1157 | | // check that the pktid is TYPE_WRITE |
1158 | | // ==> TYPE_WRITE = X100 with the TSAR encoding |
1159 | | // ==> mask = 0b0111 = 0x7 |
1160 | | assert(((p_vci_tgt.pktid.read() & 0x7) == 0x4) and |
1161 | | "The type specified in the pktid field is incompatible with the WRITE CMD"); |
1162 | | r_tgt_cmd_fsm = TGT_CMD_WRITE; |
1163 | | } |
1164 | | else if(p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ) |
1165 | | { |
1166 | | // check that the pktid is TYPE_LL |
1167 | | // ==> TYPE_LL = X110 with the TSAR encoding |
1168 | | // ==> mask = 0b0111 = 0x7 |
1169 | | assert(((p_vci_tgt.pktid.read() & 0x7) == 0x6) and |
1170 | | "The type specified in the pktid field is incompatible with the LL CMD"); |
1171 | | r_tgt_cmd_fsm = TGT_CMD_READ; |
1172 | | } |
1173 | | else if(p_vci_tgt.cmd.read() == vci_param_int::CMD_NOP) |
1174 | | { |
1175 | | // check that the pktid is either : |
1176 | | // TYPE_CAS |
1177 | | // TYPE_SC |
1178 | | // ==> TYPE_CAS = X101 with the TSAR encoding |
1179 | | // ==> TYPE_SC = X111 with the TSAR encoding |
1180 | | // ==> mask = 0b0101 = 0x5 |
1181 | | assert(((p_vci_tgt.pktid.read() & 0x5) == 0x5) and |
1182 | | "The type specified in the pktid field is incompatible with the NOP CMD"); |
1183 | | |
1184 | | if((p_vci_tgt.pktid.read() & 0x7) == TYPE_CAS) r_tgt_cmd_fsm = TGT_CMD_CAS; |
1185 | | else r_tgt_cmd_fsm = TGT_CMD_WRITE; |
1186 | | } |
1187 | | else |
1188 | | { |
1189 | | r_tgt_cmd_fsm = TGT_CMD_ERROR; |
1190 | | } |
1191 | | } |
1192 | | } |
1193 | | break; |
1194 | | |
1195 | | /////////////////// |
1196 | | case TGT_CMD_ERROR: // response error must be sent |
1197 | | |
1198 | | // wait if pending request |
1199 | | if(r_tgt_cmd_to_tgt_rsp_req.read()) break; |
1200 | | |
1201 | | // consume all the command packet flits before sending response error |
1202 | | if ( p_vci_tgt.cmdval and p_vci_tgt.eop ) |
1203 | | { |
1204 | | r_tgt_cmd_to_tgt_rsp_req = true; |
1205 | | r_tgt_cmd_to_tgt_rsp_error = 1; |
1206 | | r_tgt_cmd_fsm = TGT_CMD_IDLE; |
1207 | | |
1208 | | #if DEBUG_MEMC_TGT_CMD |
1209 | | if(m_debug) |
1210 | | std::cout << " <MEMC " << name() |
1211 | | << " TGT_CMD_ERROR> Segmentation violation:" |
1212 | | << " address = " << std::hex << p_vci_tgt.address.read() |
1213 | | << " / srcid = " << p_vci_tgt.srcid.read() |
1214 | | << " / trdid = " << p_vci_tgt.trdid.read() |
1215 | | << " / pktid = " << p_vci_tgt.pktid.read() |
1216 | | << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl; |
1217 | | #endif |
1218 | | |
1219 | | } |
1220 | | break; |
1221 | | |
1222 | | //////////////////// |
1223 | | case TGT_CMD_CONFIG: // execute config request and return response |
1224 | | { |
1225 | | addr_t seg_base = m_seg[m_seg_config]->baseAddress(); |
1226 | | addr_t address = p_vci_tgt.address.read(); |
1227 | | size_t cell = (address - seg_base)/vci_param_int::B; |
1228 | | |
1229 | | bool need_rsp; |
1230 | | size_t error; |
1231 | | uint32_t rdata = 0; // default value |
1232 | | uint32_t wdata = p_vci_tgt.wdata.read(); |
1233 | | |
1234 | | if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_READ) // get lock |
1235 | | and (cell == MEMC_LOCK) ) |
1236 | | { |
1237 | | rdata = (uint32_t)r_config_lock.read(); |
1238 | | need_rsp = true; |
1239 | | error = 0; |
1240 | | r_config_lock = true; |
1241 | | if ( rdata == 0 ) |
1242 | | { |
1243 | | r_tgt_cmd_srcid = p_vci_tgt.srcid.read(); |
1244 | | r_tgt_cmd_trdid = p_vci_tgt.trdid.read(); |
1245 | | r_tgt_cmd_pktid = p_vci_tgt.pktid.read(); |
1246 | | } |
1247 | | } |
1248 | | else if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE) // release lock |
1249 | | and (cell == MEMC_LOCK) |
1250 | | and (p_vci_tgt.srcid.read() == r_tgt_cmd_srcid.read()) ) |
1251 | | { |
1252 | | need_rsp = true; |
1253 | | error = 0; |
1254 | | r_config_lock = false; |
1255 | | } |
1256 | | else if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE) // set addr_lo |
1257 | | and (cell == MEMC_ADDR_LO) |
1258 | | and (p_vci_tgt.srcid.read() == r_tgt_cmd_srcid.read()) ) |
1259 | | { |
1260 | | assert( ((wdata % (m_words*vci_param_int::B)) == 0) and |
1261 | | "VCI_MEM_CACHE CONFIG ERROR: The buffer must be aligned on a cache line"); |
1262 | | |
1263 | | need_rsp = true; |
1264 | | error = 0; |
1265 | | r_config_address = (r_config_address.read() & 0xFFFFFFFF00000000LL) | |
1266 | | (addr_t)p_vci_tgt.wdata.read(); |
1267 | | } |
1268 | | else if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE) // set addr_hi |
1269 | | and (cell == MEMC_ADDR_HI) |
1270 | | and (p_vci_tgt.srcid.read() == r_tgt_cmd_srcid.read()) ) |
1271 | | |
1272 | | { |
1273 | | need_rsp = true; |
1274 | | error = 0; |
1275 | | r_config_address = (r_config_address.read() & 0x00000000FFFFFFFFLL) | |
1276 | | ((addr_t)p_vci_tgt.wdata.read())<<32; |
1277 | | } |
1278 | | else if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE) // set buf_lines |
1279 | | and (cell == MEMC_BUF_LENGTH) |
1280 | | and (p_vci_tgt.srcid.read() == r_tgt_cmd_srcid.read()) ) |
1281 | | { |
1282 | | need_rsp = true; |
1283 | | error = 0; |
1284 | | size_t lines = (size_t)(p_vci_tgt.wdata.read()/(m_words<<2)); |
1285 | | if ( r_config_address.read()%(m_words*4) ) lines++; |
1286 | | r_config_cmd_lines = lines; |
1287 | | r_config_rsp_lines = lines; |
1288 | | } |
1289 | | else if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE) // set cmd type |
1290 | | and (cell == MEMC_CMD_TYPE) |
1291 | | and (p_vci_tgt.srcid.read() == r_tgt_cmd_srcid.read()) ) |
1292 | | { |
1293 | | need_rsp = false; |
1294 | | error = 0; |
1295 | | r_config_cmd = p_vci_tgt.wdata.read(); |
1296 | | |
1297 | | // prepare delayed response from CONFIG FSM |
1298 | | r_config_srcid = p_vci_tgt.srcid.read(); |
1299 | | r_config_trdid = p_vci_tgt.trdid.read(); |
1300 | | r_config_pktid = p_vci_tgt.pktid.read(); |
1301 | | } |
1302 | | else |
1303 | | { |
1304 | | need_rsp = true; |
1305 | | error = 1; |
1306 | | } |
1307 | | |
1308 | | if ( need_rsp ) |
1309 | | { |
1310 | | // blocked if previous pending request to TGT_RSP FSM |
1311 | | if ( r_tgt_cmd_to_tgt_rsp_req.read() ) break; |
1312 | | |
1313 | | r_tgt_cmd_to_tgt_rsp_req = true; |
1314 | | r_tgt_cmd_to_tgt_rsp_error = error; |
1315 | | r_tgt_cmd_to_tgt_rsp_rdata = rdata; |
1316 | | r_tgt_cmd_fsm = TGT_CMD_IDLE; |
1317 | | } |
1318 | | else |
1319 | | { |
1320 | | r_tgt_cmd_fsm = TGT_CMD_IDLE; |
1321 | | } |
1322 | | |
1323 | | #if DEBUG_MEMC_TGT_CMD |
1324 | | if(m_debug) |
1325 | | std::cout << " <MEMC " << name() << " TGT_CMD_CONFIG> Configuration request:" |
1326 | | << " address = " << std::hex << p_vci_tgt.address.read() |
1327 | | << " / wdata = " << p_vci_tgt.wdata.read() |
1328 | | << " / need_rsp = " << need_rsp |
1329 | | << " / error = " << error << std::endl; |
1330 | | #endif |
1331 | | break; |
1332 | | } |
1333 | | ////////////////// |
1334 | | case TGT_CMD_READ: // Push a read request into read fifo |
1335 | | |
1336 | | // check that the read does not cross a cache line limit. |
1337 | | if ( ((m_x[(addr_t) p_vci_tgt.address.read()]+ (p_vci_tgt.plen.read() >>2)) > 16) and |
1338 | | (p_vci_tgt.cmd.read() != vci_param_int::CMD_LOCKED_READ)) |
1339 | | { |
1340 | | std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state" |
1341 | | << " illegal address/plen for VCI read command" << std::endl; |
1342 | | exit(0); |
1343 | | } |
1344 | | // check single flit |
1345 | | if(!p_vci_tgt.eop.read()) |
1346 | | { |
1347 | | std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state" |
1348 | | << " read command packet must contain one single flit" << std::endl; |
1349 | | exit(0); |
1350 | | } |
1351 | | // check plen for LL |
1352 | | if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ) and |
1353 | | (p_vci_tgt.plen.read() != 8) ) |
1354 | | { |
1355 | | std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state" |
1356 | | << " ll command packets must have a plen of 8" << std::endl; |
1357 | | exit(0); |
1358 | | } |
1359 | | |
1360 | | if ( p_vci_tgt.cmdval and m_cmd_read_addr_fifo.wok() ) |
1361 | | { |
1362 | | |
1363 | | #if DEBUG_MEMC_TGT_CMD |
1364 | | if(m_debug) |
1365 | | std::cout << " <MEMC " << name() << " TGT_CMD_READ> Push into read_fifo:" |
1366 | | << " address = " << std::hex << p_vci_tgt.address.read() |
1367 | | << " / srcid = " << p_vci_tgt.srcid.read() |
1368 | | << " / trdid = " << p_vci_tgt.trdid.read() |
1369 | | << " / pktid = " << p_vci_tgt.pktid.read() |
1370 | | << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl; |
1371 | | #endif |
1372 | | cmd_read_fifo_put = true; |
1373 | | if(p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ) m_cpt_ll++; |
1374 | | else m_cpt_read++; |
1375 | | r_tgt_cmd_fsm = TGT_CMD_IDLE; |
1376 | | } |
1377 | | break; |
1378 | | |
1379 | | /////////////////// |
1380 | | case TGT_CMD_WRITE: |
1381 | | if(p_vci_tgt.cmdval and m_cmd_write_addr_fifo.wok()) |
1382 | | { |
1383 | | |
1384 | | #if DEBUG_MEMC_TGT_CMD |
1385 | | if(m_debug) |
1386 | | std::cout << " <MEMC " << name() << " TGT_CMD_WRITE> Push into write_fifo:" |
1387 | | << " address = " << std::hex << p_vci_tgt.address.read() |
1388 | | << " / srcid = " << p_vci_tgt.srcid.read() |
1389 | | << " / trdid = " << p_vci_tgt.trdid.read() |
1390 | | << " / pktid = " << p_vci_tgt.pktid.read() |
1391 | | << " / wdata = " << p_vci_tgt.wdata.read() |
1392 | | << " / be = " << p_vci_tgt.be.read() |
1393 | | << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl; |
1394 | | #endif |
1395 | | cmd_write_fifo_put = true; |
1396 | | if(p_vci_tgt.eop) r_tgt_cmd_fsm = TGT_CMD_IDLE; |
1397 | | } |
1398 | | break; |
1399 | | |
1400 | | ///////////////// |
1401 | | case TGT_CMD_CAS: |
1402 | | if((p_vci_tgt.plen.read() != 8) and (p_vci_tgt.plen.read() != 16)) |
1403 | | { |
1404 | | std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_CAS state" |
1405 | | << "illegal format for CAS command " << std::endl; |
1406 | | exit(0); |
1407 | | } |
1408 | | |
1409 | | if(p_vci_tgt.cmdval and m_cmd_cas_addr_fifo.wok()) |
1410 | | { |
1411 | | |
1412 | | #if DEBUG_MEMC_TGT_CMD |
1413 | | if(m_debug) |
1414 | | std::cout << " <MEMC " << name() << " TGT_CMD_CAS> Pushing command into cmd_cas_fifo:" |
1415 | | << " address = " << std::hex << p_vci_tgt.address.read() |
1416 | | << " srcid = " << p_vci_tgt.srcid.read() |
1417 | | << " trdid = " << p_vci_tgt.trdid.read() |
1418 | | << " pktid = " << p_vci_tgt.pktid.read() |
1419 | | << " wdata = " << p_vci_tgt.wdata.read() |
1420 | | << " be = " << p_vci_tgt.be.read() |
1421 | | << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl; |
1422 | | #endif |
1423 | | cmd_cas_fifo_put = true; |
1424 | | if(p_vci_tgt.eop) r_tgt_cmd_fsm = TGT_CMD_IDLE; |
1425 | | } |
1426 | | break; |
1427 | | } // end switch tgt_cmd_fsm |
1428 | | |
1429 | | ///////////////////////////////////////////////////////////////////////// |
1430 | | // MULTI_ACK FSM |
1431 | | ///////////////////////////////////////////////////////////////////////// |
1432 | | // This FSM controls the response to the multicast update requests sent |
1433 | | // by the memory cache to the L1 caches and update the UPT. |
1434 | | // |
1435 | | // - The FSM decrements the proper entry in UPT, |
1436 | | // and clear the UPT entry when all responses have been received. |
1437 | | // - If required, it sends a request to the TGT_RSP FSM to complete |
1438 | | // a pending write transaction. |
1439 | | // |
1440 | | // All those multi-ack packets are one flit packet. |
1441 | | // The index in the UPT is defined in the TRDID field. |
1442 | | //////////////////////////////////////////////////////////////////////// |
1443 | | |
1444 | | //std::cout << std::endl << "multi_ack_fsm" << std::endl; |
1445 | | |
1446 | | switch(r_multi_ack_fsm.read()) |
1447 | | { |
1448 | | //////////////////// |
1449 | | case MULTI_ACK_IDLE: |
1450 | | { |
1451 | | bool multi_ack_fifo_rok = m_cc_receive_to_multi_ack_fifo.rok(); |
1452 | | |
1453 | | // No CC_RECEIVE FSM request and no WRITE FSM request |
1454 | | if( not multi_ack_fifo_rok and not r_write_to_multi_ack_req.read()) |
1455 | | break; |
1456 | | |
1457 | | uint8_t updt_index; |
1458 | | |
1459 | | // handling WRITE FSM request to decrement update table response |
1460 | | // counter if no CC_RECEIVE FSM request |
1461 | | if(not multi_ack_fifo_rok) |
1462 | | { |
1463 | | updt_index = r_write_to_multi_ack_upt_index.read(); |
1464 | | r_write_to_multi_ack_req = false; |
1465 | | } |
1466 | | // Handling CC_RECEIVE FSM request |
1467 | | else |
1468 | | { |
1469 | | uint64_t flit = m_cc_receive_to_multi_ack_fifo.read(); |
1470 | | updt_index = DspinDhccpParam::dspin_get(flit, |
1471 | | DspinDhccpParam::MULTI_ACK_UPDT_INDEX); |
1472 | | |
1473 | | cc_receive_to_multi_ack_fifo_get = true; |
1474 | | } |
1475 | | |
1476 | | assert((updt_index < m_upt.size()) and |
1477 | | "VCI_MEM_CACHE ERROR in MULTI_ACK_IDLE : " |
1478 | | "index too large for UPT"); |
1479 | | |
1480 | | r_multi_ack_upt_index = updt_index; |
1481 | | r_multi_ack_fsm = MULTI_ACK_UPT_LOCK; |
1482 | | |
1483 | | #if DEBUG_MEMC_MULTI_ACK |
1484 | | if(m_debug) |
1485 | | { |
1486 | | if (multi_ack_fifo_rok) |
1487 | | { |
1488 | | std::cout << " <MEMC " << name() |
1489 | | << " MULTI_ACK_IDLE> Response for UPT entry " |
1490 | | << (size_t)updt_index << std::endl; |
1491 | | } |
1492 | | else |
1493 | | { |
1494 | | std::cout << " <MEMC " << name() |
1495 | | << " MULTI_ACK_IDLE> Write FSM request to decrement UPT entry " |
1496 | | << updt_index << std::endl; |
1497 | | } |
1498 | | } |
1499 | | #endif |
1500 | | break; |
1501 | | } |
1502 | | |
1503 | | //////////////////////// |
1504 | | case MULTI_ACK_UPT_LOCK: |
1505 | | { |
1506 | | m_cpt_multi_ack_fsm_upt_lock++; |
1507 | | // get lock to the UPDATE table |
1508 | | if(r_alloc_upt_fsm.read() != ALLOC_UPT_MULTI_ACK) break; |
1509 | | |
1510 | | // decrement the number of expected responses |
1511 | | size_t count = 0; |
1512 | | bool valid = m_upt.decrement(r_multi_ack_upt_index.read(), count); |
1513 | | |
1514 | | |
1515 | | if(not valid) |
1516 | | { |
1517 | | std::cout << "VCI_MEM_CACHE ERROR " << name() |
1518 | | << " MULTI_ACK_UPT_LOCK state" << std::endl |
1519 | | << "unsuccessful access to decrement the UPT" << std::endl; |
1520 | | exit(0); |
1521 | | } |
1522 | | |
1523 | | if(count == 0) |
1524 | | { |
1525 | | r_multi_ack_fsm = MULTI_ACK_UPT_CLEAR; |
1526 | | } |
1527 | | else |
1528 | | { |
1529 | | r_multi_ack_fsm = MULTI_ACK_IDLE; |
1530 | | } |
1531 | | |
1532 | | #if DEBUG_MEMC_MULTI_ACK |
1533 | | if(m_debug) |
1534 | | std::cout << " <MEMC " << name() |
1535 | | << " MULTI_ACK_UPT_LOCK> Decrement the responses counter for UPT:" |
1536 | | << " entry = " << r_multi_ack_upt_index.read() |
1537 | | << " / rsp_count = " << std::dec << count << std::endl; |
1538 | | m_cpt_multi_ack_fsm_n_upt_lock++; |
1539 | | #endif |
1540 | | break; |
1541 | | } |
1542 | | |
1543 | | ///////////////////////// |
1544 | | case MULTI_ACK_UPT_CLEAR: // Clear UPT entry / Test if rsp or ack required |
1545 | | { |
1546 | | if(r_alloc_upt_fsm.read() != ALLOC_UPT_MULTI_ACK) |
1547 | | { |
1548 | | std::cout << "VCI_MEM_CACHE ERROR " << name() |
1549 | | << " MULTI_ACK_UPT_CLEAR state" |
1550 | | << " bad UPT allocation" << std::endl; |
1551 | | exit(0); |
1552 | | } |
1553 | | |
1554 | | r_multi_ack_srcid = m_upt.srcid(r_multi_ack_upt_index.read()); |
1555 | | r_multi_ack_trdid = m_upt.trdid(r_multi_ack_upt_index.read()); |
1556 | | r_multi_ack_pktid = m_upt.pktid(r_multi_ack_upt_index.read()); |
1557 | | r_multi_ack_nline = m_upt.nline(r_multi_ack_upt_index.read()); |
1558 | | bool need_rsp = m_upt.need_rsp(r_multi_ack_upt_index.read()); |
1559 | | |
1560 | | // clear the UPT entry |
1561 | | m_upt.clear(r_multi_ack_upt_index.read()); |
1562 | | |
1563 | | if ( need_rsp ) r_multi_ack_fsm = MULTI_ACK_WRITE_RSP; |
1564 | | else r_multi_ack_fsm = MULTI_ACK_IDLE; |
1565 | | |
1566 | | #if DEBUG_MEMC_MULTI_ACK |
1567 | | if(m_debug) |
1568 | | std::cout << " <MEMC " << name() |
1569 | | << " MULTI_ACK_UPT_CLEAR> Clear UPT entry " |
1570 | | << std::dec << r_multi_ack_upt_index.read() << std::endl; |
1571 | | #endif |
1572 | | break; |
1573 | | } |
1574 | | ///////////////////////// |
1575 | | case MULTI_ACK_WRITE_RSP: // Post a response request to TGT_RSP FSM |
1576 | | // Wait if pending request |
1577 | | { |
1578 | | if ( r_multi_ack_to_tgt_rsp_req.read() ) break; |
1579 | | |
1580 | | r_multi_ack_to_tgt_rsp_req = true; |
1581 | | r_multi_ack_to_tgt_rsp_srcid = r_multi_ack_srcid.read(); |
1582 | | r_multi_ack_to_tgt_rsp_trdid = r_multi_ack_trdid.read(); |
1583 | | r_multi_ack_to_tgt_rsp_pktid = r_multi_ack_pktid.read(); |
1584 | | r_multi_ack_fsm = MULTI_ACK_IDLE; |
1585 | | |
1586 | | #if DEBUG_MEMC_MULTI_ACK |
1587 | | if(m_debug) |
1588 | | std::cout << " <MEMC " << name() << " MULTI_ACK_WRITE_RSP>" |
1589 | | << " Request TGT_RSP FSM to send a response to srcid " |
1590 | | << std::hex << r_multi_ack_srcid.read() << std::endl; |
1591 | | #endif |
1592 | | break; |
1593 | | } |
1594 | | } // end switch r_multi_ack_fsm |
1595 | | |
1596 | | //////////////////////////////////////////////////////////////////////////////////// |
1597 | | // CONFIG FSM |
1598 | | //////////////////////////////////////////////////////////////////////////////////// |
1599 | | // The CONFIG FSM handles the VCI configuration requests (INVAL & SYNC). |
1600 | | // The target buffer can have any size, and there is one single command for |
1601 | | // all cache lines covered by the target buffer. |
1602 | | // |
1603 | | // An INVAL or SYNC configuration operation is defined by the following registers: |
1604 | | // - bool r_config_cmd : INVAL / SYNC / NOP |
1605 | | // - uint64_t r_config_address : buffer base address |
1606 | | // - uint32_t r_config_cmd_lines : number of lines to be handled |
1607 | | // - uint32_t r_config_rsp_lines : number of lines not completed |
1608 | | // |
1609 | | // For both INVAL and SYNC commands, the CONFIG FSM contains the loop handling |
1610 | | // all cache lines covered by the buffer. The various lines of a given buffer |
1611 | | // can be pipelined: the CONFIG FSM does not wait the response for line (n) to send |
1612 | | // the command for line (n+1). It decrements the r_config_cmd_lines counter until |
1613 | | // the last request has been registered in TRT (for a SYNC), or in IVT (for an INVAL). |
1614 | | // |
1615 | | // - INVAL request: |
1616 | | // For each line, it access to the DIR. |
1617 | | // In case of miss, it does nothing, and a response is requested to TGT_RSP FSM. |
1618 | | // In case of hit, with no copies in L1 caches, the line is invalidated and |
1619 | | // a response is requested to TGT_RSP FSM. |
1620 | | // If there is copies, a multi-inval, or a broadcast-inval coherence transaction |
1621 | | // is launched and registered in UPT. The multi-inval transaction completion |
1622 | | // is signaled by the CLEANUP FSM by decrementing the r_config_rsp_lines counter. |
1623 | | // The CONFIG INVAL response is sent only when the last line has been invalidated. |
1624 | | // TODO : The target buffer address must be aligned on a cache line boundary. |
1625 | | // This constraint can be released, but it requires to make 2 PUT transactions |
1626 | | // for the first and the last line... |
1627 | | // |
1628 | | // - SYNC request: |
1629 | | // For each line, it access to the DIR. |
1630 | | // In case of miss, it does nothing, and a response is requested to TGT_RSP FSM. |
1631 | | // In case of hit, a PUT transaction is registered in TRT and a request is sent |
1632 | | // to IXR_CMD FSM. The IXR_RSP FSM decrements the r_config_rsp_lines counter |
1633 | | // when a PUT response is received. |
1634 | | // The CONFIG SYNC response is sent only when the last PUT response is received. |
1635 | | // |
1636 | | // From the software point of view, a configuration request is a sequence |
1637 | | // of 6 atomic accesses in an uncached segment. A dedicated lock is used |
1638 | | // to handle only one configuration command at a given time: |
1639 | | // - Read MEMC_LOCK : Get the lock |
1640 | | // - Write MEMC_ADDR_LO : Set the buffer address LSB |
1641 | | // - Write MEMC_ADDR_HI : Set the buffer address MSB |
1642 | | // - Write MEMC_BUF_LENGTH : set buffer length (bytes) |
1643 | | // - Write MEMC_CMD_TYPE : launch the actual operation |
1644 | | // - WRITE MEMC_LOCK : release the lock |
1645 | | //////////////////////////////////////////////////////////////////////////////////// |
1646 | | |
1647 | | //std::cout << std::endl << "config_fsm" << std::endl; |
1648 | | |
1649 | | switch( r_config_fsm.read() ) |
1650 | | { |
1651 | | ///////////////// |
1652 | | case CONFIG_IDLE: // waiting a config request |
1653 | | { |
1654 | | if ( r_config_cmd.read() != MEMC_CMD_NOP ) |
1655 | | { |
1656 | | r_config_fsm = CONFIG_LOOP; |
1657 | | |
1658 | | #if DEBUG_MEMC_CONFIG |
1659 | | if(m_debug) |
1660 | | std::cout << " <MEMC " << name() << " CONFIG_IDLE> Config Request received" |
1661 | | << " / address = " << std::hex << r_config_address.read() |
1662 | | << " / lines = " << std::dec << r_config_cmd_lines.read() |
1663 | | << " / type = " << r_config_cmd.read() << std::endl; |
1664 | | #endif |
1665 | | } |
1666 | | break; |
1667 | | } |
1668 | | ///////////////// |
1669 | | case CONFIG_LOOP: // test if last line to be handled |
1670 | | { |
1671 | | if ( r_config_cmd_lines.read() == 0 ) |
1672 | | { |
1673 | | r_config_cmd = MEMC_CMD_NOP; |
1674 | | r_config_fsm = CONFIG_WAIT; |
1675 | | } |
1676 | | else |
1677 | | { |
1678 | | r_config_fsm = CONFIG_DIR_REQ; |
1679 | | } |
1680 | | |
1681 | | #if DEBUG_MEMC_CONFIG |
1682 | | if(m_debug) |
1683 | | std::cout << " <MEMC " << name() << " CONFIG_LOOP>" |
1684 | | << " / address = " << std::hex << r_config_address.read() |
1685 | | << " / lines not handled = " << std::dec << r_config_cmd_lines.read() |
1686 | | << " / command = " << r_config_cmd.read() << std::endl; |
1687 | | #endif |
1688 | | break; |
1689 | | } |
1690 | | ///////////////// |
1691 | | case CONFIG_WAIT: // wait completion (last response) |
1692 | | { |
1693 | | if ( r_config_rsp_lines.read() == 0 ) // last response received |
1694 | | { |
1695 | | r_config_fsm = CONFIG_RSP; |
1696 | | } |
1697 | | |
1698 | | #if DEBUG_MEMC_CONFIG |
1699 | | if(m_debug) |
1700 | | std::cout << " <MEMC " << name() << " CONFIG_WAIT>" |
1701 | | << " / lines to do = " << std::dec << r_config_rsp_lines.read() << std::endl; |
1702 | | #endif |
1703 | | break; |
1704 | | } |
1705 | | //////////////// |
1706 | | case CONFIG_RSP: // request TGT_RSP FSM to return response |
1707 | | { |
1708 | | if ( not r_config_to_tgt_rsp_req.read() ) |
1709 | | { |
1710 | | r_config_to_tgt_rsp_srcid = r_config_srcid.read(); |
1711 | | r_config_to_tgt_rsp_trdid = r_config_trdid.read(); |
1712 | | r_config_to_tgt_rsp_pktid = r_config_pktid.read(); |
1713 | | r_config_to_tgt_rsp_error = false; |
1714 | | r_config_to_tgt_rsp_req = true; |
1715 | | r_config_fsm = CONFIG_IDLE; |
1716 | | |
1717 | | #if DEBUG_MEMC_CONFIG |
1718 | | if(m_debug) |
1719 | | std::cout << " <MEMC " << name() << " CONFIG_RSP> Request TGT_RSP FSM to return response:" |
1720 | | << " error = " << r_config_to_tgt_rsp_error.read() |
1721 | | << " / rsrcid = " << std::hex << r_config_srcid.read() |
1722 | | << " / rtrdid = " << std::hex << r_config_trdid.read() |
1723 | | << " / rpktid = " << std::hex << r_config_pktid.read() << std::endl; |
1724 | | #endif |
1725 | | } |
1726 | | break; |
1727 | | |
1728 | | } |
1729 | | //////////////////// |
1730 | | case CONFIG_DIR_REQ: // Request directory lock |
1731 | | { |
1732 | | if ( r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG ) |
1733 | | { |
1734 | | r_config_fsm = CONFIG_DIR_ACCESS; |
1735 | | } |
1736 | | |
1737 | | #if DEBUG_MEMC_CONFIG |
1738 | | if(m_debug) |
1739 | | std::cout << " <MEMC " << name() << " CONFIG_DIR_REQ>" |
1740 | | << " Request DIR access" << std::endl; |
1741 | | #endif |
1742 | | break; |
1743 | | } |
1744 | | /////////////////////// |
1745 | | case CONFIG_DIR_ACCESS: // Access directory and decode config command |
1746 | | { |
1747 | | assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and |
1748 | | "MEMC ERROR in CONFIG_DIR_ACCESS state: bad DIR allocation"); |
1749 | | |
1750 | | size_t way = 0; |
1751 | | DirectoryEntry entry = m_cache_directory.read(r_config_address.read(), way); |
1752 | | |
1753 | | if ( entry.valid and // hit & inval command |
1754 | | (r_config_cmd.read() == MEMC_CMD_INVAL) ) |
1755 | | { |
1756 | | r_config_dir_way = way; |
1757 | | r_config_dir_copy_inst = entry.owner.inst; |
1758 | | r_config_dir_copy_srcid = entry.owner.srcid; |
1759 | | r_config_dir_is_cnt = entry.is_cnt; |
1760 | | r_config_dir_lock = entry.lock; |
1761 | | r_config_dir_count = entry.count; |
1762 | | r_config_dir_ptr = entry.ptr; |
1763 | | |
1764 | | r_config_fsm = CONFIG_IVT_LOCK; |
1765 | | } |
1766 | | else if ( entry.valid and // hit & sync command |
1767 | | entry.dirty and |
1768 | | (r_config_cmd.read() == MEMC_CMD_SYNC) ) |
1769 | | { |
1770 | | r_config_fsm = CONFIG_TRT_LOCK; |
1771 | | } |
1772 | | else // miss : return to LOOP |
1773 | | { |
1774 | | r_config_cmd_lines = r_config_cmd_lines.read() - 1; |
1775 | | r_config_rsp_lines = r_config_rsp_lines.read() - 1; |
1776 | | r_config_cmd_lines = r_config_cmd_lines.read() - 1; |
1777 | | r_config_address = r_config_address.read() + (m_words<<2); |
1778 | | r_config_fsm = CONFIG_LOOP; |
1779 | | } |
1780 | | |
1781 | | #if DEBUG_MEMC_CONFIG |
1782 | | if(m_debug) |
1783 | | std::cout << " <MEMC " << name() << " CONFIG_DIR_ACCESS> Accessing directory: " |
1784 | | << " address = " << std::hex << r_config_address.read() |
1785 | | << " / hit = " << std::dec << entry.valid |
1786 | | << " / dirty = " << entry.dirty |
1787 | | << " / count = " << entry.count |
1788 | | << " / is_cnt = " << entry.is_cnt << std::endl; |
1789 | | #endif |
1790 | | break; |
1791 | | } |
1792 | | ///////////////////// |
1793 | | case CONFIG_TRT_LOCK: // enter this state in case of SYNC command |
1794 | | // to a dirty cache line |
1795 | | // keep DIR lock, and try to get TRT lock |
1796 | | // return to LOOP state if TRT full |
1797 | | // reset dirty bit in DIR and register a PUT |
1798 | | // trabsaction in TRT if not full. |
1799 | | { |
1800 | | assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and |
1801 | | "MEMC ERROR in CONFIG_TRT_LOCK state: bad DIR allocation"); |
1802 | | |
1803 | | if ( r_alloc_trt_fsm.read() == ALLOC_TRT_CONFIG ) |
1804 | | { |
1805 | | size_t index = 0; |
1806 | | bool wok = not m_trt.full(index); |
1807 | | |
1808 | | if ( not wok ) |
1809 | | { |
1810 | | r_config_fsm = CONFIG_LOOP; |
1811 | | } |
1812 | | else |
1813 | | { |
1814 | | size_t way = r_config_dir_way.read(); |
1815 | | size_t set = m_y[r_config_address.read()]; |
1816 | | |
1817 | | // reset dirty bit in DIR |
1818 | | DirectoryEntry entry; |
1819 | | entry.valid = true; |
1820 | | entry.dirty = false; |
1821 | | entry.tag = m_z[r_config_address.read()]; |
1822 | | entry.is_cnt = r_config_dir_is_cnt.read(); |
1823 | | entry.lock = r_config_dir_lock.read(); |
1824 | | entry.ptr = r_config_dir_ptr.read(); |
1825 | | entry.count = r_config_dir_count.read(); |
1826 | | entry.owner.inst = r_config_dir_copy_inst.read(); |
1827 | | entry.owner.srcid = r_config_dir_copy_srcid.read(); |
1828 | | m_cache_directory.write( set, |
1829 | | way, |
1830 | | entry ); |
1831 | | |
1832 | | r_config_trt_index = index; |
1833 | | r_config_fsm = CONFIG_TRT_SET; |
1834 | | } |
1835 | | |
1836 | | #if DEBUG_MEMC_CONFIG |
1837 | | if(m_debug) |
1838 | | std::cout << " <MEMC " << name() << " CONFIG_TRT_LOCK> Access TRT: " |
1839 | | << " wok = " << std::dec << wok |
1840 | | << " index = " << index << std::endl; |
1841 | | #endif |
1842 | | } |
1843 | | break; |
1844 | | } |
1845 | | //////////////////// |
1846 | | case CONFIG_TRT_SET: // read data in cache |
1847 | | // and post a PUT request in TRT |
1848 | | { |
1849 | | assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and |
1850 | | "MEMC ERROR in CONFIG_TRT_SET state: bad DIR allocation"); |
1851 | | |
1852 | | assert( (r_alloc_trt_fsm.read() == ALLOC_TRT_CONFIG) and |
1853 | | "MEMC ERROR in CONFIG_TRT_SET state: bad TRT allocation"); |
1854 | | |
1855 | | // read data into cache |
1856 | | size_t way = r_config_dir_way.read(); |
1857 | | size_t set = m_y[r_config_address.read()]; |
1858 | | |
1859 | | sc_signal<data_t> config_data[16]; |
1860 | | m_cache_data.read_line( way, |
1861 | | set, |
1862 | | config_data ); |
1863 | | |
1864 | | // post a PUT request in TRT |
1865 | | std::vector<data_t> data_vector; |
1866 | | data_vector.clear(); |
1867 | | for(size_t i=0; i<m_words; i++) data_vector.push_back(config_data[i].read()); |
1868 | | m_trt.set( r_config_trt_index.read(), |
1869 | | false, // PUT |
1870 | | m_nline[r_config_address.read()], // nline |
1871 | | 0, // srcid: unused |
1872 | | 0, // trdid: unused |
1873 | | 0, // pktid: unused |
1874 | | false, // not proc_read |
1875 | | 0, // read_length: unused |
1876 | | 0, // word_index: unused |
1877 | | std::vector<be_t>(m_words,0xF), |
1878 | | data_vector); |
1879 | | |
1880 | | #if DEBUG_MEMC_CONFIG |
1881 | | if(m_debug) |
1882 | | std::cout << " <MEMC " << name() << " CONFIG_TRT_SET> PUT request in TRT:" |
1883 | | << " address = " << std::hex << r_config_address.read() |
1884 | | << " index = " << std::dec << r_config_trt_index.read() << std::endl; |
1885 | | #endif |
1886 | | break; |
1887 | | } |
1888 | | //////////////////// |
1889 | | case CONFIG_PUT_REQ: // PUT request to IXR_CMD_FSM |
1890 | | { |
1891 | | if ( not r_config_to_ixr_cmd_req.read() ) |
1892 | | { |
1893 | | r_config_to_ixr_cmd_req = true; |
1894 | | r_config_to_ixr_cmd_index = r_config_trt_index.read(); |
1895 | | |
1896 | | // prepare next iteration |
1897 | | r_config_cmd_lines = r_config_cmd_lines.read() - 1; |
1898 | | r_config_address = r_config_address.read() + (m_words<<2); |
1899 | | r_config_fsm = CONFIG_LOOP; |
1900 | | |
1901 | | #if DEBUG_MEMC_CONFIG |
1902 | | if(m_debug) |
1903 | | std::cout << " <MEMC " << name() << " CONFIG_PUT_REQ> PUT request to IXR_CMD_FSM" |
1904 | | << " / address = " << std::hex << r_config_address.read() << std::endl; |
1905 | | #endif |
1906 | | } |
1907 | | break; |
1908 | | } |
1909 | | ///////////////////// |
1910 | | case CONFIG_IVT_LOCK: // enter this state in case of INVAL command |
1911 | | // Keep DIR lock and Try to get IVT lock. |
1912 | | // Return to LOOP state if IVT full. |
1913 | | // Register inval in IVT, and invalidate the |
1914 | | // directory if IVT not full. |
1915 | | { |
1916 | | assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and |
1917 | | "MEMC ERROR in CONFIG_IVT_LOCK state: bad DIR allocation"); |
1918 | | |
1919 | | if ( r_alloc_ivt_fsm.read() == ALLOC_IVT_CONFIG ) |
1920 | | { |
1921 | | size_t set = m_y[(addr_t)(r_config_address.read())]; |
1922 | | size_t way = r_config_dir_way.read(); |
1923 | | |
1924 | | if ( r_config_dir_count.read() == 0 ) // inval DIR and return to LOOP |
1925 | | { |
1926 | | m_cache_directory.inval( way, set ); |
1927 | | r_config_cmd_lines = r_config_cmd_lines.read() - 1; |
1928 | | r_config_rsp_lines = r_config_rsp_lines.read() - 1; |
1929 | | r_config_address = r_config_address.read() + (m_words<<2); |
1930 | | r_config_fsm = CONFIG_LOOP; |
1931 | | |
1932 | | #if DEBUG_MEMC_CONFIG |
1933 | | if(m_debug) |
1934 | | std::cout << " <MEMC " << name() << " CONFIG_IVT_LOCK>" |
1935 | | << " No copies in L1 : inval DIR entry" << std::endl; |
1936 | | #endif |
1937 | | } |
1938 | | else // try to register inval in IVT |
1939 | | { |
1940 | | bool wok = false; |
1941 | | size_t index = 0; |
1942 | | bool broadcast = r_config_dir_is_cnt.read(); |
1943 | | size_t srcid = r_config_srcid.read(); |
1944 | | size_t trdid = r_config_trdid.read(); |
1945 | | size_t pktid = r_config_pktid.read(); |
1946 | | addr_t nline = m_nline[(addr_t)(r_config_address.read())]; |
1947 | | size_t nb_copies = r_config_dir_count.read(); |
1948 | | |
1949 | | wok = m_ivt.set(false, // it's an inval transaction |
1950 | | broadcast, |
1951 | | false, // no response required |
1952 | | true, // acknowledge required |
1953 | | srcid, |
1954 | | trdid, |
1955 | | pktid, |
1956 | | nline, |
1957 | | nb_copies, |
1958 | | index); |
1959 | | |
1960 | | if ( wok ) // IVT success => inval DIR slot |
1961 | | { |
1962 | | m_cache_directory.inval( way, set ); |
1963 | | r_config_ivt_index = index; |
1964 | | if ( broadcast ) r_config_fsm = CONFIG_BC_SEND; |
1965 | | else r_config_fsm = CONFIG_INVAL_SEND; |
1966 | | |
1967 | | #if DEBUG_MEMC_CONFIG |
1968 | | if(m_debug) |
1969 | | std::cout << " <MEMC " << name() << " CONFIG_IVT_LOCK>" |
1970 | | << " Inval DIR entry and register inval in IVT" |
1971 | | << " / index = " << std::dec << index |
1972 | | << " / broadcast = " << broadcast << std::endl; |
1973 | | #endif |
1974 | | } |
1975 | | else // IVT full => release both DIR and IVT locks |
1976 | | { |
1977 | | r_config_fsm = CONFIG_LOOP; |
1978 | | |
1979 | | #if DEBUG_MEMC_CONFIG |
1980 | | if(m_debug) |
1981 | | std::cout << " <MEMC " << name() << " CONFIG_IVT_LOCK>" |
1982 | | << " IVT full : release DIR & IVT locks and retry" << std::endl; |
1983 | | #endif |
1984 | | } |
1985 | | } |
1986 | | } |
1987 | | break; |
1988 | | } |
1989 | | //////////////////// |
1990 | | case CONFIG_BC_SEND: // Post a broadcast inval request to CC_SEND FSM |
1991 | | { |
1992 | | if( not r_config_to_cc_send_multi_req.read() and |
1993 | | not r_config_to_cc_send_brdcast_req.read() ) |
1994 | | { |
1995 | | // post bc inval request |
1996 | | r_config_to_cc_send_multi_req = false; |
1997 | | r_config_to_cc_send_brdcast_req = true; |
1998 | | r_config_to_cc_send_trdid = r_config_ivt_index.read(); |
1999 | | r_config_to_cc_send_nline = m_nline[(addr_t)(r_config_address.read())]; |
2000 | | |
2001 | | // prepare next iteration |
2002 | | r_config_cmd_lines = r_config_cmd_lines.read() - 1; |
2003 | | r_config_address = r_config_address.read() + (m_words<<2); |
2004 | | r_config_fsm = CONFIG_LOOP; |
2005 | | |
2006 | | #if DEBUG_MEMC_CONFIG |
2007 | | if(m_debug) |
2008 | | std::cout << " <MEMC " << name() << " CONFIG_BC_SEND>" |
2009 | | << " Post a broadcast inval request to CC_SEND FSM" |
2010 | | << " / address = " << r_config_address.read() <<std::endl; |
2011 | | #endif |
2012 | | } |
2013 | | break; |
2014 | | } |
2015 | | /////////////////////// |
2016 | | case CONFIG_INVAL_SEND: // Post a multi inval request to CC_SEND FSM |
2017 | | { |
2018 | | if( not r_config_to_cc_send_multi_req.read() and |
2019 | | not r_config_to_cc_send_brdcast_req.read() ) |
2020 | | { |
2021 | | // post multi inval request |
2022 | | r_config_to_cc_send_multi_req = true; |
2023 | | r_config_to_cc_send_brdcast_req = false; |
2024 | | r_config_to_cc_send_trdid = r_config_ivt_index.read(); |
2025 | | r_config_to_cc_send_nline = m_nline[(addr_t)(r_config_address.read())]; |
2026 | | |
2027 | | // post data into FIFO |
2028 | | config_to_cc_send_fifo_srcid = r_config_dir_copy_srcid.read(); |
2029 | | config_to_cc_send_fifo_inst = r_config_dir_copy_inst.read(); |
2030 | | config_to_cc_send_fifo_put = true; |
2031 | | |
2032 | | if ( r_config_dir_count.read() == 1 ) // one copy |
2033 | | { |
2034 | | // prepare next iteration |
2035 | | r_config_cmd_lines = r_config_cmd_lines.read() - 1; |
2036 | | r_config_address = r_config_address.read() + (m_words<<2); |
2037 | | r_config_fsm = CONFIG_LOOP; |
2038 | | } |
2039 | | else // several copies |
2040 | | { |
2041 | | r_config_fsm = CONFIG_HEAP_REQ; |
2042 | | } |
2043 | | |
2044 | | #if DEBUG_MEMC_CONFIG |
2045 | | if(m_debug) |
2046 | | std::cout << " <MEMC " << name() << " CONFIG_INVAL_SEND>" |
2047 | | << " Post multi inval request to CC_SEND FSM" |
2048 | | << " / address = " << std::hex << r_config_address.read() |
2049 | | << " / copy = " << r_config_dir_copy_srcid.read() |
2050 | | << " / inst = " << std::dec << r_config_dir_copy_inst.read() << std::endl; |
2051 | | #endif |
2052 | | } |
2053 | | break; |
2054 | | } |
2055 | | ///////////////////// |
2056 | | case CONFIG_HEAP_REQ: // Try to get access to Heap |
2057 | | { |
2058 | | if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CONFIG ) |
2059 | | { |
2060 | | r_config_fsm = CONFIG_HEAP_SCAN; |
2061 | | r_config_heap_next = r_config_dir_ptr.read(); |
2062 | | } |
2063 | | |
2064 | | #if DEBUG_MEMC_CONFIG |
2065 | | if(m_debug) |
2066 | | std::cout << " <MEMC " << name() << " CONFIG_HEAP_REQ>" |
2067 | | << " Requesting HEAP lock" << std::endl; |
2068 | | #endif |
2069 | | break; |
2070 | | } |
2071 | | ////////////////////// |
2072 | | case CONFIG_HEAP_SCAN: // scan HEAP and send inval to CC_SEND FSM |
2073 | | { |
2074 | | HeapEntry entry = m_heap.read( r_config_heap_next.read() ); |
2075 | | bool last_copy = (entry.next == r_config_heap_next.read()); |
2076 | | |
2077 | | config_to_cc_send_fifo_srcid = entry.owner.srcid; |
2078 | | config_to_cc_send_fifo_inst = entry.owner.inst; |
2079 | | // config_to_cc_send_fifo_last = last_copy; |
2080 | | config_to_cc_send_fifo_put = true; |
2081 | | |
2082 | | if ( m_config_to_cc_send_inst_fifo.wok() ) // inval request accepted |
2083 | | { |
2084 | | r_config_heap_next = entry.next; |
2085 | | if ( last_copy ) r_config_fsm = CONFIG_HEAP_LAST; |
2086 | | } |
2087 | | |
2088 | | #if DEBUG_MEMC_CONFIG |
2089 | | if(m_debug) |
2090 | | std::cout << " <MEMC " << name() << " CONFIG_HEAP_SCAN>" |
2091 | | << " Post multi inval request to CC_SEND FSM" |
2092 | | << " / address = " << std::hex << r_config_address.read() |
2093 | | << " / copy = " << entry.owner.srcid |
2094 | | << " / inst = " << std::dec << entry.owner.inst << std::endl; |
2095 | | #endif |
2096 | | break; |
2097 | | } |
2098 | | ////////////////////// |
2099 | | case CONFIG_HEAP_LAST: // HEAP housekeeping |
2100 | | { |
2101 | | size_t free_pointer = m_heap.next_free_ptr(); |
2102 | | HeapEntry last_entry; |
2103 | | last_entry.owner.srcid = 0; |
2104 | | last_entry.owner.inst = false; |
2105 | | |
2106 | | if ( m_heap.is_full() ) |
2107 | | { |
2108 | | last_entry.next = r_config_dir_ptr.read(); |
2109 | | m_heap.unset_full(); |
2110 | | } |
2111 | | else |
2112 | | { |
2113 | | last_entry.next = free_pointer; |
2114 | | } |
2115 | | |
2116 | | m_heap.write_free_ptr( r_config_dir_ptr.read() ); |
2117 | | m_heap.write( r_config_heap_next.read(), last_entry ); |
2118 | | |
2119 | | // prepare next iteration |
2120 | | r_config_cmd_lines = r_config_cmd_lines.read() - 1; |
2121 | | r_config_address = r_config_address.read() + (m_words<<2); |
2122 | | r_config_fsm = CONFIG_LOOP; |
2123 | | |
2124 | | #if DEBUG_MEMC_CONFIG |
2125 | | if(m_debug) |
2126 | | std::cout << " <MEMC " << name() << " CONFIG_HEAP_LAST>" |
2127 | | << " Heap housekeeping" << std::endl; |
2128 | | #endif |
2129 | | break; |
2130 | | } |
2131 | | } // end switch r_config_fsm |
2132 | | |
2133 | | //////////////////////////////////////////////////////////////////////////////////// |
2134 | | // READ FSM |
2135 | | //////////////////////////////////////////////////////////////////////////////////// |
2136 | | // The READ FSM controls the VCI read and ll requests. |
2137 | | // It takes the lock protecting the cache directory to check the cache line status: |
2138 | | // - In case of HIT |
2139 | | // The fsm copies the data (one line, or one single word) |
2140 | | // in the r_read_to_tgt_rsp buffer. It waits if this buffer is not empty. |
2141 | | // The requesting initiator is registered in the cache directory. |
2142 | | // If the number of copy is larger than 1, the new copy is registered |
2143 | | // in the HEAP. |
2144 | | // If the number of copy is larger than the threshold, the HEAP is cleared, |
2145 | | // and the corresponding line switches to the counter mode. |
2146 | | // - In case of MISS |
2147 | | // The READ fsm takes the lock protecting the transaction tab. |
2148 | | // If a read transaction to the XRAM for this line already exists, |
2149 | | // or if the transaction tab is full, the fsm is stalled. |
2150 | | // If a TRT entry is free, the READ request is registered in TRT, |
2151 | | // it is consumed in the request FIFO, and transmited to the IXR_CMD FSM. |
2152 | | // The READ FSM returns in the IDLE state as the read transaction will be |
2153 | | // completed when the missing line will be received. |
2154 | | //////////////////////////////////////////////////////////////////////////////////// |
2155 | | |
2156 | | //std::cout << std::endl << "read_fsm" << std::endl; |
2157 | | |
2158 | | switch(r_read_fsm.read()) |
2159 | | { |
2160 | | /////////////// |
2161 | | case READ_IDLE: // waiting a read request |
2162 | | { |
2163 | | if(m_cmd_read_addr_fifo.rok()) |
2164 | | { |
| 2160 | /////////////// |
| 2161 | case READ_IDLE: // waiting a read request |
| 2162 | { |
| 2163 | if(m_cmd_read_addr_fifo.rok()) |
| 2164 | { |
2594 | | if(!wok) m_cpt_trt_full++; |
2595 | | if(hit_read or hit_write) m_cpt_trt_rb++; |
2596 | | r_read_fsm = READ_IDLE; |
2597 | | } |
2598 | | else // missing line is requested to the XRAM |
2599 | | { |
2600 | | m_cpt_read_miss++; |
2601 | | r_read_trt_index = index; |
2602 | | r_read_fsm = READ_TRT_SET; |
2603 | | } |
2604 | | |
2605 | | #if DEBUG_MEMC_READ |
2606 | | if(m_debug) |
2607 | | std::cout << " <MEMC " << name() << " READ_TRT_LOCK> Check TRT:" |
2608 | | << " hit_read = " << hit_read |
2609 | | << " / hit_write = " << hit_write |
2610 | | << " / Index = " << index_write |
2611 | | << " / full = " << !wok << std::endl; |
2612 | | m_cpt_read_fsm_n_trt_lock++; |
2613 | | #endif |
2614 | | } |
2615 | | |
2616 | | m_cpt_read_fsm_trt_lock++; |
2617 | | |
2618 | | break; |
2619 | | } |
2620 | | ////////////////// |
2621 | | case READ_TRT_SET: // register get transaction in TRT |
2622 | | { |
2623 | | if(r_alloc_trt_fsm.read() == ALLOC_TRT_READ) |
2624 | | { |
2625 | | m_trt.set( r_read_trt_index.read(), |
2626 | | true, // GET |
2627 | | m_nline[(addr_t)(m_cmd_read_addr_fifo.read())], |
2628 | | m_cmd_read_srcid_fifo.read(), |
2629 | | m_cmd_read_trdid_fifo.read(), |
2630 | | m_cmd_read_pktid_fifo.read(), |
2631 | | true, // proc read |
2632 | | m_cmd_read_length_fifo.read(), |
2633 | | m_x[(addr_t)(m_cmd_read_addr_fifo.read())], |
2634 | | std::vector<be_t> (m_words,0), |
2635 | | std::vector<data_t> (m_words,0), |
2636 | | r_read_ll_key.read() ); |
2637 | | #if DEBUG_MEMC_READ |
2638 | | if(m_debug) |
2639 | | std::cout << " <MEMC " << name() << " READ_TRT_SET> Set a GET in TRT:" |
2640 | | << " address = " << std::hex << m_cmd_read_addr_fifo.read() |
2641 | | << " / srcid = " << std::hex << m_cmd_read_srcid_fifo.read() << std::endl; |
2642 | | #endif |
2643 | | r_read_fsm = READ_TRT_REQ; |
2644 | | } |
2645 | | break; |
2646 | | } |
2647 | | |
2648 | | ////////////////// |
2649 | | case READ_TRT_REQ: // consume the read request in FIFO and send it to IXR_CMD_FSM |
2650 | | { |
2651 | | if(not r_read_to_ixr_cmd_req) |
2652 | | { |
2653 | | cmd_read_fifo_get = true; |
2654 | | r_read_to_ixr_cmd_req = true; |
2655 | | r_read_to_ixr_cmd_index = r_read_trt_index.read(); |
2656 | | r_read_fsm = READ_IDLE; |
2657 | | |
2658 | | #if DEBUG_MEMC_READ |
2659 | | if(m_debug) |
2660 | | std::cout << " <MEMC " << name() << " READ_TRT_REQ> Request GET transaction for address " |
2661 | | << std::hex << m_cmd_read_addr_fifo.read() << std::endl; |
2662 | | #endif |
2663 | | } |
2664 | | break; |
2665 | | } |
2666 | | } // end switch read_fsm |
2667 | | |
2668 | | /////////////////////////////////////////////////////////////////////////////////// |
2669 | | // WRITE FSM |
2670 | | /////////////////////////////////////////////////////////////////////////////////// |
2671 | | // The WRITE FSM handles the write bursts and sc requests sent by the processors. |
2672 | | // All addresses in a burst must be in the same cache line. |
2673 | | // A complete write burst is consumed in the FIFO & copied to a local buffer. |
2674 | | // Then the FSM takes the lock protecting the cache directory, to check |
2675 | | // if the line is in the cache. |
2676 | | // |
2677 | | // - In case of HIT, the cache is updated. |
2678 | | // If there is no other copy, an acknowledge response is immediately |
2679 | | // returned to the writing processor. |
2680 | | // If the data is cached by other processors, a coherence transaction must |
2681 | | // be launched (sc requests always require a coherence transaction): |
2682 | | // It is a multicast update if the line is not in counter mode: the processor |
2683 | | // takes the lock protecting the Update Table (UPT) to register this transaction. |
2684 | | // If the UPT is full, it releases the lock(s) and retry. Then, it sends |
2685 | | // a multi-update request to all owners of the line (but the writer), |
2686 | | // through the CC_SEND FSM. In case of coherence transaction, the WRITE FSM |
2687 | | // does not respond to the writing processor, as this response will be sent by |
2688 | | // the MULTI_ACK FSM when all update responses have been received. |
2689 | | // It is a broadcast invalidate if the line is in counter mode: The line |
2690 | | // should be erased in memory cache, and written in XRAM with a PUT transaction, |
2691 | | // after registration in TRT. |
2692 | | // |
2693 | | // - In case of MISS, the WRITE FSM takes the lock protecting the transaction |
2694 | | // table (TRT). If a read transaction to the XRAM for this line already exists, |
2695 | | // it writes in the TRT (write buffer). Otherwise, if a TRT entry is free, |
2696 | | // the WRITE FSM register a new transaction in TRT, and sends a GET request |
2697 | | // to the XRAM. If the TRT is full, it releases the lock, and waits. |
2698 | | // Finally, the WRITE FSM returns an aknowledge response to the writing processor. |
2699 | | ///////////////////////////////////////////////////////////////////////////////////// |
2700 | | |
2701 | | //std::cout << std::endl << "write_fsm" << std::endl; |
2702 | | |
2703 | | switch(r_write_fsm.read()) |
2704 | | { |
2705 | | //////////////// |
2706 | | case WRITE_IDLE: // copy first word of a write burst in local buffer |
2707 | | { |
2708 | | if(m_cmd_write_addr_fifo.rok()) |
2709 | | { |
2710 | | if((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC) |
2711 | | { |
2712 | | m_cpt_sc++; |
2713 | | } |
2714 | | else |
2715 | | { |
2716 | | m_cpt_write++; |
2717 | | m_cpt_write_cells++; |
2718 | | } |
2719 | | |
2720 | | // consume a word in the FIFO & write it in the local buffer |
2721 | | cmd_write_fifo_get = true; |
2722 | | size_t index = m_x[(addr_t)(m_cmd_write_addr_fifo.read())]; |
2723 | | |
2724 | | r_write_address = (addr_t)(m_cmd_write_addr_fifo.read()); |
2725 | | r_write_word_index = index; |
2726 | | r_write_word_count = 1; |
2727 | | r_write_data[index] = m_cmd_write_data_fifo.read(); |
2728 | | r_write_srcid = m_cmd_write_srcid_fifo.read(); |
2729 | | r_write_trdid = m_cmd_write_trdid_fifo.read(); |
2730 | | r_write_pktid = m_cmd_write_pktid_fifo.read(); |
2731 | | r_write_pending_sc = false; |
2732 | | |
2733 | | // initialize the be field for all words |
2734 | | for(size_t word=0 ; word<m_words ; word++) |
2735 | | { |
2736 | | if(word == index) r_write_be[word] = m_cmd_write_be_fifo.read(); |
2737 | | else r_write_be[word] = 0x0; |
2738 | | } |
2739 | | |
2740 | | if (m_cmd_write_eop_fifo.read() or ((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC)) |
2741 | | { |
2742 | | r_write_fsm = WRITE_DIR_REQ; |
2743 | | } |
2744 | | else |
2745 | | { |
2746 | | r_write_fsm = WRITE_NEXT; |
2747 | | } |
| 2705 | //////////////// |
| 2706 | case WRITE_IDLE: // copy first word of a write burst in local buffer |
| 2707 | { |
| 2708 | if(m_cmd_write_addr_fifo.rok()) |
| 2709 | { |
| 2710 | if((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC) |
| 2711 | { |
| 2712 | m_cpt_sc++; |
| 2713 | } |
| 2714 | else |
| 2715 | { |
| 2716 | m_cpt_write++; |
| 2717 | m_cpt_write_cells++; |
| 2718 | } |
| 2719 | |
| 2720 | // consume a word in the FIFO & write it in the local buffer |
| 2721 | cmd_write_fifo_get = true; |
| 2722 | size_t index = m_x[(addr_t)(m_cmd_write_addr_fifo.read())]; |
| 2723 | |
| 2724 | r_write_address = (addr_t)(m_cmd_write_addr_fifo.read()); |
| 2725 | r_write_word_index = index; |
| 2726 | r_write_word_count = 1; |
| 2727 | r_write_data[index] = m_cmd_write_data_fifo.read(); |
| 2728 | r_write_srcid = m_cmd_write_srcid_fifo.read(); |
| 2729 | r_write_trdid = m_cmd_write_trdid_fifo.read(); |
| 2730 | r_write_pktid = m_cmd_write_pktid_fifo.read(); |
| 2731 | r_write_pending_sc = false; |
| 2732 | |
| 2733 | // initialize the be field for all words |
| 2734 | for(size_t word=0 ; word<m_words ; word++) |
| 2735 | { |
| 2736 | if(word == index) r_write_be[word] = m_cmd_write_be_fifo.read(); |
| 2737 | else r_write_be[word] = 0x0; |
| 2738 | } |
| 2739 | |
| 2740 | if (m_cmd_write_eop_fifo.read() or ((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC)) |
| 2741 | { |
| 2742 | r_write_fsm = WRITE_DIR_REQ; |
| 2743 | } |
| 2744 | else |
| 2745 | { |
| 2746 | r_write_fsm = WRITE_NEXT; |
| 2747 | } |