UVMでプロトコル変換を試してみた話。ICSを題材に実装したものはこちら。
Verification Aacademyの記事を参考に作成してみた。
通常のAgentの外側にプロトコルレイヤーを処理するシーケンス、シーケンサー、モニターを追加するだけ。 実装はUARTの通信インターフェースを使ってデータを交換するICSのモデルを作成した。
下位から上位へのプロトコル変換はmonitorから受け取ったitemを順次処理すれば良い。 ポイントは下位のsequencerでプロトコル変換用のsequenceを動作させること。
このシーケンスが上位のsequencerのitemを取得し、 それを現在動作しているsequencerの実行アイテムに分してdriverに送り込むことでプロトコルの変換が行われる。
該当の実装は以下の通り。
class ics_item_to_uart_item_seq extends uvm_sequence #(simple_uart_seq_item);
`uvm_object_utils(ics_item_to_uart_item_seq)
function new(string name="ics_item_to_uart_item");
super.new(name);
endfunction
uvm_sequencer #(simple_ics_seq_item) up_sequencer;
virtual task body();
simple_ics_seq_item ics_item;
simple_uart_seq_item uart_item;
logic[4:0] id;
bit enable_item_port = 0;
forever begin
up_sequencer.get_next_item(ics_item);
uart_item = simple_uart_seq_item::type_id::create("test");
id = ics_item.id;
`uvm_create(uart_item)
case(ics_item.cmd)
simple_ics_seq_item::POSITION_R:
begin
`uvm_do_with(uart_item, {char=={simple_ics_seq_item::POSITION_R,id};})
`uvm_do_with(uart_item, {char=={0,ics_item.data[13:7]};})
`uvm_do_with(uart_item, {char=={0,ics_item.data[ 6:0]};})
end
simple_ics_seq_item::READ_R:
begin
`uvm_do_with(uart_item, {char=={simple_ics_seq_item::READ_R,id};})
`uvm_do_with(uart_item, {char==ics_item.sub_cmd;})
if(ics_item.sub_cmd === simple_ics_seq_item::EEPROM) begin
for(int i = 0; i < 64; ++i) begin
`uvm_do_with(uart_item, {char==ics_item.eeprom_data[i];})
end
end else if(ics_item.sub_cmd === simple_ics_seq_item::TCH) begin
`uvm_do_with(uart_item, {char=={0,ics_item.data[13:7]};})
`uvm_do_with(uart_item, {char=={0,ics_item.data[ 6:0]};})
end else begin
`uvm_do_with(uart_item, {char==ics_item.data[7:0];})
end
end
simple_ics_seq_item::WRITE_R:
begin
`uvm_do_with(uart_item, {char=={simple_ics_seq_item::WRITE_R,id};})
`uvm_do_with(uart_item, {char==ics_item.sub_cmd;})
if(ics_item.sub_cmd === simple_ics_seq_item::EEPROM) begin
//do nothing
end else begin
`uvm_do_with(uart_item, {char==ics_item.data[7:0];})
end
end
simple_ics_seq_item::ID_R:
begin
`uvm_do_with(uart_item, {char=={simple_ics_seq_item::ID,id};})
end
simple_ics_seq_item::POSITION:
begin
`uvm_do_with(uart_item, {char=={simple_ics_seq_item::POSITION,id};})
`uvm_do_with(uart_item, {char=={0,ics_item.data[13:7]};})
`uvm_do_with(uart_item, {char=={0,ics_item.data[ 6:0]};})
end
simple_ics_seq_item::READ:
begin
`uvm_do_with(uart_item, {char=={simple_ics_seq_item::READ,id};})
`uvm_do_with(uart_item, {char==ics_item.sub_cmd;})
end
simple_ics_seq_item::WRITE:
begin
`uvm_do_with(uart_item, {char=={simple_ics_seq_item::WRITE,id};})
`uvm_do_with(uart_item, {char==ics_item.sub_cmd;})
if(ics_item.sub_cmd === simple_ics_seq_item::EEPROM) begin
for(int i = 0; i < 64; ++i) begin
`uvm_do_with(uart_item, {char==ics_item.eeprom_data[i];})
end
end else begin
`uvm_do_with(uart_item, {char==ics_item.data[7:0];})
end
end
simple_ics_seq_item::ID:
begin
if(ics_item.id_sub_cmd === simple_ics_seq_item::ID_READ) begin
`uvm_do_with(uart_item, {char==8'hff;})
end else begin
`uvm_do_with(uart_item, {char=={simple_ics_seq_item::ID,id};})
end
for(int i = 0; i < 3; ++i) begin
`uvm_do_with(uart_item, {char==ics_item.id_sub_cmd;})
end
end
endcase
up_sequencer.item_done();
end
endtask
endclass
0 件のコメント:
コメントを投稿