550 | | |
| 550 | #include "vci_ram.h" |
| 551 | |
| 552 | #ifndef VCI_RAM_DEBUG |
| 553 | #define VCI_RAM_DEBUG 0 |
| 554 | #endif |
| 555 | |
| 556 | #define tmpl(x) x VciRam |
| 557 | |
| 558 | ////////////////////////////////////////////////////////////////////////////////////////// |
| 559 | // CONSTRUCTOR |
| 560 | ////////////////////////////////////////////////////////////////////////////////////////// |
| 561 | tmpl(/**/)::VciRam |
| 562 | ( sc_core::sc_module_name name, |
| 563 | const soclib::common::IntTab &index, |
| 564 | const soclib::common::MappingTable &mt, |
| 565 | soclib::common::ElfLoader &loader) |
| 566 | : sc_module(name), |
| 567 | m_mt(mt), |
| 568 | m_loader(new soclib::common::ElfLoader(loader)), |
| 569 | m_atomic(8), // 8 equals to maximal number of initiator |
| 570 | p_vci_target("socket") |
| 571 | { |
| 572 | //register callback fuction |
| 573 | p_vci_target.register_nb_transport_fw(this, &VciRam::my_nb_transport_fw); |
| 574 | |
| 575 | //identification |
| 576 | m_tgtid = m_mt.indexForId(index); |
| 577 | |
| 578 | m_segments = m_mt.getSegmentList(index); |
| 579 | m_contents = new ram_t*[m_segments.size()]; |
| 580 | size_t word_size = sizeof(vci_param::data_t); |
| 581 | |
| 582 | std::list<soclib::common::Segment>::iterator seg; |
| 583 | size_t i; |
| 584 | for (i=0, seg = m_segments.begin(); seg != m_segments.end(); ++i, ++seg ) { |
| 585 | soclib::common::Segment &s = *seg; |
| 586 | m_contents[i] = new ram_t[(s.size()+word_size-1)/word_size]; |
| 587 | } |
| 588 | |
| 589 | if ( m_loader ){ |
| 590 | for (i=0, seg = m_segments.begin(); seg != m_segments.end(); ++i, ++seg ) { |
| 591 | soclib::common::Segment &s = *seg; |
| 592 | m_loader->load(&m_contents[i][0], s.baseAddress(), s.size()); |
| 593 | for (size_t addr = 0; addr < s.size()/word_size; ++addr ) |
| 594 | m_contents[i][addr] = le_to_machine(m_contents[i][addr]); |
| 595 | } |
| 596 | } |
| 597 | |
| 598 | //initialize the control table LL/SC |
| 599 | m_atomic.clearAll(); |
| 600 | |
| 601 | } |
| 602 | |
| 603 | tmpl(/**/)::~VciRam(){} |
| 604 | |
| 605 | ///////////////////////////////////////////////////////////////////////////////////// |
| 606 | // Virtual Fuctions tlm::tlm_fw_transport_if VCI SOCKET |
| 607 | ///////////////////////////////////////////////////////////////////////////////////// |
| 608 | |
| 609 | //nb_transport_fw implementation calls from initiators |
| 610 | tmpl(tlm::tlm_sync_enum)::my_nb_transport_fw // non-blocking transport call through Bus |
| 611 | ( tlm::tlm_generic_payload &payload, // generic payoad pointer |
| 612 | tlm::tlm_phase &phase, // transaction phase |
| 613 | sc_core::sc_time &time) // time it should take for transport |
| 614 | { |
| 615 | // First, find the right segment using the first address of the packet |
| 616 | std::list<soclib::common::Segment>::iterator seg; |
| 617 | size_t segIndex; |
| 618 | soclib_payload_extension *extension_pointer; |
| 619 | payload.get_extension(extension_pointer); |
| 620 | |
| 621 | if(extension_pointer->is_null_message()){ |
| 622 | #if VCI_RAM_DEBUG |
| 623 | std::cout << "[RAM " << m_tgtid << "] Receive NULL MESSAGE Time = " << time.value() << std::endl; |
| 624 | #endif |
| 625 | return tlm::TLM_COMPLETED; |
| 626 | } |
| 627 | |
| 628 | uint32_t srcid = extension_pointer->get_src_id(); |
| 629 | uint32_t pktid = extension_pointer->get_pkt_id(); |
| 630 | uint32_t nwords = payload.get_data_length() / vci_param::nbytes; |
| 631 | |
| 632 | for (segIndex=0,seg = m_segments.begin(); seg != m_segments.end(); ++segIndex, ++seg ) { |
| 633 | soclib::common::Segment &s = *seg; |
| 634 | if (!s.contains(payload.get_address())) |
| 635 | continue; |
| 636 | |
| 637 | switch(extension_pointer->get_command()){ |
| 638 | case soclib::tlmt::VCI_READ_COMMAND: |
| 639 | { |
| 640 | #if VCI_RAM_DEBUG |
| 641 | std::cout << "[RAM " << m_tgtid << "] Receive from source "<< srcid << " a read packet " << pktid << " Time = " << time.value() << std::endl; |
| 642 | #endif |
| 643 | |
| 644 | vci_param::addr_t address; |
| 645 | for (size_t i=0;i<nwords;i++){ |
| 646 | //if (payload.contig) |
| 647 | address = (payload.get_address()+(i*vci_param::nbytes)) - s.baseAddress(); //XXX contig = TRUE always |
| 648 | //else |
| 649 | //address = payload.get_address() - s.baseAddress(); //always the same address |
| 650 | |
| 651 | utoa(m_contents[segIndex][address / vci_param::nbytes], payload.get_data_ptr(),(i * vci_param::nbytes)); |
| 652 | |
| 653 | //std::cout << "[RAM " << m_tgtid << "] READ address = " << std::hex << (payload.get_address()+(i*vci_param::nbytes)) << " data = " << m_contents[segIndex][address / vci_param::nbytes] << std::endl; |
| 654 | |
| 655 | } |
| 656 | |
| 657 | payload.set_response_status(tlm::TLM_OK_RESPONSE); |
| 658 | phase = tlm::BEGIN_RESP; |
| 659 | time = time + (nwords * UNIT_TIME); |
| 660 | |
| 661 | #if VCI_RAM_DEBUG |
| 662 | std::cout << "[RAM " << m_tgtid << "] Send to source "<< srcid << " a anwser packet " << pktid << " Time = " << time.value() << std::endl; |
| 663 | #endif |
| 664 | |
| 665 | p_vci_target->nb_transport_bw(payload, phase, time); |
| 666 | return tlm::TLM_COMPLETED; |
| 667 | } |
| 668 | break; |
| 669 | case soclib::tlmt::VCI_WRITE_COMMAND: |
| 670 | { |
| 671 | #if VCI_RAM_DEBUG |
| 672 | std::cout << "[RAM " << m_tgtid << "] Receive from source " << srcid <<" a Write packet "<< pktid << " Time = " << time.value() << std::endl; |
| 673 | #endif |
| 674 | |
| 675 | vci_param::addr_t address; |
| 676 | for (size_t i=0; i<nwords; i++){ |
| 677 | //if(payload.contig) |
| 678 | address = (payload.get_address()+(i*vci_param::nbytes)) - s.baseAddress();//XXX contig = TRUE always |
| 679 | //else |
| 680 | //address = payload.get_address() - s.baseAddress(); |
| 681 | |
| 682 | m_atomic.accessDone(address); |
| 683 | |
| 684 | uint32_t index = address / vci_param::nbytes; |
| 685 | ram_t *tab = m_contents[segIndex]; |
| 686 | unsigned int cur = tab[index]; |
| 687 | uint32_t mask = atou(payload.get_byte_enable_ptr(), (i * vci_param::nbytes)); |
| 688 | |
| 689 | tab[index] = (cur & ~mask) | (atou( payload.get_data_ptr(), (i * vci_param::nbytes) ) & mask); |
| 690 | |
| 691 | //std::cout << "[RAM " << m_tgtid << "] WRITE address = " << std::hex << (payload.get_address()+(i*vci_param::nbytes)) << " data = " << tab[index] << std::endl; |
| 692 | |
| 693 | } |
| 694 | |
| 695 | payload.set_response_status(tlm::TLM_OK_RESPONSE); |
| 696 | phase = tlm::BEGIN_RESP; |
| 697 | time = time + (nwords * UNIT_TIME); |
| 698 | |
| 699 | #if VCI_RAM_DEBUG |
| 700 | std::cout << "[RAM " << m_tgtid << "] Send to source "<< srcid << " a anwser packet " << pktid << " Time = " << time.value() << std::endl; |
| 701 | #endif |
| 702 | |
| 703 | p_vci_target->nb_transport_bw(payload, phase, time); |
| 704 | return tlm::TLM_COMPLETED; |
| 705 | } |
| 706 | break; |
| 707 | case soclib::tlmt::VCI_LINKED_READ_COMMAND: |
| 708 | { |
| 709 | #if VCI_RAM_DEBUG |
| 710 | std::cout << "[RAM " << m_tgtid << "] Receive from source " << srcid <<" a Locked Read packet "<< pktid << " Time = " << time.value() << std::endl; |
| 711 | #endif |
| 712 | |
| 713 | vci_param::addr_t address; |
| 714 | for (size_t i=0; i<nwords; i++){ |
| 715 | //if(payload.contig) |
| 716 | address = (payload.get_address()+(i*vci_param::nbytes)) - s.baseAddress();//XXX contig = TRUE always |
| 717 | //else |
| 718 | //address = payload.get_address() - s.baseAddress(); |
| 719 | |
| 720 | utoa(m_contents[segIndex][address / vci_param::nbytes], payload.get_data_ptr(),(i * vci_param::nbytes)); |
| 721 | |
| 722 | //std::cout << "[RAM " << m_tgtid << "] LOCKED READ address = " << std::hex << (payload.get_address()+(i*vci_param::nbytes)) << " data = " << m_contents[segIndex][address / vci_param::nbytes] << std::endl; |
| 723 | |
| 724 | m_atomic.doLoadLinked(address, srcid); |
| 725 | } |
| 726 | |
| 727 | payload.set_response_status(tlm::TLM_OK_RESPONSE); |
| 728 | phase = tlm::BEGIN_RESP; |
| 729 | time = time + (nwords * UNIT_TIME); |
| 730 | |
| 731 | #if VCI_RAM_DEBUG |
| 732 | std::cout << "[RAM " << m_tgtid << "] Send to source "<< srcid << " a anwser packet " << pktid << " Time = " << time.value() << std::endl; |
| 733 | #endif |
| 734 | |
| 735 | p_vci_target->nb_transport_bw(payload, phase, time); |
| 736 | return tlm::TLM_COMPLETED; |
| 737 | } |
| 738 | break; |
| 739 | case soclib::tlmt::VCI_STORE_COND_COMMAND: |
| 740 | { |
| 741 | #if VCI_RAM_DEBUG |
| 742 | std::cout << "[RAM " << m_tgtid << "] Receive from source " << srcid <<" a Store Conditionnel packet "<< pktid << " Time = " << time.value() << std::endl; |
| 743 | #endif |
| 744 | |
| 745 | vci_param::addr_t address; |
| 746 | for (size_t i=0; i<nwords; i++){ |
| 747 | //if(payload.contig) |
| 748 | address = (payload.get_address()+(i*vci_param::nbytes)) - s.baseAddress();//XXX contig = TRUE always |
| 749 | //else |
| 750 | //address = payload.get_address() - s.baseAddress(); |
| 751 | |
| 752 | if(m_atomic.isAtomic(address, srcid)){ |
| 753 | m_atomic.accessDone(address); |
| 754 | |
| 755 | uint32_t index = address / vci_param::nbytes; |
| 756 | ram_t *tab = m_contents[segIndex]; |
| 757 | unsigned int cur = tab[index]; |
| 758 | uint32_t mask = atou(payload.get_byte_enable_ptr(), (i * vci_param::nbytes)); |
| 759 | |
| 760 | tab[index] = (cur & ~mask) | (atou(payload.get_data_ptr(), (i * vci_param::nbytes)) & mask); |
| 761 | |
| 762 | //std::cout << "[RAM " << m_tgtid << "] STORE COND address = " << std::hex << (payload.get_address()+(i*vci_param::nbytes)) << " data = " << tab[index] << std::endl; |
| 763 | |
| 764 | utoa(0, payload.get_data_ptr(),(i * vci_param::nbytes)); |
| 765 | } |
| 766 | else{ |
| 767 | utoa(1, payload.get_data_ptr(),(i * vci_param::nbytes)); |
| 768 | } |
| 769 | } |
| 770 | |
| 771 | payload.set_response_status(tlm::TLM_OK_RESPONSE); |
| 772 | phase = tlm::BEGIN_RESP; |
| 773 | time = time + (nwords * UNIT_TIME); |
| 774 | |
| 775 | #if VCI_RAM_DEBUG |
| 776 | std::cout << "[RAM " << m_tgtid << "] Send to source "<< srcid << " a anwser packet " << pktid << " Time = " << time.value() << std::endl; |
| 777 | #endif |
| 778 | |
| 779 | p_vci_target->nb_transport_bw(payload, phase, time); |
| 780 | return tlm::TLM_COMPLETED; |
| 781 | } |
| 782 | break; |
| 783 | default: |
| 784 | break; |
| 785 | } |
| 786 | } |
| 787 | |
| 788 | //send error message |
| 789 | payload.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE); |
| 790 | |
| 791 | phase = tlm::BEGIN_RESP; |
| 792 | time = time + nwords * UNIT_TIME; |
| 793 | |
| 794 | #if VCI_RAM_DEBUG |
| 795 | std::cout << "[RAM " << m_tgtid << "] Address " << std::hex << payload.get_address() << std::dec << " does not match any segment " << std::endl; |
| 796 | std::cout << "[RAM " << m_tgtid << "] Send to source "<< srcid << " a error packet with time = " << time.value() << std::endl; |
| 797 | #endif |
| 798 | p_vci_target->nb_transport_bw(payload, phase, time); |
| 799 | return tlm::TLM_COMPLETED; |
| 800 | } |