UVMでslave動作するモデルを作成してみた話。実装したものはこちら。命名が微妙なのは諦めている。
Verilabの資料を参考に作成してみた。 資料とは異なり、sequencerはuvm_sequencerを使用し、その代わりにconfig_dbを使用してreact_req_fifoをsequenceから利用できるようにしている。参照させるためだけにクラス定義もあれかと思ったので。
加えてmonitor_icsからstorageのアップデートをせず、ics_reactive_seqに管理を一任している。passiveで使うならslaveでないものを使用すれば良いし、その状況下でstorageが必要になるとも思えないと思ったので。
プロトコル変換するのと同様に無限ループするシーケンスを用意し、react_req_fifoからデータを取り出して、応答データを作成してsequencerに実行させている。
get_sequencer()でsequencerに設定された設定値をsequenceで取得できるので使用している。
該当の実装は以下の通り。
class simple_ics_slave_env extends uvm_env;
`uvm_component_utils(simple_ics_slave_env)
`uvm_new_func
simple_ics_env ics_env;
simple_ics_slave_storage storage;
uvm_tlm_analysis_fifo#(simple_ics_seq_item) react_req_fifo;
//uvm_sequencer#(simple_ics_seq_item) sequencer;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
ics_env = simple_ics_env::type_id::create("ics_env",this);
react_req_fifo = new("react_req_fifo",this);
storage = simple_ics_slave_storage::type_id::create("storage",this);
storage.init();
uvm_config_db #(uvm_tlm_analysis_fifo#(simple_ics_seq_item))::set(this, "*", "react_req_fifo", react_req_fifo);
uvm_config_db #(simple_ics_slave_storage)::set(this, "*", "storage", storage);
endfunction
function void connect_phase(uvm_phase phase);
ics_env.monitor.react_req_port.connect(react_req_fifo.analysis_export);
endfunction
task run_phase(uvm_phase phase);
ics_reactive_seq reactive_seq;
reactive_seq = ics_reactive_seq::type_id::create("reactive_seq",this);
reactive_seq.start(ics_env.sequencer);
endtask
endclass
class ics_reactive_seq extends uvm_sequence #(simple_ics_seq_item);
`uvm_object_utils(ics_reactive_seq)
simple_ics_seq_item received_item;
simple_ics_seq_item responce_item;
uvm_tlm_analysis_fifo#(simple_ics_seq_item) react_req_fifo;
simple_ics_slave_storage storage;
int baud_rate;
int bit_period;
int stop_bit_num;
function new(string name="ics_reactive_seq");
super.new(name);
endfunction
task body();
logic[7:0] rdata;
if(!uvm_config_db #(uvm_tlm_analysis_fifo#(simple_ics_seq_item))::get(get_sequencer(), "", "react_req_fifo", react_req_fifo)) begin
`uvm_fatal("CONFIG_DB_ERROR", "Could not find react_req_fifo")
end
if(!uvm_config_db #(simple_ics_slave_storage)::get(get_sequencer(),"", "storage", storage)) begin
`uvm_fatal("CONFIG_DB_ERROR", "Could not find simple_ics_slave_storage")
end
//baud rate
if(!uvm_config_db#(int)::get(get_sequencer(), "", "simple_uart_baud_rate", baud_rate)) begin
uvm_report_info("CONFIG","baud rate set to default value(115200 bps)");
baud_rate = 115200;//default value
end
case(baud_rate)
115200: bit_period = 8681;//8680.6 ns for 115200 bps.
default: `uvm_fatal("CONFIG_ERR","Undefined baud rate.")
endcase
//number of stop bit
if(!uvm_config_db#(int)::get(get_sequencer(), "", "simple_uart_stop_bit_num", stop_bit_num)) begin
uvm_report_info("CONFIG","number of stop bit set to default value(1bit)");
stop_bit_num = 1;//default value
end
forever begin
react_req_fifo.get(received_item);
uvm_report_info("REACT","get item");
#(bit_period*(0.2+stop_bit_num));
received_item.print();
responce_item = new();
case(received_item.cmd)
simple_ics_seq_item::POSITION_R: uvm_report_fatal("REACT", "Invalid POSITION_R command received.");
simple_ics_seq_item::READ_R: uvm_report_fatal("REACT", "Invalid READ_R command received.");
simple_ics_seq_item::WRITE_R: uvm_report_fatal("REACT", "Invalid WRITE_R command received.");
simple_ics_seq_item::ID_R: uvm_report_fatal("REACT", "Invalid ID_R command received.");
simple_ics_seq_item::POSITION:
begin
storage.write_reg(received_item.id, simple_ics_seq_item::TCH, received_item.data);
responce_item.cmd = simple_ics_seq_item::POSITION_R;
responce_item.id = received_item.id;
responce_item.data = storage.read_reg(received_item.id, simple_ics_seq_item::TCH);
end
simple_ics_seq_item::READ:
begin
responce_item.cmd = simple_ics_seq_item::READ_R;
responce_item.id = received_item.id;
if(received_item.sub_cmd === simple_ics_seq_item::EEPROM) begin
logic[7:0] eeprom[0:63];
//responce_item.eeprom_data = new[64];
storage.read_mem(received_item.id, eeprom);
responce_item.eeprom_data = eeprom;
end else begin
responce_item.sub_cmd = received_item.sub_cmd;
responce_item.data = storage.read_reg(received_item.id, received_item.sub_cmd);
end
end
simple_ics_seq_item::WRITE:
begin
responce_item.cmd = simple_ics_seq_item::WRITE_R;
responce_item.id = received_item.id;
if(received_item.sub_cmd === simple_ics_seq_item::EEPROM) begin
storage.write_mem(received_item.id, received_item.eeprom_data);
responce_item.sub_cmd = simple_ics_seq_item::EEPROM;
responce_item.data = 0;
end else begin
storage.write_reg(received_item.id, received_item.sub_cmd, received_item.data);
responce_item.sub_cmd = received_item.sub_cmd;
responce_item.data = storage.read_reg(received_item.id, received_item.sub_cmd);
end
end
simple_ics_seq_item::ID:
begin
uvm_report_fatal("REACT", "ID command is not implemented yet.");
end
endcase
responce_item.print();
`uvm_send(responce_item);
end
endtask
endclass
0 件のコメント:
コメントを投稿