| 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 | } |