NVDLA系列之C-model:cvif<102>

ext2cvif_rd_rsp_b_transport

void NV_NVDLA_cvif::ext2cvif_rd_rsp_b_transport(int ID, tlm::tlm_generic_payload& tlm_gp, sc_time& delay) {
    
    
    uint32_t            dma_sent_size;              // 存储已发送的 DMA 数据大小
    uint8_t*            axi_data_ptr;               // 指向 AXI 数据的指针
    uint32_t            axi_length;                 // AXI 数据的长度
    uint8_t*            axi_byte_enable_ptr;        // 指向 AXI 字节使能的指针
    uint32_t            axi_byte_enable_length;     // AXI 字节使能的长度
    uint8_t             axi_id;                     // AXI 事务的 ID
    uint8_t             dma_payload_atom_mask;      // 用于表示 DMA 数据的掩码
    nvdla_dbb_extension *nvdla_dbb_ext = NULL;     // NVDLA 数据总线扩展
    uint8_t           * axi_atom_ptr;               // 指向当前 AXI 原子事务的指针
    uint32_t            idx;                        // 用于循环迭代的索引

    // 获取 NVDLA 数据总线扩展
    tlm_gp.get_extension(nvdla_dbb_ext);

    // 如果没有找到 NVDLA 数据总线扩展,报错并终止仿真
    if(!nvdla_dbb_ext) {
    
    
        FAIL(("NV_NVDLA_cvif::ext2cvif_rd_rsp_b_transport, DBB extension is required, ar_id is needed to forward data to corresponding DMA."));
    }

    // 获取 AXI 数据相关信息
    axi_data_ptr           =  tlm_gp.get_data_ptr();
    axi_length             =  tlm_gp.get_data_length();
    axi_byte_enable_ptr    =  tlm_gp.get_byte_enable_ptr();
    axi_byte_enable_length =  tlm_gp.get_byte_enable_length();
    axi_id                 =  nvdla_dbb_ext->get_id();

    // 检查 AXI 事务长度是否符合要求
    if (axi_length > CVIF_MAX_MEM_TRANSACTION_SIZE) {
    
    
        FAIL(("NV_NVDLA_cvif::ext2cvif_rd_rsp_b_transport, Max AXI transaction length is %d byte, current AXI transaction length is %d byte", CVIF_MAX_MEM_TRANSACTION_SIZE, axi_length));
    }
    if (0 != (axi_length%DMA_TRANSACTION_ATOM_SIZE)) {
    
    
        FAIL(("NV_NVDLA_cvif::ext2cvif_rd_rsp_b_transport, AXI transaction length shall be an integral multiple of %d byte, current AXI transaction length is %d byte", DMA_TRANSACTION_ATOM_SIZE, axi_length));
    }

    // 遍历 AXI 数据并生成 DMA 响应
    dma_sent_size = 0;
    for (dma_sent_size = 0; dma_sent_size < axi_length; dma_sent_size += DMA_TRANSACTION_ATOM_SIZE) {
    
    
        switch (axi_id) {
    
    
            // 根据 AXI ID 选择对应的 FIFO
            case BDMA_AXI_ID:
                dma_payload_atom_mask = (true == bdma_rd_atom_enable_fifo_->read()) ? 0x1 : 0;
                break;
            case SDP_AXI_ID:
                dma_payload_atom_mask = (true == sdp_rd_atom_enable_fifo_->read()) ? 0x1 : 0;
                break;
            case PDP_AXI_ID:
                dma_payload_atom_mask = (true == pdp_rd_atom_enable_fifo_->read()) ? 0x1 : 0;
                break;
            case CDP_AXI_ID:
                dma_payload_atom_mask = (true == cdp_rd_atom_enable_fifo_->read()) ? 0x1 : 0;
                break;
            case RBK_AXI_ID:
                dma_payload_atom_mask = (true == rbk_rd_atom_enable_fifo_->read()) ? 0x1 : 0;
                break;
            case SDP_B_AXI_ID:
                dma_payload_atom_mask = (true == sdp_b_rd_atom_enable_fifo_->read()) ? 0x1 : 0;
                break;
            case SDP_N_AXI_ID:
                dma_payload_atom_mask = (true == sdp_n_rd_atom_enable_fifo_->read()) ? 0x1 : 0;
                break;
            case SDP_E_AXI_ID:
                dma_payload_atom_mask = (true == sdp_e_rd_atom_enable_fifo_->read()) ? 0x1 : 0;
                break;
            case CDMA_DAT_AXI_ID:
                dma_payload_atom_mask = (true == cdma_dat_rd_atom_enable_fifo_->read()) ? 0x1 : 0;
                break;
            case CDMA_WT_AXI_ID:
                dma_payload_atom_mask = (true == cdma_wt_rd_atom_enable_fifo_->read()) ? 0x1 : 0;
                break;
            default:
                FAIL(("NV_N

VDLA_cvif::ext2cvif_rd_rsp_b_transport, unexpected AXI ID"));
        }

        // 如果 DMA 数据掩码为 1,则将当前 AXI 原子事务写入对应的 FIFO
        if (0x1 == dma_payload_atom_mask) {
    
    
            axi_atom_ptr = new uint8_t[DMA_TRANSACTION_ATOM_SIZE];
            memcpy (axi_atom_ptr, &axi_data_ptr[dma_sent_size], DMA_TRANSACTION_ATOM_SIZE);

            // 根据 AXI ID 写入不同的 FIFO
            switch (axi_id) {
    
    
                case BDMA_AXI_ID:
                    cvif2bdma_rd_rsp_fifo_->write(axi_atom_ptr);
                    break;
                case SDP_AXI_ID:
                    cvif2sdp_rd_rsp_fifo_->write(axi_atom_ptr);
                    break;
                case PDP_AXI_ID:
                    cvif2pdp_rd_rsp_fifo_->write(axi_atom_ptr);
                    break;
                case CDP_AXI_ID:
                    cvif2cdp_rd_rsp_fifo_->write(axi_atom_ptr);
                    break;
                case RBK_AXI_ID:
                    cvif2rbk_rd_rsp_fifo_->write(axi_atom_ptr);
                    break;
                case SDP_B_AXI_ID:
                    cvif2sdp_b_rd_rsp_fifo_->write(axi_atom_ptr);
                    break;
                case SDP_N_AXI_ID:
                    cvif2sdp_n_rd_rsp_fifo_->write(axi_atom_ptr);
                    break;
                case SDP_E_AXI_ID:
                    cvif2sdp_e_rd_rsp_fifo_->write(axi_atom_ptr);
                    break;
                case CDMA_DAT_AXI_ID:
                    cvif2cdma_dat_rd_rsp_fifo_->write(axi_atom_ptr);
                    break;
                case CDMA_WT_AXI_ID:
                    cvif2cdma_wt_rd_rsp_fifo_->write(axi_atom_ptr);
                    break;
                default:
                    FAIL(("NV_NVDLA_cvif::ext2cvif_rd_rsp_b_transport, unexpected AXI ID"));
            }
        } else {
    
    
            cslDebug((50, "NV_NVDLA_cvif::ext2cvif_rd_rsp_b_transport, {client} payload atom mask is 0x0, ignore current atom, dma_payload_atom_mask is 0x%x\x0A", uint32_t(dma_payload_atom_mask)));
        }
    }

    // 设置响应状态为 TLM_OK_RESPONSE
    tlm_gp.set_response_status(tlm::TLM_OK_RESPONSE);
}

函数总结

  • 函数名称:ext2cvif_rd_rsp_b_transport
  • 参数:ID(整数)、tlm_generic_payload(泛型传输对象的引用)、delay(时间延迟)
  • 返回值:无
  • 功能:此函数用于处理外部数据到 CVIF 模块的读响应传输。它从传输对象中提取数据,根据 AXI ID 选择相应的 FIFO 并写入数据。函数还包含错误检查和日志记录的逻辑。

这个函数是处理硬件设计中的数据传输的一部分,根据 AXI ID 将数据写入不同的 FIFO 中,以便后续处理。它还包含了一些错误检查,以确保数据的完整性和一致性。函数注释提供了对函数的详细说明和各个变量的用途解释。

ext2cvif_wr_rsp_b_transport

void NV_NVDLA_cvif::ext2cvif_wr_rsp_b_transport(int ID, tlm::tlm_generic_payload& tlm_gp, sc_time& delay) {
    
    
    uint8_t             axi_id;                    // 存储 AXI 事务的 ID
    nvdla_dbb_extension *nvdla_dbb_ext = NULL;     // NVDLA 数据总线扩展
    cslDebug((50, "NV_NVDLA_cvif::ext2cvif_wr_rsp_b_transport.\x0A"));

    // 获取 DBB 扩展
    tlm_gp.get_extension(nvdla_dbb_ext);

    // 如果没有找到 NVDLA 数据总线扩展,报错并终止仿真
    if(!nvdla_dbb_ext) {
    
    
        FAIL(("NV_NVDLA_cvif::ext2cvif_wr_rsp_b_transport, DBB extension is required, ar_id is needed to forward data to corresponding DMA."));
    }

    // 获取 AXI ID
    axi_id  = nvdla_dbb_ext->get_id();

    // 根据 AXI ID 处理响应
    switch (axi_id) {
    
    
        case BDMA_AXI_ID:
            bdma_wr_rsp_count_++;
            // 从 FIFO 读取新请求的 ack
            bdma_wr_req_expected_ack = bdma_wr_required_ack_fifo_->read();
            if (true == bdma_wr_req_expected_ack) {
    
    
                cslDebug((50, "send wr rsp to bdma\x0A"));
                NV_NVDLA_cvif_base::cvif2bdma_wr_rsp.write(true);
            } else {
    
    
                // NV_NVDLA_cvif_base::cvif2bdma_wr_rsp.write(false);
            }
            break;
        case SDP_AXI_ID:
            sdp_wr_rsp_count_++;
            // 从 FIFO 读取新请求的 ack
            sdp_wr_req_expected_ack = sdp_wr_required_ack_fifo_->read();
            if (true == sdp_wr_req_expected_ack) {
    
    
                cslDebug((50, "send wr rsp to sdp\x0A"));
                NV_NVDLA_cvif_base::cvif2sdp_wr_rsp.write(true);
            } else {
    
    
                // NV_NVDLA_cvif_base::cvif2sdp_wr_rsp.write(false);
            }
            break;
        case PDP_AXI_ID:
            pdp_wr_rsp_count_++;
            // 从 FIFO 读取新请求的 ack
            pdp_wr_req_expected_ack = pdp_wr_required_ack_fifo_->read();
            if (true == pdp_wr_req_expected_ack) {
    
    
                cslDebug((50, "send wr rsp to pdp\x0A"));
                NV_NVDLA_cvif_base::cvif2pdp_wr_rsp.write(true);
            } else {
    
    
                // NV_NVDLA_cvif_base::cvif2pdp_wr_rsp.write(false);
            }
            break;
        case CDP_AXI_ID:
            cdp_wr_rsp_count_++;
            // 从 FIFO 读取新请求的 ack
            cdp_wr_req_expected_ack = cdp_wr_required_ack_fifo_->read();
            if (true == cdp_wr_req_expected_ack) {
    
    
                cslDebug((50, "send wr rsp to cdp\x0A"));
                NV_NVDLA_cvif_base::cvif2cdp_wr_rsp.write(true);
            } else {
    
    
                // NV_NVDLA_cvif_base::cvif2cdp_wr_rsp.write(false);
            }
            break;
        case RBK_AXI_ID:
            rbk_wr_rsp_count_++;
            // 从 FIFO 读取新请求的 ack
            rbk_wr_req_expected_ack = rbk_wr_required_ack_fifo_->read();
            if (true == rbk_wr_req_expected_ack) {
    
    
                cslDebug((50, "send wr rsp to rbk\x0A"));
                NV_NVDLA_cvif_base::cvif2rbk_wr_rsp.write(true);
            } else {
    
    
                // NV_NVDLA_cvif_base::cvif2rbk_wr_rsp.write(false);
            }
            break;
#pragma CTC SKIP
        default:
            FAIL(("NV_NVDLA_cvif::ext2cvif_wr_rsp_b_transport, unexpected AXI ID"));
#pragma CTC ENDSKIP
    }
    
    // 设置响应状态为 TLM_OK_RESPONSE
    tlm_gp.set_response_status(tlm::TLM_OK_RESPONSE);
}

函数总结

  • 函数名称:ext2cvif_wr_rsp_b_transport
  • 参数:ID(整数)、tlm_generic_payload(泛型传输对象的引用)、delay(时间延迟)
  • 返回值:无
  • 功能:此函数用于处理外部数据到 CVIF 模块的写响应传输。它从传输对象中提取数据,根据 AXI ID 决定是否向相应的 FIFO 中写入响应信号。函数还包含错误检查和日志记录的逻辑。
    这个函数主要用于处理来自硬件设计的写响应传输。根据 AXI ID,它选择适当的 FIFO 并发送写响应信号。函数还包含了一些错误检查,以确保数据的完整性和一致性。

ReadRequestArbiter

void NV_NVDLA_cvif::ReadRequestArbiter() {
    
    
    // 定义各个模块的就绪信号
    bool bdma_ready, cdma_dat_ready, cdma_wt_ready, sdp_ready, pdp_ready, cdp_ready;
    bool rbk_ready, sdp_b_ready, sdp_n_ready, sdp_e_ready;

    while (true) {
    
    
        // 如果 bdma_rd_req_payload_ 为空,从 bdma_rd_req_fifo_ 读取一个请求
        if (bdma_rd_req_payload_ == NULL) {
    
    
            bdma_rd_req_fifo_->nb_read(bdma_rd_req_payload_);
        }

        // 如果 bdma_rd_req_payload_ 不为空,检查是否有足够的信用来处理该请求
        if (bdma_rd_req_payload_ != NULL) {
    
    
            int payload_size = bdma_rd_req_payload_->gp.get_data_length();
            int atom_num = payload_size / DMA_TRANSACTION_ATOM_SIZE;
            if (credit_cvif2bdma_rd_rsp_fifo_ >= atom_num) {
    
    
                bdma_ready = true;
            } else {
    
    
                bdma_ready = false;
            }
        } else {
    
    
            bdma_ready = false;
        }

        // 重复上述过程,检查其他模块的请求和就绪状态
        // 这里包括 cdma_dat, cdma_wt, sdp, pdp, cdp, rbk, sdp_b, sdp_n, sdp_e

        // 如果没有任何模块有待处理的请求,进入等待状态
        if (!cdma_dat_ready && !cdma_wt_ready && !bdma_ready && !sdp_ready &&
            !pdp_ready && !cdp_ready && !rbk_ready && !sdp_b_ready && !sdp_n_ready && !sdp_e_ready) {
    
    
            cslDebug((50, "NV_NVDLA_cvif::ReadRequestArbiter, no pending request, waiting.\x0A"));
            wait();
            cslDebug((50, "NV_NVDLA_cvif::ReadRequestArbiter, get new request, wake up.\x0A"));
        }

        // 处理各个模块的读请求
        // 对于每个模块,检查请求是否有效并有足够的信用,然后将请求传递给相应的外部模块

        // 处理 BDMA 模块的读请求
        if (bdma_rd_req_payload_ != NULL) {
    
    
            int payload_size = bdma_rd_req_payload_->gp.get_data_length();
            uint8_t* axi_byte_enable_ptr = bdma_rd_req_payload_->gp.get_byte_enable_ptr();
            int atom_num = 0;
            for (int i = 0; i < payload_size / DMA_TRANSACTION_ATOM_SIZE; i++) {
    
    
                atom_num += axi_byte_enable_ptr[i * DMA_TRANSACTION_ATOM_SIZE] == TLM_BYTE_ENABLED;
            }
            if (credit_cvif2bdma_rd_rsp_fifo_ >= atom_num) {
    
    
                credit_cvif2bdma_rd_rsp_fifo_ -= atom_num;
                cslDebug((50, "NV_NVDLA_cvif::ReadRequestArbiter, send read request, payload from bdma, begin, atom:%d, num_free:%d credit_cvif2bdma_rd_rsp_fifo_=%d.\x0A", atom_num, cvif2bdma_rd_rsp_fifo_->num_free(), credit_cvif2bdma_rd_rsp_fifo_));

                cvif2ext_rd_req->b_transport(bdma_rd_req_payload_->gp, axi_delay_);
                cslDebug((50, "NV_NVDLA_cvif::ReadRequestArbiter, send read request, payload from bdma, end.\x0A"));
                delete bdma_rd_req_payload_;
                bdma_rd_req_payload_ = NULL;
            }
        }

        // 类似地,处理其他模块的读请求,如 SDP、PDP、CDP、RBK 和 SDP_B、SDP_N、SDP_E

        // 删除已经处理的请求,释放内存
    }
}

函数总结

  • 函数名称:NV_NVDLA_cvif::ReadRequestArbiter
  • 参数:无
  • 返回值:无
  • 功能:此函数是一个无限循环,用于处理各个外部模块的读请求。它检查每个模块的请求是否有效,并根据模块的就绪状态和信用来决定是否传递请求到外部模块。函数包括 BDMA、CDMA 数据、CDMA 权重、SDP、PDP、CDP、RBK、SDP_B、SDP_N 和 SDP_E 模块的请求处理逻辑。如果没有待处理的请求,函数将进入等待状态。此外,函数还负责删除已经处理的请求以释放内存。

WriteRequestArbiter

void NV_NVDLA_cvif::WriteRequestArbiter() {
    
    
    // 定义一个指向写请求的指针
    dla_b_transport_payload *payload;

    while (true) {
    
    
        cslDebug((50, "Calling WriteRequestArbiter\x0A"));

        // 如果所有外部模块的写请求 FIFO 都为空,则进入等待状态
        if ((bdma_wr_req_fifo_->num_available() == 0) && 
            (rbk_wr_req_fifo_->num_available() == 0) && 
            (sdp_wr_req_fifo_->num_available() == 0) && 
            (pdp_wr_req_fifo_->num_available() == 0) && 
            (cdp_wr_req_fifo_->num_available() == 0)) {
    
    
            wait();
        }

        // 处理各个外部模块的写请求

        // 处理 BDMA 模块的写请求
        if (bdma_wr_req_fifo_->nb_read(payload)) {
    
    
            cslDebug((50, "NV_NVDLA_cvif::WriteRequestArbiter, send write request, payload from bdma.\x0A"));
            cvif2ext_wr_req->b_transport(payload->gp, axi_delay_);
            delete payload;
        }
        
        // 类似地,处理其他外部模块的写请求,如 SDP、PDP、CDP 和 RBK

        // 删除已经处理的请求,释放内存
    }
}

函数总结

  • 函数名称:NV_NVDLA_cvif::WriteRequestArbiter
  • 参数:无
  • 返回值:无
  • 功能:此函数是一个无限循环,用于处理各个外部模块的写请求。它检查每个模块的写请求 FIFO 是否为空,如果不为空,则将请求传递给外部模块。函数包括 BDMA、SDP、PDP、CDP 和 RBK 模块的写请求处理逻辑。如果所有模块的写请求 FIFO 都为空,则函数将进入等待状态。此外,函数还负责删除已经处理的请求以释放内存。

猜你喜欢

转载自blog.csdn.net/lincolnjunior_lj/article/details/134991008