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

NV_NVDLA_cvif.cpp

bdma2cvif_wr_req_b_transport


// DMA read request target sockets

void NV_NVDLA_cvif::bdma2cvif_wr_req_b_transport(int ID, nvdla_dma_wr_req_t* payload, sc_time& delay) {
    
    
    uint32_t packet_id;
    uint8_t  *dma_payload_data_ptr;
    uint8_t  *data_ptr;
    uint32_t rest_size, incoming_size;
    client_cvif_wr_req_t * bdma_wr_req;

    packet_id = payload->tag;
    if (TAG_CMD == packet_id) {
    
    
        bdma_wr_req_count_ ++;
#pragma CTC SKIP
        if (true == has_bdma_onging_wr_req_) {
    
    
            FAIL(("NV_NVDLA_cvif::bdma2cvif_wr_req_b_transport, got two consective command request, one command request shall be followed by one or more data request."));
        }
#pragma CTC ENDSKIP
	else {
    
    
            has_bdma_onging_wr_req_ = true;
        }

        bdma_wr_req = new client_cvif_wr_req_t;
        bdma_wr_req->addr  = payload->pd.dma_write_cmd.addr;
        bdma_wr_req->size  = (payload->pd.dma_write_cmd.size + 1) * DMA_TRANSACTION_ATOM_SIZE;    //In byte
        bdma_wr_req->require_ack = payload->pd.dma_write_cmd.require_ack;
        cslDebug((50, "before write to bdma2cvif_wr_cmd_fifo_\x0A"));
        bdma2cvif_wr_cmd_fifo_->write(bdma_wr_req);
        cslDebug((50, "after write to bdma2cvif_wr_cmd_fifo_\x0A"));
        bdma_wr_req_got_size_ = 0;
        bdma_wr_req_size_ = bdma_wr_req->size;

    } else {
    
    
        dma_payload_data_ptr = reinterpret_cast <uint8_t *> (payload->pd.dma_write_data.data);
        rest_size = bdma_wr_req_size_ - bdma_wr_req_got_size_;
        incoming_size = min(rest_size, uint32_t (DMA_TRANSACTION_MAX_SIZE));
        data_ptr = new uint8_t[DMA_TRANSACTION_ATOM_SIZE];
        memcpy(data_ptr, dma_payload_data_ptr, DMA_TRANSACTION_ATOM_SIZE);
        cslDebug((50, "before write to bdma2cvif_wr_data_fifo_\x0A"));
        bdma2cvif_wr_data_fifo_->write(data_ptr);   // Write to FIFO in 32Byte atom
        cslDebug((50, "after write to bdma2cvif_wr_data_fifo_\x0A"));
        bdma_wr_req_got_size_ += incoming_size;
        for(int i = 0; i < DMA_TRANSACTION_ATOM_SIZE; i++) {
    
    
            cslDebug((50, "%x ", data_ptr[i]));
        }
        cslDebug((50, "\x0A"));
        if (incoming_size==DMA_TRANSACTION_MAX_SIZE) {
    
     // The payload is 64B
            data_ptr = new uint8_t[DMA_TRANSACTION_ATOM_SIZE];
            memcpy(data_ptr, &dma_payload_data_ptr[DMA_TRANSACTION_ATOM_SIZE], DMA_TRANSACTION_ATOM_SIZE);
            cslDebug((50, "write to bdma2cvif_wr_data_fifo_\x0A"));
            bdma2cvif_wr_data_fifo_->write(data_ptr);
            for(int i = 0; i < DMA_TRANSACTION_ATOM_SIZE; i++) {
    
    
                cslDebug((50, "%x ", data_ptr[i]));
            }
            cslDebug((50, "\x0A"));
        }

        if (bdma_wr_req_got_size_ == bdma_wr_req_size_) {
    
    
            has_bdma_onging_wr_req_ = false;
        }
    }
}

这段代码是用于处理来自BDMA(Batched Data Movement Accelerator)的写入请求(包括命令请求和数据请求)的函数。以下是代码的主要步骤:

  1. payload中获取请求的packet_id,用于判断是命令请求还是数据请求。

  2. 如果packet_idTAG_CMD,表示这是一个命令请求,执行以下步骤:

    • 增加bdma_wr_req_count_,表示已经接收到一个BDMA写入请求。
    • 检查是否已经存在一个正在进行的BDMA写入请求,如果已经存在,则报错,因为一个命令请求应该紧随一个或多个数据请求。
    • 如果没有正在进行的BDMA写入请求,则设置has_bdma_onging_wr_req_true,表示有一个正在进行的写入请求。
    • 创建一个client_cvif_wr_req_t结构体对象bdma_wr_req,并将命令请求的地址、大小和是否需要ACK等信息存储在该结构体中。
    • bdma_wr_req对象写入bdma2cvif_wr_cmd_fifo_中,通知CVIF有一个新的写入请求。
  3. 如果packet_id不是TAG_CMD,表示这是一个数据请求,执行以下步骤:

    • payload中获取DMA写入数据的指针dma_payload_data_ptr
    • 计算剩余数据大小rest_size,即待接收数据大小与已接收数据大小之差。
    • 计算本次接收数据的大小incoming_size,为剩余数据大小和DMA事务最大大小中的较小值。
    • 创建一个新的uint8_t类型数组data_ptr,用于存储接收的数据,大小为一个DMA事务原子大小(32字节)。
    • dma_payload_data_ptr复制incoming_size大小的数据到data_ptr中。
    • data_ptr写入bdma2cvif_wr_data_fifo_中,以32字节原子的方式写入数据。
    • 更新已接收的数据大小bdma_wr_req_got_size_,增加incoming_size
    • 如果本次接收的数据大小为DMA事务最大大小(64字节),则再次复制接收的数据(下一个32字节)到data_ptr中,并写入bdma2cvif_wr_data_fifo_中。
    • 如果已接收的数据大小等于待接收数据大小bdma_wr_req_size_,则表示当前写入请求已完成,将has_bdma_onging_wr_req_设置为false,表示没有正在进行的写入请求。

总之,这段代码用于处理来自BDMA的写入请求,包括命令请求和数据请求。命令请求用于指示写入操作的地址和大小等信息,而数据请求用于传输实际的写入数据。写入数据被分为32字节的原子,按照原子大小写入bdma2cvif_wr_data_fifo_中,以便后续处理。

WriteRequest_bdma2cvif


void NV_NVDLA_cvif::WriteRequest_bdma2cvif() {
    
    
    uint64_t base_addr;
    uint64_t first_base_addr;
    uint64_t last_base_addr;
    uint64_t cur_address;
    uint32_t size_in_byte;
    uint32_t total_axi_size;
    uint64_t payload_addr;
    uint32_t payload_size;
    uint8_t* axi_byte_enable_ptr;
    uint32_t byte_iter;
    uint32_t atom_iter;
    uint32_t atom_num;
    bool     is_base_64byte_align;
    bool     is_rear_64byte_align;
    bool     is_read=false;
    uint8_t  *axi_atom_ptr;
    nvdla_dbb_extension *nvdla_dbb_ext = NULL;
    client_cvif_wr_req_t   * bdma_wr_req;
    dla_b_transport_payload *bt_payload;

    while(true) {
    
    
        // Read one write command
        bdma_wr_req = bdma2cvif_wr_cmd_fifo_->read();
        payload_addr = bdma_wr_req->addr;   // It's aligend to 32B, not 64B
        payload_size = bdma_wr_req->size;
        cslDebug((50, "NV_NVDLA_cvif::WriteRequest_bdma2cvif, got one write command from bdma2cvif_wr_cmd_fifo_\x0A"));
        cslDebug((50, "    payload_addr: 0x%lx\x0A", payload_addr));
        cslDebug((50, "    payload_size: 0x%x\x0A", payload_size));

        is_base_64byte_align = payload_addr%AXI_TRANSACTION_ATOM_SIZE == 0;
        first_base_addr = is_base_64byte_align? payload_addr: payload_addr - DMA_TRANSACTION_ATOM_SIZE; // Align to 64B
        is_rear_64byte_align = (payload_addr + payload_size) % AXI_TRANSACTION_ATOM_SIZE == 0;
        // According to DBB_PV standard, data_length shall be equal or greater than DBB_PV m_size * m_length no matter the transactions is aglined or not
        total_axi_size = payload_size + (is_base_64byte_align? 0: DMA_TRANSACTION_ATOM_SIZE) + (is_rear_64byte_align? 0: DMA_TRANSACTION_ATOM_SIZE);
        last_base_addr = first_base_addr + total_axi_size - AXI_TRANSACTION_ATOM_SIZE;

这段代码用于从BDMA(Batched Data Movement Accelerator)读取写入请求命令,然后生成相应的AXI写入请求并将其发送到CVIF(Common Video Interface)。以下是代码的主要步骤:

  1. 无限循环:这个循环将持续从bdma2cvif_wr_cmd_fifo_中读取来自BDMA的写入请求命令。

  2. bdma2cvif_wr_cmd_fifo_中读取一个写入请求命令,并从命令中提取以下信息:

    • payload_addr:写入请求的起始地址,该地址按32字节(不是64字节)对齐。
    • payload_size:写入请求的数据大小,以字节为单位。
  3. 计算地址对齐:

    • 检查payload_addr是否按照64字节的AXI事务原子大小对齐,如果没有,则将first_base_addr设置为payload_addr - DMA_TRANSACTION_ATOM_SIZE,以确保地址按照64字节对齐。
    • 检查payload_addr + payload_size是否按照64字节对齐,如果没有,则在total_axi_size中添加适当的字节数,以确保数据区域的末尾也按照64字节对齐。
    • 计算last_base_addr,即数据区域的末尾地址,用于确定AXI事务的结束地址。
  4. 进入循环处理数据:

    • 循环处理每个AXI事务的原子(32字节)。
    • 创建一个新的AXI事务负载对象bt_payload,用于描述本次写入请求。
    • 设置AXI字节使能信号axi_byte_enable_ptr,以确定哪些字节将被写入。这些信息在写入数据到AXI总线时非常重要。
    • 根据是否是对齐的地址和是否是最后一个AXI事务来设置字节使能信号。根据注释,字节使能信号用于指示BDMA的字节是否需要被写入到CVIF。如果某个字节不需要写入,相应位置为TLM_BYTE_DISABLED
    • 配置bt_payload的基地址、大小和读写标志。
    • 获取nvdla_dbb_extension扩展对象,设置AXI ID和事务大小等信息。
    • 检查size_in_byte是否是AXI_TRANSACTION_ATOM_SIZE的倍数,如果不是,产生错误。
    • bt_payload写入bdma2cvif_wr_req_fifo_,将AXI事务请求发送到CVIF。
  5. 循环继续,处理下一个AXI事务的原子,直到处理完整个写入请求的数据。

总之,这段代码用于将来自BDMA的写入请求转换为AXI事务并将其发送到CVIF,以便CVIF可以将数据写入内存中的相应位置。在生成AXI事务时,代码确保地址按照64字节对齐,同时根据需要设置字节使能信号以确定是否需要写入每个字节的数据。

 // if ( total_axi_size <= AXI_TRANSACTION_ATOM_SIZE ) {
    
    
        //     // The first and last transaction is actually the same
        //     last_base_addr = first_base_addr;
        // } else {
    
    
        //     last_base_addr = (first_base_addr + total_axi_size) - (first_base_addr + total_axi_size)%AXI_TRANSACTION_ATOM_SIZE;
        // }
        // if (total_axi_size + first_base_addr%CVIF_MAX_MEM_TRANSACTION_SIZE <= CVIF_MAX_MEM_TRANSACTION_SIZE) {
    
    
        //     // Base and last are in the same AXI transaction
        // } else {
    
    
        //     // Base and last are in different AXI transaction
        //     last_base_addr = 
        // }
        // } else if ((first_base_addr + total_axi_size)%CVIF_MAX_MEM_TRANSACTION_SIZE != 0) {
    
    
        //     if (total_axi_size >= (first_base_addr + total_axi_size)%CVIF_MAX_MEM_TRANSACTION_SIZE) {
    
    
        //         last_base_addr = first_base_addr + total_axi_size - (first_base_addr + total_axi_size)%CVIF_MAX_MEM_TRANSACTION_SIZE;
        //     } else {
    
    
        //         last_base_addr = first_base_addr;
        //     }
        // } else {
    
    
        //     if (total_axi_size >= CVIF_MAX_MEM_TRANSACTION_SIZE) {
    
    
        //         last_base_addr = first_base_addr + total_axi_size - CVIF_MAX_MEM_TRANSACTION_SIZE;
        //     } else {
    
    
        //         last_base_addr = first_base_addr;
        //     }
        // }
        cslDebug((50, "NV_NVDLA_cvif::WriteRequest_bdma2cvif:\x0A"));
        cslDebug((50, "    first_base_addr: 0x%lx\x0A", first_base_addr));
        cslDebug((50, "    last_base_addr: 0x%lx\x0A", last_base_addr));
        cslDebug((50, "    total_axi_size: 0x%x\x0A", total_axi_size));

        // cur_address = payload_addr;
        cur_address = is_base_64byte_align? payload_addr: first_base_addr; // Align to 64B
        //Split dma request to axi requests
        // while(cur_address < payload_addr + payload_size) {}
        while(cur_address <= last_base_addr) {
    
    
            base_addr    = cur_address;
            size_in_byte = AXI_TRANSACTION_ATOM_SIZE;
            // Check whether next ATOM belongs to current AXI transaction
            // while (((cur_address + DMA_TRANSACTION_ATOM_SIZE) < (payload_addr + payload_size)) && ((cur_address + DMA_TRANSACTION_ATOM_SIZE) % CVIF_MAX_MEM_TRANSACTION_SIZE != 0)) {
    
    
            //     size_in_byte += DMA_TRANSACTION_ATOM_SIZE;
            //     cur_address  += DMA_TRANSACTION_ATOM_SIZE;
            // }
            while (((cur_address + AXI_TRANSACTION_ATOM_SIZE) < (first_base_addr + total_axi_size)) && ((cur_address + AXI_TRANSACTION_ATOM_SIZE) % CVIF_MAX_MEM_TRANSACTION_SIZE != 0)) {
    
    
                size_in_byte += AXI_TRANSACTION_ATOM_SIZE;
                cur_address  += AXI_TRANSACTION_ATOM_SIZE;
            }
            // start address of next axi transaction
            cur_address += AXI_TRANSACTION_ATOM_SIZE;

            atom_num = size_in_byte / DMA_TRANSACTION_ATOM_SIZE;

            bt_payload = new dla_b_transport_payload(size_in_byte, dla_b_transport_payload::DLA_B_TRANSPORT_PAYLOAD_TYPE_MC);
            axi_byte_enable_ptr = bt_payload->gp.get_byte_enable_ptr();
            cslDebug((50, "NV_NVDLA_cvif::WriteRequest_bdma2cvif, base_addr=0x%lx size_in_byte=0x%x atom_num=0x%x\x0A", base_addr, size_in_byte, atom_num));

            for (byte_iter=0; byte_iter < size_in_byte; byte_iter++) {
    
    
                if ( (base_addr == first_base_addr) && (false == is_base_64byte_align) && (byte_iter < DMA_TRANSACTION_ATOM_SIZE)) {
    
    
                    // Diable 1st DMA atom of the unaligned first_base_addr
                    axi_byte_enable_ptr[byte_iter] = TLM_BYTE_DISABLED;  // All bytes should be enabled
                } else if (( (base_addr + size_in_byte) == (last_base_addr+AXI_TRANSACTION_ATOM_SIZE)) && (false == is_rear_64byte_align) && (byte_iter >= size_in_byte - DMA_TRANSACTION_ATOM_SIZE)) {
    
    
                    // Diable 2nd DMA atom of the unaligned last_base_addr
                    axi_byte_enable_ptr[byte_iter] = TLM_BYTE_DISABLED;  // All bytes should be enabled
                } else {
    
    
                    axi_byte_enable_ptr[byte_iter] = TLM_BYTE_ENABLED;  // All bytes should be enabled
                }
            }
            cslDebug((50, "NV_NVDLA_cvif::WriteRequest_bdma2cvif, TLM_BYTE_ENABLE is done\x0A"));

这部分代码是在处理BDMA到CVIF的写入请求时,计算并分割AXI事务的逻辑。以下是主要步骤:

  1. 注释部分:代码包含一些注释,描述了在不同情况下如何计算last_base_addr,即AXI事务的结束地址。这部分代码用于处理AXI事务的边界情况,确保地址对齐。

  2. 初始化参数:初始化cur_addresspayload_addr,如果payload_addr不是64字节对齐,那么cur_address将被调整到64字节对齐的地址。然后进入一个循环,该循环将处理每个AXI事务。

  3. 计算AXI事务大小:代码在循环中计算每个AXI事务的大小(size_in_byte),并检查下一个原子是否属于当前AXI事务。循环条件用于检查下一个原子是否属于当前AXI事务,并根据需要增加size_in_byte

  4. 分配内存:为每个AXI事务创建一个新的dla_b_transport_payload对象(bt_payload),并为字节使能信号(axi_byte_enable_ptr)分配内存。

  5. 设置字节使能信号:根据不同情况设置字节使能信号,确保按照要求启用或禁用字节。具体逻辑是根据地址对齐、是否是第一个AXI事务、是否是最后一个AXI事务以及当前字节的位置来确定字节使能信号的值。

  6. 循环继续:循环继续处理下一个AXI事务,直到处理完整个写入请求的数据。

总之,这部分代码的主要功能是计算和分割AXI事务,以确保数据的正确传输。在生成每个AXI事务时,代码会检查地址对齐,并根据需要设置字节使能信号,以便正确地传输数据。这是确保写入请求在AXI总线上正确执行的关键步骤。


            for (atom_iter=0; atom_iter < atom_num; atom_iter++) {
    
    
                if ( (base_addr == first_base_addr) && (false == is_base_64byte_align) && (0 == atom_iter)) {
    
    
                    // Disable 1st DMA atom of the unaligned first_base_addr
                    // Use unaligned address as required by DBB_PV
                    memset(&bt_payload->data[atom_iter*DMA_TRANSACTION_ATOM_SIZE], 0, DMA_TRANSACTION_ATOM_SIZE);
                } else if (((base_addr + size_in_byte) == (last_base_addr+AXI_TRANSACTION_ATOM_SIZE)) && (false == is_rear_64byte_align) && ( (atom_iter + 1) == atom_num)) {
    
    
                    // Disable 2nd DMA atom of the unaligned last_base_addr
                    memset(&bt_payload->data[atom_iter*DMA_TRANSACTION_ATOM_SIZE], 0, DMA_TRANSACTION_ATOM_SIZE);
                } else {
    
    
                    cslDebug((50, "NV_NVDLA_cvif::WriteRequest_bdma2cvif, before read an atom from bdma2cvif_wr_data_fifo_, base_addr = 0x%lx, atom_iter=0x%x\x0A", base_addr, atom_iter));

                    axi_atom_ptr = bdma2cvif_wr_data_fifo_->read();
                    for(int i=0; i<DMA_TRANSACTION_ATOM_SIZE; i++) {
    
    
                        cslDebug((50, "%02x ", axi_atom_ptr[i]));
                    }
                    cslDebug((50, "\x0A"));
                    cslDebug((50, "NV_NVDLA_cvif::WriteRequest_bdma2cvif, after read an atom from bdma2cvif_wr_data_fifo_\x0A"));
                    memcpy(&bt_payload->data[atom_iter*DMA_TRANSACTION_ATOM_SIZE], axi_atom_ptr, DMA_TRANSACTION_ATOM_SIZE);
                    delete[] axi_atom_ptr;
                }
            }

            if ( (base_addr == first_base_addr) && (false == is_base_64byte_align) ) {
    
    
                base_addr += DMA_TRANSACTION_ATOM_SIZE;
            }
            cslDebug((50, "NV_NVDLA_cvif::WriteRequest_bdma2cvif, base_address=0x%lx size in byte=0x%x\x0A", base_addr, size_in_byte));
            // Prepare write payload
            bt_payload->configure_gp(base_addr, size_in_byte, is_read);
            bt_payload->gp.get_extension(nvdla_dbb_ext);
            cslDebug((50, "NV_NVDLA_cvif::WriteRequest_bdma2cvif, sending write command to bdma_wr_req_fifo_.\x0A"));
            cslDebug((50, "    addr: 0x%016lx\x0A", base_addr));
            cslDebug((50, "    size: %d\x0A", size_in_byte));
            nvdla_dbb_ext->set_id(BDMA_AXI_ID);
            nvdla_dbb_ext->set_size(64);
            nvdla_dbb_ext->set_length(size_in_byte/AXI_TRANSACTION_ATOM_SIZE);
            // if (base_addr%AXI_TRANSACTION_ATOM_SIZE != 0) //Set length(in unit of 64B) to be same as RTL
            //     nvdla_dbb_ext->set_length(((size_in_byte - DMA_TRANSACTION_ATOM_SIZE) + DMA_TRANSACTION_ATOM_SIZE)/AXI_TRANSACTION_ATOM_SIZE);
            // else // base_addr is aligned to 64Bytes
            //     nvdla_dbb_ext->set_length((size_in_byte + DMA_TRANSACTION_ATOM_SIZE)/AXI_TRANSACTION_ATOM_SIZE-1);

            // write payload to arbiter fifo
            bdma_wr_req_fifo_->write(bt_payload);

            // When the last split req is sent to ext, write true to bdma_wr_required_ack_fifo_ when ack is required.
            if (cur_address >= (payload_addr + payload_size)) {
    
    
                if(bdma_wr_req->require_ack!=0) {
    
    
                    cslDebug((50, "NV_NVDLA_cvif::WriteRequest_bdma2cvif, require ack.\x0A"));
                    bdma_wr_required_ack_fifo_->write(true);
                }
                else {
    
    
                    cslDebug((50, "NV_NVDLA_cvif::WriteRequest_bdma2cvif, does not require ack.\x0A"));
                    bdma_wr_required_ack_fifo_->write(false);
                }
            }
            else {
    
    
                cslDebug((50, "NV_NVDLA_cvif::WriteRequest_bdma2cvif, does not require ack.\x0A"));
                bdma_wr_required_ack_fifo_->write(false);
            }
        }
        delete bdma_wr_req;
        cslDebug((50, "NV_NVDLA_cvif::WriteRequest_bdma2cvif, write command processing done\x0A"));
    }
}

这段代码是处理BDMA到CVIF的写入请求的主要逻辑。以下是主要步骤:

  1. 循环遍历AXI事务:在一个循环中,该代码会处理每个AXI事务,每个事务都包括多个DMA原子。

  2. 检查是否需要禁用DMA原子:根据当前的AXI事务和地址对齐情况,代码会决定是否需要禁用DMA原子。如果是第一个AXI事务且未对齐,或者是最后一个AXI事务且未对齐,那么代码将通过memset函数将DMA原子的数据设置为0,以禁用这些不需要的DMA原子。

  3. 读取DMA原子数据:如果不需要禁用DMA原子,代码将从bdma2cvif_wr_data_fifo_中读取DMA原子的数据,并将其复制到bt_payload中相应的位置。

  4. 准备写入请求:设置bt_payload的其他字段,包括起始地址、大小、是否为读取请求等。

  5. 写入请求到FIFO:将bt_payload写入到bdma_wr_req_fifo_中,以便发送给CVIF。

  6. 处理是否需要ACK:根据当前AXI事务是否为最后一个,以及写入请求是否需要ACK,决定是否向bdma_wr_required_ack_fifo_写入true或false。

  7. 释放资源:释放用于存储BDMA写入请求的资源,并继续处理下一个AXI事务。

总之,这段代码负责将BDMA的写入请求转换成AXI事务,并将这些事务发送到CVIF,同时处理是否需要ACK。在处理每个AXI事务时,根据地址对齐情况,可能会禁用一些DMA原子,以确保数据传输的正确性。这是BDMA到CVIF写入请求的主要逻辑。

sdp2cvif_wr_req_b_transport


void NV_NVDLA_cvif::sdp2cvif_wr_req_b_transport(int ID, nvdla_dma_wr_req_t* payload, sc_time& delay) {
    
    
    uint32_t packet_id;
    uint8_t  *dma_payload_data_ptr;
    uint8_t  *data_ptr;
    uint32_t rest_size, incoming_size;
    client_cvif_wr_req_t * sdp_wr_req;

    packet_id = payload->tag;
    if (TAG_CMD == packet_id) {
    
    
        sdp_wr_req_count_ ++;
#pragma CTC SKIP
        if (true == has_sdp_onging_wr_req_) {
    
    
            FAIL(("NV_NVDLA_cvif::sdp2cvif_wr_req_b_transport, got two consective command request, one command request shall be followed by one or more data request."));
        }
#pragma CTC ENDSKIP
	else {
    
    
            has_sdp_onging_wr_req_ = true;
        }

        sdp_wr_req = new client_cvif_wr_req_t;
        sdp_wr_req->addr  = payload->pd.dma_write_cmd.addr;
        sdp_wr_req->size  = (payload->pd.dma_write_cmd.size + 1) * DMA_TRANSACTION_ATOM_SIZE;    //In byte
        sdp_wr_req->require_ack = payload->pd.dma_write_cmd.require_ack;
        cslDebug((50, "before write to sdp2cvif_wr_cmd_fifo_\x0A"));
        sdp2cvif_wr_cmd_fifo_->write(sdp_wr_req);
        cslDebug((50, "after write to sdp2cvif_wr_cmd_fifo_\x0A"));
        sdp_wr_req_got_size_ = 0;
        sdp_wr_req_size_ = sdp_wr_req->size;

    } else {
    
    
        dma_payload_data_ptr = reinterpret_cast <uint8_t *> (payload->pd.dma_write_data.data);
        rest_size = sdp_wr_req_size_ - sdp_wr_req_got_size_;
        incoming_size = min(rest_size, uint32_t (DMA_TRANSACTION_MAX_SIZE));
        data_ptr = new uint8_t[DMA_TRANSACTION_ATOM_SIZE];
        memcpy(data_ptr, dma_payload_data_ptr, DMA_TRANSACTION_ATOM_SIZE);
        cslDebug((50, "before write to sdp2cvif_wr_data_fifo_\x0A"));
        sdp2cvif_wr_data_fifo_->write(data_ptr);   // Write to FIFO in 32Byte atom
        cslDebug((50, "after write to sdp2cvif_wr_data_fifo_\x0A"));
        sdp_wr_req_got_size_ += incoming_size;
        for(int i = 0; i < DMA_TRANSACTION_ATOM_SIZE; i++) {
    
    
            cslDebug((50, "%x ", data_ptr[i]));
        }
        cslDebug((50, "\x0A"));
        if (incoming_size==DMA_TRANSACTION_MAX_SIZE) {
    
     // The payload is 64B
            data_ptr = new uint8_t[DMA_TRANSACTION_ATOM_SIZE];
            memcpy(data_ptr, &dma_payload_data_ptr[DMA_TRANSACTION_ATOM_SIZE], DMA_TRANSACTION_ATOM_SIZE);
            cslDebug((50, "write to sdp2cvif_wr_data_fifo_\x0A"));
            sdp2cvif_wr_data_fifo_->write(data_ptr);
            for(int i = 0; i < DMA_TRANSACTION_ATOM_SIZE; i++) {
    
    
                cslDebug((50, "%x ", data_ptr[i]));
            }
            cslDebug((50, "\x0A"));
        }

        if (sdp_wr_req_got_size_ == sdp_wr_req_size_) {
    
    
            has_sdp_onging_wr_req_ = false;
        }
    }
}

这段代码是处理SDP(Scalar Data Processor)到CVIF的写入请求的逻辑。下面是主要步骤:

  1. 获取请求类型:首先,代码会检查请求类型,即命令(TAG_CMD)还是数据(TAG_DATA),这是通过查看payload->tag来确定的。

  2. 处理命令请求:如果是命令请求,代码会进行如下操作:

    • 增加SDP写入请求计数器。
    • 检查是否已经有正在处理的SDP写入请求,如果有,则报错,因为一个命令请求应该紧随在一个或多个数据请求之后。
    • 创建一个client_cvif_wr_req_t结构体来存储请求的地址、大小和是否需要ACK。
    • 将该结构体写入sdp2cvif_wr_cmd_fifo_,这是一个FIFO队列,用于存储写入请求。
    • 初始化SDP写入请求的已接收大小(sdp_wr_req_got_size_)和总大小(sdp_wr_req_size_)。
  3. 处理数据请求:如果是数据请求,代码会进行如下操作:

    • payload->pd.dma_write_data.data中获取DMA数据的指针。
    • 计算未处理的数据大小(rest_size)以及要处理的数据大小(incoming_size),这取决于已接收大小和总大小之间的差异。
    • 创建一个长度为DMA_TRANSACTION_ATOM_SIZEdata_ptr数组,将DMA数据的一部分复制到其中。
    • data_ptr数组写入sdp2cvif_wr_data_fifo_,这是一个FIFO队列,用于存储写入数据。
    • 更新已接收大小(sdp_wr_req_got_size_)。
    • 如果数据大小等于DMA_TRANSACTION_MAX_SIZE,表示这个Payload是64字节,需要处理第二个DMA原子的数据,同样地将其写入FIFO。
  4. 检查请求完成:检查已接收的数据大小是否等于总大小,如果是,则表示请求处理完成,将has_sdp_onging_wr_req_标志设置为false,表示没有正在处理的SDP写入请求。

总的来说,这段代码是将SDP到CVIF的写入请求转换为CVIF可以处理的格式,并将这些请求放入相应的FIFO队列中,以便进一步处理和传输。同时,它还处理了命令请求和数据请求的区别,以确保请求被正确地处理和组织。

猜你喜欢

转载自blog.csdn.net/lincolnjunior_lj/article/details/132835559
98