这是一个UVM的demo项目:
做一个包含绝大部分组件的uvm(sequencer, driver, monitor, agent, scoreboard, model), 验证一个同向放大器的dut, 主要验证点是
(1)放大倍数设定是否正确(过一个时钟后采集结果比较, 在sequence里直接比较)
(2) 放大值是否计算正确(和调用c++的dll 计算的预期结果, 在scoreboard里比较)
(3) 断言覆盖率
(4) 功能覆盖率
教学视频
IC验证 – 手把手教你搭建UVM芯片验证环境(含代码)_哔哩哔哩_bilibili
代码下载
IC验证-uvm验证demo代码-其它文档类资源-CSDN下载
PPT下载
https://blog.csdn.net/howard789/article/details/



目录结构

param_def.v
`define NO_WIDTH 8 `define BASE_NUMBER_WIDTH 8 `define SCALER_WIDTH 16 `define WR_DATA_WIDTH 16 `define RES_WIDTH 24 `define RD_DATA_WIDTH 32
amplifier.v
`include "param_def.v" module amplifier ( clk_i, rstn_i, wr_en_i, set_scaler_i, wr_data_i, rd_val_o, rd_data_o, scaler_o ); input clk_i; input rstn_i; input wr_en_i; // input set_scaler_i; //是否是修改scaler input [`WR_DATA_WIDTH-1:0] wr_data_i; //输入序号8位 输入数字8位 ,或 sacaler 16位 output reg rd_val_o; //data_o有效 output reg [`RD_DATA_WIDTH-1:0] rd_data_o; //输出资料包括 序号[31:24], 基本数字[23:16], 放大后的数字[15:0]其中第15位是正负号 output [`SCALER_WIDTH-1:0] scaler_o; //當前的scaler //============================================================================= // Main Code * //============================================================================= reg [`SCALER_WIDTH-1:0] scaler; //max 65,535 assign scaler_o = scaler; reg flag; reg [`NO_WIDTH-1:0] no_r; reg [`RES_WIDTH-1:0] res_r; always @ (posedge clk_i or negedge rstn_i) begin if(rstn_i == 1'b0) begin no_r <= 1'b0; res_r <= 1'b0; scaler <= 1'b0; flag <= 1'b0; end //bug start 1 else if(wr_en_i && set_scaler_i && wr_data_i == 16'd5) begin scaler <= 16'd55; no_r <= 1'b0; res_r <= 1'b0; flag <= 1'b0; end // bug end 1 else if(wr_en_i && set_scaler_i) begin scaler <= wr_data_i; no_r <= 1'b0; res_r <= 1'b0; flag <= 1'b0; end //bug start 2 else if(wr_en_i && !set_scaler_i && wr_data_i[ 7:0]== 8'd123) begin scaler <= scaler; no_r <= wr_data_i[15:8]; res_r <= wr_data_i[ 7:0] * 100; flag <= 1'b1; end // bug end 2 else if(wr_en_i && !set_scaler_i) begin scaler <= scaler; no_r <= wr_data_i[15:8]; res_r <= wr_data_i[ 7:0] * scaler; flag <= 1'b1; end else begin scaler <= scaler; no_r <= 1'b0; res_r <= 1'b0; flag <= 1'b0; end end always @ (posedge clk_i or negedge rstn_i) begin if(rstn_i == 1'b0) begin rd_val_o <= 1'b0; rd_data_o <= 1'b0; end else if(flag) begin rd_val_o <= 1'b1; rd_data_o <= {no_r,res_r}; end else begin rd_val_o <= 1'b0; rd_data_o <= 1'b0; end end endmodule
basic_tb.sv
`timescale 1ps/1ps `include "../dut/param_def.v" parameter T = 2; module ref_tb; bit clk,rstn; initial begin fork begin forever #(T/2) clk = !clk; end begin rstn <= 1'b0; #T; rstn <= 1'b1; end join_none end logic wr_en_i; logic set_scaler_i; logic [`WR_DATA_WIDTH-1:0] wr_data_i; logic rd_val_o; logic [`RD_DATA_WIDTH-1:0] rd_data_o; logic [`SCALER_WIDTH-1:0] scaler_o; initial begin wait(!rstn); #T; wr_en_i =1'b0; set_scaler_i =1'b0; wr_data_i = 16'd0; #(T*2); // 设定scaler 100 wr_en_i =1'b1; set_scaler_i =1'b1; wr_data_i = 16'd100; $display("input scaler %d ",set_scaler_i); #T; //查看是否设定成功 $display("rd_val_o %d ",rd_val_o); $display("rd_data_o %d ",rd_data_o); $display("scaler_o %d ",scaler_o); #T; //输入base_number wr_en_i =1'b1; set_scaler_i =1'b0; wr_data_i ={8'd5,8'd25}; $display("input no %d ",wr_data_i[15:8]); $display("input base number %d ",wr_data_i[ 7:0]); #T; //查看结果 $display("rd_val_o %d ",rd_val_o); $display("rd_data_o no %d ",rd_data_o[31:24]); $display("rd_data_o res %d ",rd_data_o[23:0]); $display("scaler_o %d ",scaler_o); #T; //查看结果 $display("rd_val_o %d ",rd_val_o); $display("rd_data_o no %d ",rd_data_o[31:24]); $display("rd_data_o res %d ",rd_data_o[23:0]); $display("scaler_o %d ",scaler_o); end amplifier amplifier_inst ( .clk_i(clk), .rstn_i(rstn), .wr_en_i(wr_en_i), .set_scaler_i(set_scaler_i), .wr_data_i(wr_data_i), .rd_val_o(rd_val_o), .rd_data_o(rd_data_o), .scaler_o(scaler_o) ); endmodule
ue_tb.sv
`timescale 1ns/1ps import uvm_pkg::*; `include "uvm_macros.svh" // `include "../uvm/ue_pkg.svh" module ue_tb; parameter T = 2; bit clk,rstn; string s; int res; initial begin fork begin forever #(T/2) clk = !clk; end begin rstn <= 1'b0; #T; rstn <= 1'b1; end join_none end // ue_interface intf(clk, rstn); ue_interface intf(.*); amplifier amplifier_inst ( .clk_i(clk), .rstn_i(rstn), .wr_en_i(intf.wr_en_i), .set_scaler_i(intf.set_scaler_i), .wr_data_i(intf.wr_data_i), .rd_val_o(intf.rd_val_o), .rd_data_o(intf.rd_data_o), .scaler_o(intf.scaler_o) ); initial begin uvm_config_db#(virtual ue_interface)::set(uvm_root::get(), "uvm_test_top.env.i_agt", "vif", intf); uvm_config_db#(virtual ue_interface)::set(uvm_root::get(), "uvm_test_top.env.o_agt", "vif", intf); end initial begin // run_test("ue_case0_test"); // run_test("ue_case1_test"); // run_test("ue_case2_test"); run_test(); end endmodule
ue_agent.sv
`ifndef UE_AGENT_SV `define UE_AGENT_SV //--------------------------------------- // svh //--------------------------------------- class ue_agent extends uvm_agent; uvm_active_passive_enum is_active; ue_driver drv; ue_sequencer sqr; ue_monitor mon; ue_config cfg; virtual ue_interface vif; `uvm_component_utils(ue_agent) extern function new(string name = "ue_agent",uvm_component parent = null); extern function void build(); extern function void connect(); extern function void report(); endclass //--------------------------------------- // sv //--------------------------------------- function ue_agent::new(string name = "ue_agent" ,uvm_component parent = null); super.new(name, parent); `uvm_info(get_type_name(), $sformatf("created, is_active: %s" ,is_active), UVM_LOW) endfunction : new function void ue_agent::build(); super.build(); if(!uvm_config_db#(ue_config)::get(this,"","cfg", cfg)) begin cfg = ue_config::type_id::create("cfg"); end `uvm_info(get_type_name(), $sformatf("start to build, is_active: %s",is_active), UVM_LOW) if(!uvm_config_db#(virtual ue_interface)::get(this,"","vif", vif)) begin `uvm_fatal("GETVIF","cannot get vif handle from config DB") end vif.start_report=0; mon = ue_monitor::type_id::create("mon",this); mon.vif=vif; if(is_active==UVM_ACTIVE) begin sqr = ue_sequencer::type_id::create("sqr",this); drv = ue_driver::type_id::create("drv",this); drv.vif = vif; mon.monitor_input=1'b1; end else mon.monitor_input=1'b0; `uvm_info(get_type_name(), "built", UVM_LOW) endfunction:build function void ue_agent::connect(); if(is_active==UVM_ACTIVE) begin drv.seq_item_port.connect(sqr.seq_item_export); end `uvm_info(get_type_name(), "connected", UVM_LOW) endfunction:connect function void ue_agent::report(); super.report(); vif.start_report=1; endfunction:report `endif // UE_AGENT_SV
ue_base_test.sv
`ifndef UE_BASE_TEST_SV `define UE_BASE_TEST_SV //-------------------------------------------------------------------------------------------------------- // svh //-------------------------------------------------------------------------------------------------------- class ue_base_test extends uvm_test; ue_env env; `uvm_component_utils(ue_base_test) extern function new(string name="ue_base_test",uvm_component parent = null); extern function void build(); extern function void report(); endclass //-------------------------------------------------------------------------------------------------------- // sv //-------------------------------------------------------------------------------------------------------- function ue_base_test::new(string name ="ue_base_test",uvm_component parent = null); super.new(name, parent); `uvm_info(get_type_name(), $sformatf("created"), UVM_LOW) endfunction : new function void ue_base_test::build(); super.build(); env = ue_env::type_id::create("env",this); `uvm_info(get_type_name(), "built", UVM_LOW) endfunction function void ue_base_test::report(); uvm_report_server server; int err_num; super.report(); server = get_report_server(); err_num = server.get_severity_count(UVM_ERROR); if(err_num != 0) `uvm_info(get_type_name(), $sformatf("err_num:%0d TEST CASE FAILED",err_num), UVM_LOW) else `uvm_info(get_type_name(), $sformatf("TEST CASE PASSED"), UVM_LOW) endfunction `endif // UE_BASE_TEST_SV
ue_driver.sv
`ifndef UE_DRIVER_SV `define UE_DRIVER_SV //--------------------------------------- // svh //--------------------------------------- class ue_driver extends uvm_driver #(ue_transaction); bit show_info; ue_config cfg; virtual ue_interface vif; `uvm_component_utils(ue_driver) extern function new(string name ="ue_driver",uvm_component parent = null); extern function void build(); extern task run(); extern protected task _reset_listener(); extern protected task _get_and_drive(); extern protected task _drive_transfer(ue_transaction t); extern protected task _do_idle(); extern protected task _set_scaler(ue_transaction t); extern protected task _wr_base_number(ue_transaction t); endclass : ue_driver //--------------------------------------- // sv //--------------------------------------- function ue_driver::new(string name ="ue_driver",uvm_component parent = null); super.new(name, parent); `uvm_info(get_type_name(), $sformatf("created"), UVM_LOW) endfunction : new function void ue_driver::build(); super.build(); if(!uvm_config_db#(ue_config)::get(this,"","cfg", cfg)) begin cfg = ue_config::type_id::create("cfg"); end show_info = cfg.show_info_drv; `uvm_info(get_type_name(), "built", UVM_LOW) endfunction : build task ue_driver::run(); super.run(); vif.wr_en_i = 1'b0; vif.set_scaler_i = 1'b0; vif.wr_data_i = 1'b0; vif.rd_val_o = 1'b0; vif.rd_data_o = 1'b0; vif.scaler_o = 1'b0; while(!vif.rstn) @(posedge vif.clk); `uvm_info(get_type_name(), "start run()", UVM_LOW) fork ue_driver::_get_and_drive(); ue_driver::_reset_listener(); join `uvm_info(get_type_name(), "end run()", UVM_LOW) endtask : run task ue_driver::_reset_listener(); forever begin @(negedge vif.rstn); vif.wr_en_i = 0; vif.set_scaler_i =0 ; vif.wr_data_i = 0; if(show_info) `uvm_info(get_type_name(), "_reset_listener done", UVM_LOW) end endtask task ue_driver::_drive_transfer(ue_transaction t); if(show_info) t.print_info("ue_driver _drive_transfer"); case (t.ttype) ue_transaction::IDLE:_do_idle(); ue_transaction::SET_SCALER:_set_scaler(t); ue_transaction::WR_BASE_NUMBER:_wr_base_number(t); default:`uvm_error("ERRTYPE", "_drive_transfer mode err") endcase endtask task ue_driver::_do_idle(); @(vif.cb_drv); vif.cb_drv.wr_en_i <= 1'b0; vif.cb_drv.wr_data_i<= 1'b0; endtask task ue_driver::_set_scaler(ue_transaction t); @(vif.cb_drv); vif.cb_drv.wr_en_i <= 1'b1; vif.cb_drv.set_scaler_i<= 1'b1; vif.cb_drv.wr_data_i <= t.wr_scaler; @(vif.cb_drv);//dut收到信号 @(vif.cb_drv); t.rd_scaler = vif.cb_drv.scaler_o; endtask task ue_driver::_wr_base_number(ue_transaction t); @(vif.cb_drv); vif.cb_drv.wr_en_i <= 1'b1; vif.cb_drv.set_scaler_i <= 1'b0; vif.cb_drv.wr_data_i <= {t.no,t.base_number}; t.rd_scaler = vif.cb_drv.scaler_o; repeat(t.idle_cycles) _do_idle(); endtask task ue_driver::_get_and_drive(); forever begin seq_item_port.get_next_item(req); this._drive_transfer(req); void'($cast(rsp, req.clone())); rsp.set_sequence_id(req.get_sequence_id()); seq_item_port.item_done(rsp); end endtask `endif // UE_DRIVER_SV
ue_env.sv
`ifndef UE_ENV_SV `define UE_ENV_SV //--------------------------------------- // svh //--------------------------------------- class ue_env extends uvm_env; ue_config cfg; ue_agent i_agt; ue_agent o_agt; ue_ref_model mdl; ue_scoreboard scb; uvm_tlm_analysis_fifo #(ue_transaction) iagt_mdl_fifo; uvm_tlm_analysis_fifo #(ue_transaction) oagt_scb_fifo; uvm_tlm_analysis_fifo #(ue_transaction) mdl_scb_fifo; `uvm_component_utils(ue_env) extern function new (string name = "ue_env", uvm_component parent =null); extern function void build(); extern function void connect(); extern function void report(); endclass : ue_env //--------------------------------------- // sv //--------------------------------------- function ue_env::new(string name ="ue_env",uvm_component parent = null); super.new(name, parent); `uvm_info(get_type_name(), $sformatf("created"), UVM_LOW) endfunction : new function void ue_env::build(); super.build(); if(!uvm_config_db#(ue_config)::get(this,"","cfg", cfg)) begin cfg = ue_config::type_id::create("cfg"); end i_agt = ue_agent::type_id::create("i_agt",this); i_agt.is_active=cfg.i_agt_is_active; o_agt = ue_agent::type_id::create("o_agt",this); o_agt.is_active=cfg.o_agt_is_active; mdl = ue_ref_model::type_id::create("mdl",this); scb = ue_scoreboard::type_id::create("scb",this); iagt_mdl_fifo = new("iagt_mdl_fifo",this); oagt_scb_fifo = new("oagt_scb_fifo",this); mdl_scb_fifo = new("mdl_scb_fifo",this); `uvm_info(get_type_name(), $sformatf("built"), UVM_LOW) endfunction :build function void ue_env::connect(); super.connect(); i_agt.mon.ap.connect(iagt_mdl_fifo.analysis_export); mdl.gp.connect(iagt_mdl_fifo.blocking_get_export); o_agt.mon.ap.connect(oagt_scb_fifo.analysis_export); scb.act_gp.connect(oagt_scb_fifo.blocking_get_export); mdl.ap.connect(mdl_scb_fifo.analysis_export); scb.exp_gp.connect(mdl_scb_fifo.blocking_get_export); `uvm_info(get_type_name(), "connected", UVM_LOW) endfunction :connect function void ue_env::report(); super.report(); if(i_agt.mon.sent_item_num == o_agt.mon.sent_item_num) `uvm_info(get_type_name(), "sent_item_num check ok", UVM_LOW) else `uvm_error("ENV_ERROR", "sent_item_num check error") endfunction:report `endif // UE_ENV_SV
ue_monitor.sv
`ifndef UE_MONITOR_SV `define UE_MONITOR_SV //--------------------------------------- // svh //--------------------------------------- class ue_monitor extends uvm_monitor; bit show_info; ue_config cfg; bit monitor_input; int sent_item_num; virtual ue_interface vif; uvm_analysis_port #(ue_transaction) ap; protected ue_transaction trans_collected; //内部使用的指针 `uvm_component_utils(ue_monitor) extern function new(string name ="ue_monitor",uvm_component parent = null); extern function void build(); extern task run(); extern protected task _collect_transfer(ue_transaction t); extern function void report(); endclass //--------------------------------------- // sv //--------------------------------------- function ue_monitor::new(string name="ue_monitor",uvm_component parent = null); super.new(name, parent); `uvm_info(get_type_name(), $sformatf("created"), UVM_LOW) endfunction : new function void ue_monitor::build(); ap = new("ap",this); if(!uvm_config_db#(ue_config)::get(this,"","cfg", cfg)) begin cfg = ue_config::type_id::create("cfg"); end show_info = cfg.show_info_mon; sent_item_num = 0; `uvm_info(get_type_name(), $sformatf("built"), UVM_LOW) endfunction task ue_monitor::run(); super.run(); `uvm_info(get_type_name(), "start run()", UVM_LOW) fork while(1) begin @(vif.cb_mon); trans_collected = ue_transaction::type_id::create("trans_collected"); this._collect_transfer(trans_collected);//收集vif的资料赋值给 trans_collected if(monitor_input && trans_collected.ttype==ue_transaction::WR_BASE_NUMBER) begin ap.write(trans_collected); sent_item_num+=1; if(show_info) trans_collected.print_info("mon input"); end else if(trans_collected.rd_valid) begin ap.write(trans_collected); sent_item_num+=1; if(show_info) trans_collected.print_info("mon output"); end end join `uvm_info(get_type_name(), "end run()", UVM_LOW) endtask function void ue_monitor::report(); super.report(); `uvm_info(get_type_name(), $sformatf("sent_item_num:%d",sent_item_num), UVM_LOW) endfunction:report task ue_monitor::_collect_transfer(ue_transaction t); @(vif.cb_mon); if(monitor_input)begin //i_agent if(vif.cb_mon.wr_en_i && !vif.cb_mon.set_scaler_i) begin t.ttype = ue_transaction::WR_BASE_NUMBER; t.no = vif.cb_mon.wr_data_i[15:8]; t.base_number = vif.cb_mon.wr_data_i[7:0]; t.rd_scaler = vif.cb_mon.scaler_o; end else if(vif.cb_mon.wr_en_i && vif.cb_mon.set_scaler_i) begin t.ttype = ue_transaction::SET_SCALER; t.no = 0; t.base_number = 0; t.wr_scaler = vif.cb_mon.wr_data_i; t.rd_scaler = vif.cb_mon.scaler_o; end else begin t.ttype = ue_transaction::IDLE; end end else begin //o_agent t.rd_valid = vif.cb_mon.rd_val_o; t.no = vif.cb_mon.rd_data_o[31:24]; t.rd_data = vif.cb_mon.rd_data_o[23:0]; end endtask `endif // UE_MONITOR_SV
ue_ref_model.sv
`ifndef UE_REF_MODEL_SV `define UE_REF_MODEL_SV //--------------------------------------- // svh //--------------------------------------- import "DPI-C" context function int amplifier(input int base_number,int scaler); export "DPI-C" dpi_info=function dpi_info; export "DPI-C" dpi_fatal=function dpi_fatal; function void dpi_info(string s); `uvm_info("dpi_info", s, UVM_LOW) endfunction: dpi_info function void dpi_fatal(string s); `uvm_fatal("dpi_fatal", s) endfunction: dpi_fatal class ue_ref_model extends uvm_component; ue_config cfg; bit show_info; uvm_blocking_get_port #(ue_transaction) gp; uvm_analysis_port #(ue_transaction) ap; protected ue_transaction tr; protected ue_transaction new_tr; int res; `uvm_component_utils(ue_ref_model) extern function new(string name ="ue_ref_model",uvm_component parent = null); extern function void build(); extern task run(); endclass : ue_ref_model //-------------------------------------------------------------------------------------------------------- // sv //-------------------------------------------------------------------------------------------------------- function ue_ref_model::new(string name ="ue_ref_model",uvm_component parent = null); super.new(name, parent); `uvm_info(get_type_name(), $sformatf("created, show_info:%0d",show_info), UVM_LOW) endfunction : new function void ue_ref_model::build(); super.build(); if(!uvm_config_db#(ue_config)::get(this,"","cfg", cfg)) begin cfg = ue_config::type_id::create("cfg"); end show_info = cfg.show_info_mdl; gp = new("gp", this); ap = new("ap", this); if(show_info) `uvm_info(get_type_name(), "built", UVM_LOW) endfunction task ue_ref_model::run(); if(show_info) `uvm_info(get_type_name(), " start run()", UVM_LOW) super.run(); while(1) begin new_tr = new("new_tr"); tr=new("tr"); gp.get(tr); if(show_info) tr.print_info("ref_model tr"); new_tr.copy(tr); //res=tr.base_number*tr.rd_scaler; res=amplifier(tr.base_number,tr.rd_scaler); new_tr.rd_data=res; ap.write(new_tr); if(show_info) new_tr.print_info("ref_model new_tr"); end `uvm_info(get_type_name(), "end run()", UVM_LOW) endtask `endif // UE_REF_MODEL_SV
ue_scoreboard.sv
`ifndef UE_SCOREBOARD_SV `define UE_SCOREBOARD_SV //--------------------------------------- // svh //--------------------------------------- class ue_scoreboard extends uvm_scoreboard; ue_config cfg; bit show_info; uvm_blocking_get_port #(ue_transaction) exp_gp; uvm_blocking_get_port #(ue_transaction) act_gp; ue_transaction tran_exp,tran_act; int success_num; int failure_num; `uvm_component_utils(ue_scoreboard) extern function new (string name = "ue_scoreboard", uvm_component parent =null); extern function void build(); extern task run(); extern function void report(); endclass : ue_scoreboard //--------------------------------------- // sv //--------------------------------------- function ue_scoreboard::new(string name ="ue_scoreboard",uvm_component parent = null); super.new(name, parent); `uvm_info(get_type_name(), $sformatf("created"), UVM_LOW) endfunction : new function void ue_scoreboard::build(); super.build(); if(!uvm_config_db#(ue_config)::get(this,"","cfg", cfg)) begin cfg = ue_config::type_id::create("cfg"); end show_info = cfg.show_info_scb; exp_gp=new("exp_gp",this); act_gp=new("act_gp",this); success_num=0; failure_num=0; `uvm_info(get_type_name(), "built", UVM_LOW) endfunction :build task ue_scoreboard::run(); super.run(); fork while(1)begin exp_gp.get(tran_exp); act_gp.get(tran_act); if(tran_exp.no!=tran_act.no) `uvm_info(get_type_name(), $sformatf("no is different,exp:%0d act:%0d",tran_exp.no,tran_act.no), UVM_LOW) else begin if(tran_exp.rd_data==tran_act.rd_data) begin success_num+=1; if(show_info) begin `uvm_info(get_type_name(), $sformatf("compare successfully scaler:%0d base_number:%0d rd_data:%0d",tran_act.rd_scaler,tran_act.base_number,tran_act.rd_data), UVM_LOW) tran_act.print_info(get_type_name()); end end else begin failure_num+=1; `uvm_error("SCORE_ERROR", $sformatf("compare failed,scaler:%0d,base_number:%0d,exp_res:%0d,act_res:%0d",tran_exp.rd_scaler,tran_exp.base_number,tran_exp.rd_data,tran_act.rd_data)) end end end join endtask function void ue_scoreboard::report(); super.report(); if(show_info) `uvm_info(get_type_name(), $sformatf("report"), UVM_LOW) `uvm_info(get_type_name(), $sformatf("success_num:%0d",success_num), UVM_LOW) `uvm_info(get_type_name(), $sformatf("failure_num:%0d",failure_num), UVM_LOW) // `uvm_info(get_type_name(), $sformatf("failure_base_numbers:%0s",failure_base_numbers), UVM_LOW) endfunction :report `endif // UE_SCOREBOARD_SV
ue_sequencer.sv
`ifndef UE_SEQUENCER_SV `define UE_SEQUENCER_SV class ue_sequencer extends uvm_sequencer #(ue_transaction); `uvm_component_utils(ue_sequencer) extern function new(string name ="ue_sequencer",uvm_component parent = null); extern function void build(); endclass //-------------------------------------------------------------------------------------------------------- // sv //-------------------------------------------------------------------------------------------------------- function ue_sequencer::new(string name ="ue_sequencer",uvm_component parent = null); super.new(name, parent); `uvm_info(get_type_name(), $sformatf("created"), UVM_LOW) endfunction : new function void ue_sequencer::build(); super.build(); `uvm_info(get_type_name(), "built", UVM_LOW) endfunction : build `endif // UE_SEQUENCER_SV
ue_interface.sv
`ifndef UE_INTERFACE_SV
`define UE_INTERFACE_SV
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "param_def.v"
`timescale 1ps/1ps
interface ue_interface (input clk,input rstn);
logic wr_en_i; // input valid
logic set_scaler_i; // is_input_scaler
logic [`WR_DATA_WIDTH-1:0] wr_data_i; // input data: 16 bit scaler or (8 bit no + 8 bit base_number)
logic rd_val_o; // rd_data valid
logic [`RD_DATA_WIDTH-1:0] rd_data_o; //
logic [`SCALER_WIDTH-1:0] scaler_o; //current scaler
bit start_report ;
//---------------------------------------
// clocking
//---------------------------------------
// https://blog.csdn.net/wonder_coole/article/details/82597125
clocking cb_drv @(posedge clk);
default input #1ps output #1ps;
output wr_en_i,set_scaler_i, wr_data_i;
input rd_val_o, rd_data_o,scaler_o;
endclocking : cb_drv
clocking cb_mon @(posedge clk);
default input #1ps output #1ps;
input wr_en_i,set_scaler_i,wr_data_i, rd_val_o,rd_data_o, scaler_o;
endclocking : cb_mon
// cg option https://xueying.blog.csdn.net/article/details/105309727
covergroup cg_wr_command(string comment ="") @(posedge clk iff rstn);
//type total bins: 8-2(ignore_bins)-4(type_option.weight = 0)=2
//instance total bins : 8-2(ignore_bins)=6
// type_option.weight = 0;
// option.goal =100;
// option.auto_bin_max = 100; //default 64
// option.at_least =10;
// option.goal =100;
// option.cross_num_print_missing=1;//多个实例的时候 分开计算
// option.comment=comment; //多个实例的时候
wr_en: coverpoint wr_en_i{
//http://blog.sina.com.cn/s/blog_5391b49c0102vte0.html
type_option.weight = 0;
bins unsel = {0};
bins sel = {1};
}
set_scaler: coverpoint set_scaler_i{
type_option.weight = 0;
bins unsel = {0};
bins sel = {1};
}
cmd: cross wr_en,set_scaler{
bins cmd_set_scaler = binsof(wr_en.sel) && binsof(set_scaler.sel);
bins cmd_write = binsof(wr_en.sel) && binsof(set_scaler.unsel);
ignore_bins ignore0 = binsof(wr_en.unsel) && binsof(set_scaler.sel);
ignore_bins ignore1 = binsof(wr_en.unsel) && binsof(set_scaler.unsel);
// ignore_bins others = default; //采样到的时候, 仿真会停止
// ignore_bins others = binsof(default) && binsof(default);
}
endgroup
covergroup cg_wr_timing_group(string comment ="") @(posedge clk iff (rstn && !set_scaler_i));
//type total bins: 8
//instance total bins : 8-6(option.weight = 0)=2
option.comment=comment;
coverpoint wr_en_i{
bins burst_1 = ( 0 => 1 => 0);
bins burst_2 = ( 0 => 1[*2] => 0);
bins burst_3 = ( 0 => 1[*3] => 0);
bins burst_4 = ( 0 => 1[*4] => 0);
bins burst_5 = ( 0 => 1[*5] => 0);
}
endgroup: cg_wr_timing_group
covergroup cg_scaler_range_group(int low,high,string comment ="") @(posedge clk iff (rstn && wr_en_i && set_scaler_i));
//type total bins: 1
//instance total bins : 1
option.comment=comment;
option.cross_num_print_missing=1;
coverpoint wr_data_i {
bins range[] ={[low:high]};
}
endgroup: cg_scaler_range_group
covergroup cg_base_number_range_group(int low,high,string comment ="") @(posedge clk iff (rstn && wr_en_i && !set_scaler_i));
//type total bins: 1
//instance total bins : 1
option.comment=comment;
option.cross_num_print_missing=1;
coverpoint wr_data_i[7:0] {
bins range[] ={[low:high]};
}
endgroup: cg_base_number_range_group
covergroup cg_scaler_bits_wide_group(string comment ="") @(posedge clk iff (rstn && wr_en_i && set_scaler_i));
//type total bins: 2
//instance total bins : 2
coverpoint wr_data_i {
wildcard bins highest_bit_wide0={16'b1xxx_xxxx_xxxx_xxxx};
wildcard bins highest_bit_wide1={16'b0zzz_zzzz_zzzz_zzzz};
illegal_bins others = default;
}
endgroup: cg_scaler_bits_wide_group
covergroup cg_base_number_bits_wide_group(string comment ="") @(posedge clk iff (rstn && wr_en_i && !set_scaler_i));
//type total bins: 2
//instance total bins : 2
coverpoint wr_data_i {
wildcard bins highest_bit_wide0={16'b????_????_1???_????};
wildcard bins highest_bit_wide1={16'bxxxx_xxxx_0xxx_xxxx};
illegal_bins others = default;
}
endgroup: cg_base_number_bits_wide_group
initial begin
automatic cg_wr_command cg_0= new();
automatic cg_wr_timing_group cg_1= new();
automatic cg_scaler_range_group cg_2= new(1,10);
automatic cg_base_number_range_group cg_3= new(121,130);
automatic cg_scaler_bits_wide_group cg_4= new();
automatic cg_base_number_bits_wide_group cg_5= new();
wait(rstn==0);
cg_0.stop();
wait(rstn==1);
cg_0.start();
cg_0.sample();
cg_0.set_inst_name("cg_0");
wait(start_report)begin
string s;
s={s,"cg_wr_command "};
s={s,$sformatf("coverage:%0d\n",cg_0.get_inst_coverage())};
s={s,"cg_wr_timing_group "};
s={s,$sformatf("coverage:%0d\n",cg_1.get_inst_coverage())};
s={s,"cg_scaler_range_group "};
s={s,$sformatf("coverage:%0d\n",cg_2.get_inst_coverage())};
s={s,"cg_base_number_range_group "};
s={s,$sformatf("coverage:%0d\n",cg_3.get_inst_coverage())};
s={s,"cg_scaler_bits_wide_group "};
s={s,$sformatf("coverage:%0d\n",cg_4.get_inst_coverage())};
s={s,"cg_base_number_bits_wide_group "};
s={s,$sformatf("coverage:%0d\n",cg_5.get_inst_coverage())};
s={s,$sformatf("total coverage:%0d\n",$get_coverage())};
//监测并 动态修改约束,提高覆盖率,或停止仿真
$display("%0s",s);
end
end
//--------------------------------------------------------------------------------------------------------
// property
//--------------------------------------------------------------------------------------------------------
property pro_wr_en_wr_data;
@(posedge clk) disable iff (!rstn)
wr_en_i |-> not $isunknown(wr_data_i) ;
endproperty: pro_wr_en_wr_data
assert property(pro_wr_en_wr_data) else `uvm_error("ASSERT", "wr_data_i is unknown while wr_en_i is high")
cover property(pro_wr_en_wr_data) ;
property pro_set_scaler;
@(posedge clk) disable iff (!rstn)
(wr_en_i && set_scaler_i) |-> (wr_data_i!=0) |=> not $isunknown(scaler_o);
endproperty: pro_set_scaler
assert property(pro_set_scaler) else `uvm_error("ASSERT", "set zero scaler")
cover property(pro_set_scaler) ;
property pro_wr_en_wr_scaler_rd_val;
@(posedge clk) disable iff (!rstn)
(wr_en_i && !set_scaler_i) |=> (1 rd_val_o or $rose(rd_val_o)) ;
endproperty: pro_wr_en_wr_scaler_rd_val
assert property(pro_wr_en_wr_scaler_rd_val) else `uvm_error("ASSERT", "rd_val_o is still invalid after (wr_en_i && !wr_scaler_i)")
cover property(pro_wr_en_wr_scaler_rd_val) ;
property pro_wr_scaler_i_scaler_o;
logic [15:0] data;
@(posedge clk) disable iff (!rstn)
(wr_en_i && set_scaler_i , data = wr_data_i) |=> (data == scaler_o) ;
endproperty: pro_wr_scaler_i_scaler_o
assert property(pro_wr_scaler_i_scaler_o) else `uvm_error("ASSERT", "set scaler fail");
cover property(pro_wr_scaler_i_scaler_o) ;
property pro_rd_val_rd_data_o;
@(posedge clk) disable iff (!rstn)
rd_val_o |-> !$isunknown(rd_data_o) ;
endproperty: pro_rd_val_rd_data_o
assert property(pro_rd_val_rd_data_o) else `uvm_error("ASSERT", "rd_data_o is unknown while rd_valid")
cover property(pro_rd_val_rd_data_o) ;
// initial begin
// forever begin
// wait(rstn==0);
// $assertoff();
// wait(rstn==1);
// $asserton();
// end
// end
endinterface
`endif // UE_INTERFACE_SV
ue_base_sequense.sv
`ifndef UE_BASE_SEQUENCE `define UE_BASE_SEQUENCE class ue_base_sequense extends uvm_sequence #(ue_transaction); ue_transaction m_trans; `uvm_object_utils(ue_base_sequense) extern function new(string name="ue_base_sequense"); extern function int get_rand_number_except(int min_thre,int max_thre,int except_num); extern function int get_rand_number(int min_thre,int max_thre); endclass function ue_base_sequense::new(string name="ue_base_sequense"); super.new(name); endfunction : new function int ue_base_sequense::get_rand_number_except(int min_thre,int max_thre,int except_num); int val=get_rand_number( min_thre, max_thre); while(val==except_num) val=get_rand_number( min_thre, max_thre); return val; endfunction function int ue_base_sequense::get_rand_number(int min_thre,int max_thre); int val; void'(std::randomize(val) with { val inside {[min_thre:max_thre]};}); return val; endfunction `endif // UE_BASE_SEQUENCE
ue_base_sequense_lib.sv
`ifndef UE_BASE_SEQ_LIB `define UE_BASE_SEQ_LIB //-------------------------------------------------------------------------------------------------------- // set_scaler //-------------------------------------------------------------------------------------------------------- class subseq_set_scaler extends ue_base_sequense; rand bit [`SCALER_WIDTH-1:0] scaler; `uvm_object_utils(subseq_set_scaler) function new(string name="subseq_set_scaler"); super.new(name); endfunction : new virtual task body(); `uvm_do_with(req, {no==0;base_number==0;wr_scaler == local::scaler;ttype==ue_transaction::SET_SCALER;idle_cycles==0;}) get_response(rsp); if(scaler!=rsp.rd_scaler) `uvm_error("SET_SCALER_ERR", $sformatf("ue_set_scaler_idle_sequence err, exp:%0d act:%0d",scaler,rsp.rd_scaler)) // else // `uvm_info(get_type_name(),$sformatf("ue_set_scaler_idle_sequence success"), UVM_LOW) endtask : body endclass : subseq_set_scaler class subseq_wr_base_number extends ue_base_sequense; rand logic [ 7:0] base_number; rand int idle_cycles; rand int no; `uvm_object_utils(subseq_wr_base_number) function new(string name=""); super.new(name); endfunction : new virtual task body(); `uvm_do_with(req, {no==local::no;base_number== local::base_number;ttype==ue_transaction::WR_BASE_NUMBER;idle_cycles==local::idle_cycles;}) get_response(rsp); endtask : body endclass : subseq_wr_base_number class subseq_idle extends ue_base_sequense; rand int idle_cycles; `uvm_object_utils(subseq_idle) function new(string name="subseq_idle"); super.new(name); `uvm_info(get_type_name(), $sformatf("created"), UVM_LOW) endfunction : new virtual task body(); `uvm_do_with(req, {no==0;ttype==ue_transaction::IDLE;idle_cycles==local::idle_cycles;}) get_response(rsp); endtask : body endclass : subseq_idle `endif // UE_BASE_SEQ_LIB
ue_config.sv
`ifndef UE_CONFIG_SV `define UE_CONFIG_SV class ue_config extends uvm_object; uvm_active_passive_enum i_agt_is_active = UVM_ACTIVE; uvm_active_passive_enum o_agt_is_active = UVM_PASSIVE; //debug 资讯 bit show_info_drv =0; bit show_info_mon =0; bit show_info_mdl =0; bit show_info_scb =0; `uvm_object_utils(ue_config) endclass : ue_config `endif // UE_CONFIG_SV
ue_transaction.sv
`ifndef UE_TRANS `define UE_TRANS `include "param_def.v" class ue_transaction extends uvm_sequence_item; typedef enum{IDLE,SET_SCALER,WR_BASE_NUMBER} trans_type; rand trans_type ttype; randc bit [`NO_WIDTH-1:0] no; randc bit [`BASE_NUMBER_WIDTH-1:0] base_number; randc bit [`SCALER_WIDTH-1:0] wr_scaler; rand int idle_cycles; bit [`SCALER_WIDTH-1:0] rd_scaler; bit rd_valid; bit [`RD_DATA_WIDTH-1:0] rd_data; constraint cstr { soft idle_cycles inside {[0:2]}; soft idle_cycles dist {[0:50],[1:25],[2:30]}; //destination 1:50/105 2:25/105 3:30/105 soft wr_scaler inside {[32:55]}; //0-200 // soft wr_scaler inside {[$:12],[20:$]}; //0-50 60-255 // 两个都是硬约束,取交集,如果无解就求解失败,所有值都是默认值0 ,为避免求解失败尽量用soft soft base_number inside {[0:30],[50:80]}; //软约束 // soft (!wr_en)-> base_number ==0;//以后面的为准 0 50-100 } `uvm_object_utils_begin(ue_transaction) `uvm_field_enum (trans_type,ttype , UVM_ALL_ON) `uvm_field_int (no, UVM_ALL_ON) `uvm_field_int (base_number, UVM_ALL_ON) `uvm_field_int (wr_scaler, UVM_ALL_ON) `uvm_field_int (rd_scaler, UVM_ALL_ON) `uvm_field_int (rd_valid, UVM_ALL_ON) `uvm_field_int (rd_data, UVM_ALL_ON) `uvm_field_int (idle_cycles, UVM_ALL_ON) `uvm_object_utils_end function new(string name = "ue_trans_inst"); super.new(name); `uvm_info(get_type_name(), "obj created", UVM_FULL) endfunction function void print_info(string stage); string s; s={s,$sformatf("\n=========%s==============\n",stage)}; s={s,$sformatf("no:%0d\t",no)}; s={s,$sformatf("trans_type:%s\t",ttype)}; s={s,$sformatf("base_number:%d\t",base_number)}; s={s,$sformatf("wr_scaler:%d\t",wr_scaler)}; s={s,$sformatf("rd_scaler:%d\t",rd_scaler)}; s={s,$sformatf("rd_data:%d\t",rd_data)}; s={s,$sformatf("idle_cycles:%d\n",idle_cycles)}; s={s,"=======================================================\n"}; $display("%s",s); endfunction:print_info endclass `endif // UE_TRANS
ue_case0_test.sv
`ifndef UE_CASE0_TEST_SV `define UE_CASE0_TEST_SV //-------------------------------------------------------------------------------------------------------- // sequence svh //-------------------------------------------------------------------------------------------------------- class ue_case0_sequence extends ue_base_sequense; randc bit [15:0] wr_scaler; randc bit [ 7:0] base_number; bit [ 7:0] no; int idle_cycles; int bug_base_number; int bug_scaler; subseq_set_scaler seq_scaler; subseq_wr_base_number seq_base_number; subseq_idle seq_idle; randc int burst_num; `uvm_object_utils(ue_case0_sequence) extern function new(string name="ue_case0_sequence"); extern task body(); endclass : ue_case0_sequence //-------------------------------------------------------------------------------------------------------- // sv //-------------------------------------------------------------------------------------------------------- function ue_case0_sequence::new(string name="ue_case0_sequence"); super.new(name); `uvm_info(get_type_name(), $sformatf("created"), UVM_FULL) endfunction : new task ue_case0_sequence::body(); if(starting_phase != null) begin starting_phase.raise_objection(this); end bug_base_number=123; bug_scaler=5; `uvm_do_with(seq_idle,{idle_cycles == 10;}) wr_scaler=16'hffff; // 写法:1 // `uvm_create(seq_scaler) // seq_scaler.scaler=wr_scaler; // `uvm_send(seq_scaler) // 写法:2 // `uvm_create(seq_scaler) // `uvm_rand_send_with(seq_scaler, {scaler == local::wr_scaler;}) // 写法:3 `uvm_do_with(seq_scaler, {scaler == local::wr_scaler;}) no=1; base_number=0; `uvm_do_with(seq_base_number, {no == local::no;base_number == local::base_number;idle_cycles == 0;}) //连续写入 repeat(20) begin wr_scaler=get_rand_number_except(1,10,bug_scaler); `uvm_do_with(seq_scaler, {scaler == local::wr_scaler;}) `uvm_do_with(seq_idle, {idle_cycles == 1;}) burst_num=get_rand_number(1,5); $display("burst_num %0d", burst_num); repeat(burst_num) begin //连续写入次数 no+=1; base_number = get_rand_number_except(121,130,bug_base_number); `uvm_do_with(seq_base_number, {no == local::no;base_number == local::base_number;idle_cycles == 0;}) end `uvm_do_with(seq_idle, {idle_cycles == 1;}) end repeat(10) `uvm_do_with(seq_idle, {idle_cycles == 1;}) if(starting_phase != null) starting_phase.drop_objection(this); endtask : body //-------------------------------------------------------------------------------------------------------- // test //-------------------------------------------------------------------------------------------------------- class ue_case0_test extends ue_base_test; `uvm_component_utils(ue_case0_test) function new(string name="ue_case0_test", uvm_component parent = null); super.new(name,parent); endfunction : new function void build(); super.build(); uvm_config_db#(uvm_object_wrapper)::set(this,"env.i_agt.sqr.main_phase","default_sequence", ue_case0_sequence::type_id::get()); endfunction endclass : ue_case0_test `endif // UE_CASE0_TEST_SV
ue_case1_test.sv
`ifndef UE_case1_TEST_SV `define UE_case1_TEST_SV //-------------------------------------------------------------------------------------------------------- // sequence svh //-------------------------------------------------------------------------------------------------------- class ue_case1_sequence extends ue_base_sequense; bit [15:0] wr_scaler; bit [ 7:0] base_number; bit [ 7:0] no; int idle_cycles; int bug_base_number; int bug_scaler; subseq_set_scaler seq_scaler; subseq_wr_base_number seq_base_number; subseq_idle seq_idle; `uvm_object_utils(ue_case1_sequence) extern function new(string name="ue_case1_sequence"); extern task body(); endclass : ue_case1_sequence //-------------------------------------------------------------------------------------------------------- // sv //-------------------------------------------------------------------------------------------------------- function ue_case1_sequence::new(string name="ue_case1_sequence"); super.new(name); `uvm_info(get_type_name(), $sformatf("created"), UVM_FULL) endfunction : new task ue_case1_sequence::body(); if(starting_phase != null) begin starting_phase.raise_objection(this); end bug_base_number=123; bug_scaler=5; `uvm_do_with(seq_idle,{idle_cycles == 10;}) `uvm_do_with(seq_scaler, {scaler == 7;}) no=1; // 测试bug `uvm_do_with(seq_base_number, {no == local::no;base_number == bug_base_number;idle_cycles == 0;}) `uvm_do_with(seq_scaler, {scaler == bug_scaler;}) `uvm_do_with(seq_idle, {idle_cycles == 10;}) if(starting_phase != null) starting_phase.drop_objection(this); endtask : body //-------------------------------------------------------------------------------------------------------- // test //-------------------------------------------------------------------------------------------------------- class ue_case1_test extends ue_base_test; `uvm_component_utils(ue_case1_test) function new(string name="ue_case1_test", uvm_component parent = null); super.new(name,parent); endfunction : new function void build(); super.build(); uvm_config_db#(uvm_object_wrapper)::set(this,"env.i_agt.sqr.main_phase","default_sequence", ue_case1_sequence::type_id::get()); endfunction endclass : ue_case1_test `endif // UE_case1_TEST_SV
ue_case2_test.sv
`ifndef UE_case2_TEST_SV `define UE_case2_TEST_SV //-------------------------------------------------------------------------------------------------------- // sequence svh //-------------------------------------------------------------------------------------------------------- class ue_case2_sequence extends ue_base_sequense; bit [15:0] wr_scaler; bit [ 7:0] base_number; bit [ 7:0] no; int idle_cycles; int bug_base_number; int bug_scaler; subseq_set_scaler seq_scaler; subseq_wr_base_number seq_base_number; subseq_idle seq_idle; `uvm_object_utils(ue_case2_sequence) extern function new(string name="ue_case2_sequence"); extern task body(); endclass : ue_case2_sequence //-------------------------------------------------------------------------------------------------------- // sv //-------------------------------------------------------------------------------------------------------- function ue_case2_sequence::new(string name="ue_case2_sequence"); super.new(name); `uvm_info(get_type_name(), $sformatf("created"), UVM_FULL) endfunction : new task ue_case2_sequence::body(); if(starting_phase != null) begin starting_phase.raise_objection(this); end repeat () begin `uvm_do(req) get_response(rsp); end repeat(10) `uvm_do_with(seq_idle, {idle_cycles == 1;}) if(starting_phase != null) starting_phase.drop_objection(this); endtask : body //-------------------------------------------------------------------------------------------------------- // test //-------------------------------------------------------------------------------------------------------- class ue_case2_test extends ue_base_test; `uvm_component_utils(ue_case2_test) function new(string name="ue_case2_test", uvm_component parent = null); super.new(name,parent); endfunction : new function void build(); super.build(); uvm_config_db#(uvm_object_wrapper)::set(this,"env.i_agt.sqr.main_phase","default_sequence", ue_case2_sequence::type_id::get()); endfunction endclass : ue_case2_test `endif // UE_case2_TEST_SV
complist.f
$DUT_SRC/amplifier.v $UVM_SRC/ue_pkg.svh $TB_SRC/ue_tb.sv
ue_sim.do
#======================================# # TCL script for a mini regression # #======================================# onbreak resume onerror resume # set environment variables setenv UVM_SRC ./src/uvm setenv TB_SRC ./src/tb setenv DUT_SRC src/dut setenv COMP_LIST complist.f setenv RESULT_DIR result setenv TB_NAME ue_tb setenv LOG_DIR log set timetag [clock format [clock seconds] -format "%Y%b%d-%H_%M"] #clean the environment and remove trash files..... set delfiles [glob work *.log *.ucdb sim.list] file delete -force {*}$delfiles #compile the design and dut with a filelist vlib work #complie cpp files #方法1调用cpp档案 #vlog ./src/uvm/cpp/my_fun_c.c #vlog ./src/uvm/cpp/cpp_amplifier.cpp #方法2调用dll vlog ./src/uvm/cpp/my_fun_dll.c echo prepare simrun folder file mkdir $env(RESULT_DIR)/regr_ucdb_${timetag} file mkdir $env(LOG_DIR) vlog -sv -cover bst -timescale=1ns/1ps -l $env(LOG_DIR)/comp_${timetag}.log +incdir+$env(DUT_SRC) -f $env(COMP_LIST) #simulate with specific testname sequentially set TestSets { {ue_case0_test 1} \ {ue_case1_test 0} \ {ue_case2_test 0} } foreach testset $TestSets { set testname [lindex $testset 0] set LoopNum [lindex $testset 1] for {set loop 0} {$loop < $LoopNum} {incr loop} { set seed [expr int(rand() * 100)] echo seed:${seed} vsim -onfinish stop -cvgperinstance -cvgmergeinstances -sv_seed $seed +UVM_TESTNAME=${testname} -l $env(RESULT_DIR)/regr_ucdb_${timetag}/run_${testname}_${seed}.log work.$env(TB_NAME) run -all coverage save $env(RESULT_DIR)/regr_ucdb_${timetag}/${testname}_${seed}.ucdb quit -sim } } #echo merge the ucdb per test vcover merge -testassociated $env(RESULT_DIR)/regr_ucdb_${timetag}/regr_${timetag}.ucdb {*}[glob $env(RESULT_DIR)/regr_ucdb_${timetag}/*.ucdb] echo ending..... quit -f
ue_pkg.svh
.
import uvm_pkg::*; `include "uvm_macros.svh" `include "./interface/ue_interface.sv" `include "./obj/ue_transaction.sv" `include "./obj/ue_config.sv" `include "./obj/sequence/ue_base_sequense.sv" `include "./obj/sequence/ue_base_sequense_lib.sv" `include "./compoment/ue_driver.sv" `include "./compoment/ue_monitor.sv" `include "./compoment/ue_sequencer.sv" `include "./compoment/ue_agent.sv" `include "./compoment/ue_ref_model.sv" `include "./compoment/ue_scoreboard.sv" `include "./compoment/ue_env.sv" `include "./compoment/ue_base_test.sv" `include "./test_case/ue_case0_test.sv" `include "./test_case/ue_case1_test.sv" `include "./test_case/ue_case2_test.sv"
my_fun_c.c
#include
int cal(int base_number, int scaler){ printf("calculated by c\n"); return base_number*scaler; } int amplifier(int base_number, int scaler) { // 直接用c写算法 // return cal(base_number,scaler); //调用cpp档案 return amplifier_by_cpp(base_number,scaler); }
cpp_amplifier.cpp
#include
#ifdef __cplusplus extern "C" { #endif class c_cpp{ public: c_cpp(){}; ~c_cpp(){}; int calculate(int base_number, int scaler); }; int amplifier_by_cpp(int base_number, int scaler); #ifdef __cplusplus } #endif int c_cpp::calculate(int base_number, int scaler){ using namespace std; cout<<"calculated by cpp"<
my_fun_dll.c
#include
#include
#include
extern void dpi_info(char* s); extern void dpi_fatal(char* s); int amplifier(int base_number, int scaler) { int(*p_get_res)(int, int) = NULL; int res; HMODULE h_my_fun = LoadLibraryA("my_fun.dll"); if (h_my_fun == NULL) { dpi_fatal("load dll fail"); } dpi_info("load dll success"); p_get_res = (int(*)(int, int))GetProcAddress(h_my_fun, "get_res"); void(*p_get_info)(char*,int,int, int, int) = NULL; res = p_get_res(base_number, scaler); p_get_info = (void(*)(char*,int,int, int, int))GetProcAddress(h_my_fun, "get_info"); char mm[256]; p_get_info(mm, 256, base_number, scaler, res); dpi_info(mm); return res; }
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/199757.html原文链接:https://javaforall.net
