TLM (Transaction Level Modeling) is how UVM components talk to each other. Instead of connecting wires, they call functions.
Analysis Ports: Broadcasting to Multiple Subscribers
(마이크/송신기): 데이터를 처음 만들어내서 밖으로 쏘는 출발점. (Monitor)
// Inside the Monitor
class sy_monitor extends uvm_monitor;
`uvm_component_utils(sy_monitor)
virtual axi4_lite_if vif;
// Analysis Port to send captured transactions to the Scoreboard
uvm_analysis_port #(sy_transaction) item_collected_port;
// Run Phase
virtual task run_phase(uvm_phase phase);
forever begin
fork
collect_write_tx();
collect_read_tx();
join
end
endtask
task collect_write_tx();
sy_transaction tx;
forever begin
do begin
@(posedge vif.clk);
end while (!(vif.bvalid && vif.bready));
item_collected_port.write(tx);
end
endtask
Monitor에 선언된 port는 데이터를 밖으로 쏘아 보내는 Broadcaster (송신자) 역할만 합니다.
특징: Monitor는 자신이 보낸 데이터를 누가 받는지, 몇 명이 받는지(Scoreboard 1명인지, Coverage Collector까지 2명인지) 전혀 신경 쓰지 않습니다. 그저 데이터가 캡처되면 허공에 대고 방송을 송출할 뿐입니다.
문법 설명: uvm_analysis_port #(sy_transaction)
여기서 파라미터가 1개인 이유는, 방송국 입장에서는 "내가 어떤 형태의 데이터(Transaction)를 보낼 것인가?"만 알면 되기 때문입니다.
동작: Monitor 코드 안에서 item_collected_port.write(tx);를 호출하는 순간, 이 포트를 통해 데이터가 밖으로 뿌려집니다.
(스피커): 데이터가 최종적으로 도착해서 소리를 내는(write 함수 실행) 종착점. (Scoreboard)
This is what the Scoreboard or Coverage Collector uses to receive transactions. It implements the write() function.
Scoreboard에 선언된 imp는 날아온 데이터를 받아내는 Receiver (수신자) 역할입니다. 여기서 imp는 Implementation (구현)의 약자입니다.
// in scoreboard
class sy_scoreboard extends uvm_scoreboard;
`uvm_component_utils(sy_scoreboard)
// Analysis Export to receive data from the Monitor
uvm_analysis_imp #(sy_transaction, sy_scoreboard) item_collected_export;
virtual function void write(sy_transaction tx);
... // 여기에 비교 로직 들어감
endfunction
특징: 포트로 데이터가 들어오면, "이 데이터를 받아서 어떻게 처리할지 내가 직접 행동(Implementation)을 정의하겠다"는 뜻입니다. 그래서 Scoreboard 클래스 안에는 반드시 write 함수가 구현(Implemented)되어 있어야 합니다.
문법 설명: uvm_analysis_imp #(sy_transaction, sy_scoreboard)
여기서 파라미터가 2개인 이유는 아주 중요합니다! UVM 엔진 입장에서는 데이터가 도착했을 때 다음 두 가지 정보가 필요합니다.
첫 번째 파라미터 (sy_transaction): "어떤 형태의 데이터가 들어오는가?"
두 번째 파라미터 (sy_scoreboard): "데이터가 도착했을 때, 누구의(어느 클래스의) write 함수를 실행시켜야 하는가?"
즉, 두 번째 파라미터로 자기 자신(sy_scoreboard)을 넘겨주어, UVM 엔진이 정확한 위치의 write 함수를 찾아 실행하도록 연결해 주는 것입니다.
(연장 케이블 / 중계기): 데이터가 지나가는 중간 통로입니다. 데이터를 만들지도 않고, 소리를 내지도(write 함수) 않습니다. 그저 밖에서 들어온 데이터를 내부에 있는 다른 곳으로 전달(Pass-through)만 해줍니다.
class my_env extends uvm_env;
my_agent agent;
uvm_analysis_export #(my_pkt) mon_export;
function new(string name, uvm_component parent);
super.new(name, parent);
mon_export = new("mon_export", this);
endfunction
function void connect_phase(uvm_phase phase);
// Pass through: env's export connects to agent's monitor port
mon_export.connect(agent.monitor.mon_ap);
endfunction
endclass
imp와 export의 결정적 차이