Xilinx / libsystemctlm-soc

SystemC/TLM-2.0 Co-simulation framework
https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/862421112/Co-simulation
Other
222 stars 69 forks source link

Axi2Tlm bridge does not support narrow bursts #26

Open jnbrq opened 1 month ago

jnbrq commented 1 month ago

GetData and FillData functions in axi2tlm bridge shall be modified as the following (a similar problem was reported by #20 as well):


        template<typename T1, typename T2>
        void FillData(T1& wdata, T2& wstrb) {
            unsigned char* gp_data = m_gp->get_data_ptr();
            unsigned char* be = m_gp->get_byte_enable_ptr();
            std::uint64_t address = m_gp->get_address();
            std::uint8_t numberBytes = m_genattr->get_burst_width();
            std::uint64_t alignedAddress;

            unsigned int lower_byte_lane;
            unsigned int upper_byte_lane;
            unsigned int i;

            alignedAddress = Align(address, numberBytes);

            if (m_burstType == AXI_BURST_FIXED) {
                lower_byte_lane = address - Align(address, DATA_BUS_BYTES);
                upper_byte_lane = alignedAddress + (numberBytes - 1) - Align(address, DATA_BUS_BYTES);

                for (i = 0; i < DATA_BUS_BYTES; i++) {
                    if (i >= lower_byte_lane && i <= upper_byte_lane) {
                        int firstbit = i * 8;
                        int lastbit = firstbit + 8 - 1;

                        if (wstrb.read().bit(i)) {
                            be[m_dataIdx] = TLM_BYTE_ENABLED;
                            gp_data[m_dataIdx] = wdata.read().range(lastbit, firstbit).to_uint();
                        } else {
                            be[m_dataIdx] = TLM_BYTE_DISABLED;
                        }

                        m_dataIdx++;
                    }
                }
            } else {
                if (m_beat == 1) {
                    lower_byte_lane = address - Align(address, DATA_BUS_BYTES);
                    upper_byte_lane = alignedAddress + (numberBytes - 1) - Align(address, DATA_BUS_BYTES);
                } else {
                    std::uint64_t address = alignedAddress + ((m_beat - 1) * numberBytes);

                    lower_byte_lane = address - Align(address, DATA_BUS_BYTES);
                    upper_byte_lane = lower_byte_lane + (numberBytes - 1);
                }

                assert(lower_byte_lane < DATA_BUS_BYTES);
                assert(upper_byte_lane < DATA_BUS_BYTES);

                // Set data
                for (i = 0; i < DATA_BUS_BYTES; i++) {
                    if (i >= lower_byte_lane && i <= upper_byte_lane) {
                        if (wstrb.read().bit(i)) {
                            int firstbit = i * 8;
                            int lastbit = firstbit + 8 - 1;

                            assert(m_dataIdx < m_gp->get_data_length());
                            be[m_dataIdx] = TLM_BYTE_ENABLED;
                            gp_data[m_dataIdx++] = wdata.read().range(lastbit, firstbit).to_uint();
                        } else {
                            be[m_dataIdx++] = TLM_BYTE_DISABLED;
                        }
                    }
                }

            }
        }

        template<typename T>
        void GetData(T& data) {
            unsigned char* gp_data = m_gp->get_data_ptr();
            std::uint64_t address = m_gp->get_address();
            std::uint8_t numberBytes = m_genattr->get_burst_width();
            std::uint64_t alignedAddress;
            unsigned int lower_byte_lane;
            unsigned int upper_byte_lane;
            unsigned int i;

            alignedAddress = Align(address, numberBytes);

            if (m_burstType == AXI_BURST_FIXED) {
                lower_byte_lane = address - Align(address, DATA_BUS_BYTES);
                upper_byte_lane = alignedAddress + (numberBytes - 1) - Align(address, DATA_BUS_BYTES);

                for (i = 0; i < DATA_BUS_BYTES; i++) {
                    if (i >= lower_byte_lane && i <= upper_byte_lane) {
                        int firstbit = i * 8;
                        int lastbit = firstbit + 8 - 1;

                        data.range(lastbit, firstbit) = gp_data[m_dataIdx++];
                    }
                }
            } else {
                if (m_beat == 1) {
                    lower_byte_lane = address - Align(address, DATA_BUS_BYTES);
                    upper_byte_lane = alignedAddress + (numberBytes - 1) - Align(address, DATA_BUS_BYTES);
                } else {
                    std::uint64_t address = alignedAddress + ((m_beat - 1) * numberBytes);

                    lower_byte_lane = address - Align(address, DATA_BUS_BYTES);
                    upper_byte_lane = lower_byte_lane + (numberBytes - 1);
                }

                // Set data
                for (i = 0; i < DATA_BUS_BYTES; i++) {
                    if (i >= lower_byte_lane && i <= upper_byte_lane) {
                        int firstbit = i * 8;
                        int lastbit = firstbit + 8 - 1;

                        data.range(lastbit, firstbit) = gp_data[m_dataIdx++];
                    }
                }
            }
        }

A similar might appear in tlm2axi bridges; however, I have not checked them yet.