지노랩 /JinoLab

[UVM] 3.5.3 연속적인 난수 트랜잭션 가져오기 (Fetching Consecutive Randomized Items) 본문

UVM(Universal Verification Methodology)/3. 재사용 가능한 검증 컴포넌트 개발(Developing Reusabl

[UVM] 3.5.3 연속적인 난수 트랜잭션 가져오기 (Fetching Consecutive Randomized Items)

지노랩/JinoLab 2025. 3. 13. 13:35

3.5.3 연속적인 난수 트랜잭션 가져오기 (Fetching Consecutive Randomized Items)

3.5.3.1 개요

  • 일부 프로토콜(예: 파이프라인 기반 프로토콜)에서는 여러 개의 트랜잭션을 동시에 처리해야 할 수 있음.
  • 그러나, 기본적으로 UVM의 시퀀서-드라이버 연결은 한 번에 하나의 아이템을 주고받는 방식으로 설계됨.
  • 즉, 하나의 트랜잭션을 처리한 후에야 다음 트랜잭션을 받을 수 있음.
  • 파이프라인 프로토콜을 처리하기 위해, 응답을 즉시 제공하지 않고, 후속 호출에서 응답을 제공하는 방식이 필요함.
  • 이를 위해 item_done()을 먼저 호출하여 핸드셰이크를 완료하고, 이후 put_response(r)를 호출하여 응답 데이터를 전달할 수 있다.

3.5.3.2 기본 핸드셰이크 방식

  • 기본적으로 get_next_item()을 호출하면, 드라이버는 트랜잭션을 받아 실행한 후 item_done()을 호출.
  • 이 방식에서는 트랜잭션이 완료된 후에야 새로운 트랜잭션을 받을 수 있음.
forever begin
    get_next_item(req);  // 다음 트랜잭션 가져오기
    execute_transaction(req);  // 트랜잭션 실행
    item_done();  // 트랜잭션 완료 신호 전송
end
  • 위 코드는 하나의 트랜잭션을 실행하고 나서야 새로운 트랜잭션을 가져올 수 있음.
  • 하지만, 파이프라인 방식에서는 여러 개의 트랜잭션을 동시에 실행해야 하므로, 이 방식은 적합하지 않음.

3.5.3.3 응답을 나중에 제공하는 방식

  • 파이프라인 프로토콜에서는 트랜잭션 실행과 응답 전송이 분리되어야 함.
  • 이를 위해 트랜잭션 실행 직후 item_done()을 호출하고, 후속 호출에서 put_response(r)를 이용해 응답을 제공.
forever begin
    get_next_item(req);   // 트랜잭션 가져오기
    execute_transaction(req);  // 트랜잭션 실행
    item_done();   // 핸드셰이크 완료 (응답 없이)
    store_response(req);  // 실행 결과를 저장
end
  • 위 코드에서는 트랜잭션 실행 후 item_done()을 호출하여 다음 트랜잭션을 받을 준비를 함.
  • 하지만, 응답을 즉시 제공하지 않고 별도의 저장소(store_response())에 저장함.

3.5.3.4 put_response()를 이용한 응답 제공

  • 나중에 응답을 제공해야 할 때, put_response(r) 메서드를 사용함.
  • 이를 통해 트랜잭션 실행과 응답 전송을 분리할 수 있음.
forever begin
    get_next_item(req);   // 트랜잭션 가져오기
    execute_transaction(req);  // 트랜잭션 실행
    item_done();   // 핸드셰이크 완료
    store_response(req);  // 응답을 저장
end

// 후속 프로세스에서 응답을 제공
forever begin
    wait_for_response();
    put_response(retrieve_response());  // 저장된 응답을 전송
end
  • 첫 번째 루프에서는 트랜잭션을 실행하고 item_done()을 호출하지만, 응답을 즉시 제공하지 않음.
  • 두 번째 루프에서는 응답을 보낼 시점이 되면 put_response(retrieve_response())을 호출하여 저장된 응답을 전송.

3.5.3.5 예제 코드

다음은 파이프라인 방식으로 동작하는 드라이버 예제이다.

class pipeline_driver extends uvm_driver #(simple_item);
    `uvm_component_utils(pipeline_driver)

    simple_item req;
    simple_rsp rsp;
    bit [3:0] response_queue[$];  // 응답을 저장하는 큐

    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction

    task run_phase(uvm_phase phase);
        forever begin
            seq_item_port.get_next_item(req);
            drive_transaction(req);  // 트랜잭션 실행
            item_done();  // 핸드셰이크 완료
            store_response(req);  // 응답 저장
        end
    endtask

    task response_phase();
        forever begin
            wait_for_response_ready();
            rsp = retrieve_response();
            seq_item_port.put_response(rsp);  // 저장된 응답 전송
        end
    endtask
endclass
  • run_phase()에서 트랜잭션을 실행하고 item_done()을 호출하지만, 응답을 바로 전송하지 않음.
  • response_phase()에서 응답을 나중에 put_response()를 사용하여 제공.

✅ 3.5.3 요약

  • 기본적으로 UVM의 시퀀서-드라이버 연결은 한 번에 하나의 트랜잭션을 처리하는 방식.
  • 파이프라인 방식의 프로토콜에서는 여러 개의 트랜잭션을 동시에 처리해야 하므로, 트랜잭션 실행과 응답 전송을 분리해야 함.
  • 이를 위해 item_done()을 먼저 호출하고, 후속 호출에서 put_response(r)를 이용해 응답을 제공하는 방식이 필요함.
  • 이 방식을 사용하면, 드라이버가 여러 개의 트랜잭션을 동시에 처리하면서도, 올바르게 응답을 제공할 수 있음.

 

 

 


 

본 내용은
accellera에서 공개한
Universal Verification Methodology
(UVM) 1.2 User's Guide
를 바탕으로 작성된 글입니다.