主頁 > 後端開發 > UVM基礎總結——基于《UVM實戰》示例

UVM基礎總結——基于《UVM實戰》示例

2021-01-24 17:49:28 後端開發

一、前言

  作業一直在做SoC驗證,更關注模塊間的連接性和匹配性,所以相比于擅長隨機約束激勵的UVM來說,定向測驗的概念更容易debug,當然前提是IP已經被充分驗證,因此覺得接觸UVM的機會較少,到現在發現即使在SoC驗證中依然有它的用武之地,比如驗證可獨立于CPU作業的IP、快速對系統性能進行評估、重用IP級別的驗證環境,甚至是一些通用的VIP也有基于UVM撰寫的,基于這些考量,也逐漸開始接觸,《UVM實戰》是很多驗證工程師的啟蒙,本文借用書中開頭的示例簡單梳理下UVM的基本知識,

二、UVM基礎概述

  關于UVM的知識網路上已經鋪天蓋地了,下邊的內容只是自己的一些認識和隨記,UVM其實就是基于SV語言寫的用于驗證的代碼庫和對應的驗證規范,下圖是UVM驗證環境的整體結構(圖來源見參考文獻1),圖中注釋介紹了每個組成部分的作用,《UVM實戰》書中給我留下最深刻的印象就是用子彈、彈夾和手槍分別類比transaction sequence和sequencer,這也是UVM環境靈活的重要原因之一,這是激勵的產生機制,至于回應的采集和回應任務會交給monitor和scoreboard,后者中的期望資料或者參考資料的來源比較靈活,函式、檔案或是reference model的回應均可,

  以上是UVM的空間維度,這一概念也被抽象成如下的樹狀結構,各個部分必然存在資訊互動,sequence和sequencer之間傳遞的是transaction,實際上component之間也是transaction級別的通信,叫做TLM (transaction level model)最常見的就是monitor中uvm_analysis_port通過uvm_tlm_analysis_fifo連接到reference model或scoreboard中的uvm_blocking_get_port,這樣可以確保transaction能夠傳遞給目的組件,

  另一方面UVM在時間維度上也做了規范,phase機制明確劃分了各個階段所要完成的任務,其中比較重要的是run phase這一消耗仿真時間的task phase以及ojbection的概念,只有每個phase中所有raise的objection都被drop后才會執行下一個phase的任務,搭建空間與時間維度橋梁的也是Phase--build phase是在樹狀結構中自上而下執行,其他不消耗仿真時間的phase都是自下而上運行,run phase則自上而下啟動同事運行,所有phase的順序見圖3(圖來源見參考文獻2)

  弄明白這三張圖,也就是組件、組件間通信和phase機制,基本上可以看懂別人寫的代碼了,

三、驗證環境示例

  各個UVM object和component:

sequence:

 1 class my_sequence extends uvm_sequence #(my_transaction);
 2     my_transaction m_trans;
 3 
 4     function new(string name="my_sequence");
 5         super.new(name);
 6     endfunction
 7 
 8     virtual task body();
 9         if(starting_phase != null)
10             starting_phase.raise_objection(this);
11 
12         repeat(10) begin
13             `uvm_do(m_trans)
14         end
15         #1000;
16 
17         if(starting_phase != null)
18             starting_phase.drop_objection(this);
19     endtask
20 
21     `uvm_object_utils(my_sequence)
22 
23 endclass
my_sequence

transaction:

 1 `ifndef MY_TRANSACTION__SV
 2 `define MY_TRANSACTION__SV
 3 
 4 class my_transaction extends uvm_sequence_item;
 5 
 6    rand bit[47:0] dmac;
 7    rand bit[47:0] smac;
 8    rand bit[15:0] ether_type;
 9    rand byte      pload[];
10    rand bit[31:0] crc;
11 
12    constraint pload_cons{
13       pload.size >= 46;
14       //pload.size <= 1500;
15       pload.size <= 200;
16       dmac == 48'h01_02_03_04_05_06;
17       smac == 48'h60_50_40_30_20_10;
18 
19    }
20 
21    function bit[31:0] calc_crc();
22       return 32'h0;
23    endfunction
24 
25    function void post_randomize();
26       crc = calc_crc;
27    endfunction
28 
29    //`uvm_object_utils(my_transaction)
30    `uvm_object_utils_begin(my_transaction)
31         `uvm_field_int(dmac,UVM_ALL_ON)
32         `uvm_field_int(smac,UVM_ALL_ON)
33         `uvm_field_int(ether_type,UVM_ALL_ON)
34         `uvm_field_array_int(pload,UVM_ALL_ON)
35         `uvm_field_int(crc,UVM_ALL_ON)
36    `uvm_object_utils_end
37 
38    function new(string name = "my_transaction");
39       super.new();
40    endfunction
41 
42    /*function void my_print();
43       $display("dmac = %0h", dmac);
44       $display("smac = %0h", smac);
45       $display("ether_type = %0h", ether_type);
46       for(int i = 0; i < pload.size; i++) begin
47          $display("pload[%0d] = %0h", i, pload[i]);
48       end
49       $display("crc = %0h", crc);
50    endfunction
51 
52    function void my_copy(my_transaction tr);
53       if(tr == null)
54          `uvm_fatal("my_transaction", "tr is null!!!!")
55       dmac = tr.dmac;
56       smac = tr.smac;
57       ether_type = tr.ether_type;
58       pload = new[tr.pload.size()];
59       for(int i = 0; i < pload.size(); i++) begin
60          pload[i] = tr.pload[i];
61       end
62       crc = tr.crc;
63    endfunction
64 
65    function bit my_compare(my_transaction tr);
66       bit result;
67       
68       if(tr == null)
69          `uvm_fatal("my_transaction", "tr is null!!!!")
70       result = ((dmac == tr.dmac) &&
71                 (smac == tr.smac) &&
72                 (ether_type == tr.ether_type) &&
73                 (crc == tr.crc));
74       if(pload.size() != tr.pload.size())
75          result = 0;
76       else 
77          for(int i = 0; i < pload.size(); i++) begin
78             if(pload[i] != tr.pload[i])
79                result = 0;
80          end
81       return result; 
82    endfunction*/
83 
84 endclass
85 `endif
my_transaction

sequencer:

 1 `ifndef MY_SEQUENCER__SV
 2 `define MY_SEQUENCER__SV
 3 
 4 class my_sequencer extends uvm_sequencer #(my_transaction);
 5    
 6    function new(string name, uvm_component parent);
 7       super.new(name, parent);
 8    endfunction 
 9    
10    `uvm_component_utils(my_sequencer)
11 endclass
12 
13 `endif
my_sequencer

driver:

 1 `ifndef MY_DRIVER__SV
 2 `define MY_DRIVER__SV
 3 class my_driver extends uvm_driver#(my_transaction);
 4 
 5    virtual my_if vif;
 6 
 7    `uvm_component_utils(my_driver)
 8    function new(string name = "my_driver", uvm_component parent = null);
 9       super.new(name, parent);
10    endfunction
11 
12    virtual function void build_phase(uvm_phase phase);
13       super.build_phase(phase);
14       if(!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))
15          `uvm_fatal("my_driver", "virtual interface must be set for vif!!!")
16    endfunction
17 
18    extern task main_phase(uvm_phase phase);
19    extern task drive_one_pkt(my_transaction tr);
20 endclass
21 
22 /*task my_driver::main_phase(uvm_phase phase);
23    my_transaction tr;
24    phase.raise_objection(this);
25    vif.data <= 8'b0;
26    vif.valid <= 1'b0;
27    while(!vif.rst_n)
28       @(posedge vif.clk);
29    for(int i = 0; i < 2; i++) begin 
30       req = new("req");
31       assert(req.randomize() with {pload.size == 200;
32                                   dmac == 48'h01_02_03_04_05_06;
33                                   smac == 48'h60_50_40_30_20_10;
34                                  }                        
35             );
36       drive_one_pkt(req);
37    end
38    repeat(5) @(posedge vif.clk);
39    phase.drop_objection(this);
40 endtask*/
41 
42 task my_driver::main_phase(uvm_phase phase);
43     vif.data <= 8'b0;
44     vif.valid <= 1'b0;
45    
46     while(!vif.rst_n)
47         @(posedge vif.clk);
48     
49     while(1)begin
50         seq_item_port.get_next_item(req);
51         drive_one_pkt(req);
52         seq_item_port.item_done();
53     end
54 endtask
55 
56 task my_driver::drive_one_pkt(my_transaction tr);
57       
58    byte unsigned data_q[];
59    int unsigned data_size;
60 
61    data_size = tr.pack_bytes(data_q)/8;//fill data_q on the order in uvm_object_utils of transaction
62    `uvm_info("my_driver","begin to drive one pkt",UVM_LOW);
63    repeat(3) @(posedge vif.clk);
64    for(int i=0;i<data_size;i++)begin
65         @(posedge vif.clk);
66         vif.valid <= 1'b1;
67         vif.data <= data_q[i];
68    end
69    @(posedge vif.clk);
70    vif.valid <= 1'b0;
71    repeat(10) @(posedge vif.clk);
72    `uvm_info("my_driver","end drive one pkt",UVM_LOW);
73 endtask
74 
75 
76 `endif
my_driver

monitor:

  1 `ifndef MY_MONITOR__SV
  2 `define MY_MONITOR__SV
  3 class my_monitor extends uvm_monitor;
  4 
  5    virtual my_if vif;
  6 
  7    uvm_analysis_port #(my_transaction)  ap;
  8    
  9    `uvm_component_utils(my_monitor)
 10    function new(string name = "my_monitor", uvm_component parent = null);
 11       super.new(name, parent);
 12    endfunction
 13 
 14    virtual function void build_phase(uvm_phase phase);
 15       super.build_phase(phase);
 16       if(!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))
 17          `uvm_fatal("my_monitor", "virtual interface must be set for vif!!!")
 18       ap = new("ap", this);
 19    endfunction
 20 
 21    extern task main_phase(uvm_phase phase);
 22    extern task collect_one_pkt(my_transaction tr);
 23 endclass
 24 
 25 task my_monitor::main_phase(uvm_phase phase);
 26    my_transaction tr;
 27    while(1) begin
 28       tr = new("tr");
 29       collect_one_pkt(tr);
 30       ap.write(tr);
 31    end
 32 endtask
 33 
 34 /*task my_monitor::collect_one_pkt(my_transaction tr);
 35    bit[7:0] data_q[$]; 
 36    int psize;
 37    while(1) begin
 38       @(posedge vif.clk);
 39       if(vif.valid) break;
 40    end
 41 
 42    `uvm_info("my_monitor", "begin to collect one pkt", UVM_LOW);
 43    while(vif.valid) begin
 44       data_q.push_back(vif.data);
 45       @(posedge vif.clk);
 46    end
 47    //pop dmac
 48    for(int i = 0; i < 6; i++) begin
 49       tr.dmac = {tr.dmac[39:0], data_q.pop_front()};
 50    end
 51    //pop smac
 52    for(int i = 0; i < 6; i++) begin
 53       tr.smac = {tr.smac[39:0], data_q.pop_front()};
 54    end
 55    //pop ether_type
 56    for(int i = 0; i < 2; i++) begin
 57       tr.ether_type = {tr.ether_type[7:0], data_q.pop_front()};
 58    end
 59 
 60    psize = data_q.size() - 4;
 61    tr.pload = new[psize];
 62    //pop payload
 63    for(int i = 0; i < psize; i++) begin
 64       tr.pload[i] = data_q.pop_front();
 65    end
 66    //pop crc
 67    for(int i = 0; i < 4; i++) begin
 68       tr.crc = {tr.crc[23:0], data_q.pop_front()};
 69    end
 70    `uvm_info("my_monitor", "end collect one pkt", UVM_LOW);
 71 endtask*/
 72 
 73 task my_monitor::collect_one_pkt(my_transaction tr);
 74     byte unsigned data_q[$];
 75     byte unsigned data_array[];
 76 
 77     logic [8-1:0] data;
 78     logic valid=0;
 79     int data_size;
 80 
 81     while(1) begin
 82       @(posedge vif.clk);
 83       if(vif.valid) break;
 84     end
 85 
 86 
 87     `uvm_info("my_monitor","begin to collect one pkt",UVM_LOW);
 88     while(vif.valid)begin
 89         data_q.push_back(vif.data);
 90         @(posedge vif.clk);
 91     end
 92 
 93     data_size = data_q.size();
 94     data_array = new[data_size];
 95     for(int i=0;i<data_size;i++)begin
 96         data_array[i] = data_q[i];
 97     end
 98 
 99     tr.pload = new[data_size-18];
100     data_size = tr.unpack_bytes(data_array)/8;
101     `uvm_info("my_monitor","end collect one pkt",UVM_LOW);
102 endtask
103 
104 
105 `endif
my_monitor

agent:

 1 `ifndef MY_AGENT__SV
 2 `define MY_AGENT__SV
 3 
 4 class my_agent extends uvm_agent ;
 5    my_sequencer sqr;
 6    my_driver     drv;
 7    my_monitor    mon;
 8    
 9    uvm_analysis_port #(my_transaction)  ap;
10    
11    function new(string name, uvm_component parent);
12       super.new(name, parent);
13    endfunction 
14    
15    extern virtual function void build_phase(uvm_phase phase);
16    extern virtual function void connect_phase(uvm_phase phase);
17 
18    `uvm_component_utils(my_agent)
19 endclass 
20 
21 
22 function void my_agent::build_phase(uvm_phase phase);
23    super.build_phase(phase);
24    if (is_active == UVM_ACTIVE) begin
25        sqr = my_sequencer::type_id::create("sqr",this);
26        drv = my_driver::type_id::create("drv", this);
27    end
28    mon = my_monitor::type_id::create("mon", this);
29 endfunction 
30 
31 function void my_agent::connect_phase(uvm_phase phase);
32    super.connect_phase(phase);
33    if(is_active == UVM_ACTIVE)begin
34         drv.seq_item_port.connect(sqr.seq_item_export);   
35    end
36    ap = mon.ap;
37 endfunction
38 
39 `endif
my_agent

reference model:

 1 `ifndef MY_MODEL__SV
 2 `define MY_MODEL__SV
 3 
 4 class my_model extends uvm_component;
 5    
 6    uvm_blocking_get_port #(my_transaction)  port;
 7    uvm_analysis_port #(my_transaction)  ap;
 8 
 9    extern function new(string name, uvm_component parent);
10    extern function void build_phase(uvm_phase phase);
11    extern virtual  task main_phase(uvm_phase phase);
12 
13    `uvm_component_utils(my_model)
14 endclass 
15 
16 function my_model::new(string name, uvm_component parent);
17    super.new(name, parent);
18 endfunction 
19 
20 function void my_model::build_phase(uvm_phase phase);
21    super.build_phase(phase);
22    port = new("port", this);
23    ap = new("ap", this);
24 endfunction
25 
26 task my_model::main_phase(uvm_phase phase);
27    my_transaction tr;
28    my_transaction new_tr;
29    super.main_phase(phase);
30    while(1) begin
31       port.get(tr);
32       new_tr = new("new_tr");
33       //new_tr.my_copy(tr);
34       new_tr.copy(tr);
35       `uvm_info("my_model", "get one transaction, copy and print it:", UVM_LOW)
36       //new_tr.my_print();
37       new_tr.print();
38       ap.write(new_tr);
39    end
40 endtask
41 `endif
my_model

scoreboard:

 1 `ifndef MY_SCOREBOARD__SV
 2 `define MY_SCOREBOARD__SV
 3 class my_scoreboard extends uvm_scoreboard;
 4    my_transaction  expect_queue[$];
 5    uvm_blocking_get_port #(my_transaction)  exp_port;
 6    uvm_blocking_get_port #(my_transaction)  act_port;
 7    `uvm_component_utils(my_scoreboard)
 8 
 9    extern function new(string name, uvm_component parent = null);
10    extern virtual function void build_phase(uvm_phase phase);
11    extern virtual task main_phase(uvm_phase phase);
12 endclass 
13 
14 function my_scoreboard::new(string name, uvm_component parent = null);
15    super.new(name, parent);
16 endfunction 
17 
18 function void my_scoreboard::build_phase(uvm_phase phase);
19    super.build_phase(phase);
20    exp_port = new("exp_port", this);
21    act_port = new("act_port", this);
22 endfunction 
23 
24 task my_scoreboard::main_phase(uvm_phase phase);
25    my_transaction  get_expect,  get_actual, tmp_tran;
26    bit result;
27  
28    super.main_phase(phase);
29    fork 
30       while (1) begin
31          exp_port.get(get_expect);
32          expect_queue.push_back(get_expect);
33       end
34       while (1) begin
35          act_port.get(get_actual);
36          if(expect_queue.size() > 0) begin
37             tmp_tran = expect_queue.pop_front();
38             //result = get_actual.my_compare(tmp_tran);
39             result = get_actual.compare(tmp_tran);
40             if(result) begin 
41                `uvm_info("my_scoreboard", "Compare SUCCESSFULLY", UVM_LOW);
42             end
43             else begin
44                `uvm_error("my_scoreboard", "Compare FAILED");
45                $display("the expect pkt is");
46                //tmp_tran.my_print();
47                tmp_tran.print();
48                $display("the actual pkt is");
49                //get_actual.my_print();
50                get_actual.print();
51             end
52          end
53          else begin
54             `uvm_error("my_scoreboard", "Received from DUT, while Expect Queue is empty");
55             $display("the unexpected pkt is");
56             //get_actual.my_print();
57             get_actual.print();
58          end 
59       end
60    join
61 endtask
62 `endif
my_scoreboard

  base test:

 1 `ifndef BASE_TEST__SV
 2 `define BASE_TEST__SV
 3 
 4 class base_test extends uvm_test;
 5 
 6    my_env         env;
 7    
 8    function new(string name = "base_test", uvm_component parent = null);
 9       super.new(name,parent);
10    endfunction
11    
12    extern virtual function void build_phase(uvm_phase phase);
13    extern virtual function void report_phase(uvm_phase phase);
14    `uvm_component_utils(base_test)
15 endclass
16 
17 
18 function void base_test::build_phase(uvm_phase phase);
19    super.build_phase(phase);
20    env  =  my_env::type_id::create("env", this); 
21    //uvm_config_db#(uvm_object_wrapper)::set(this,
22                                            //"env.i_agt.sqr.main_phase",
23                                            //"default_sequence",
24                                            // my_sequence::type_id::get());
25 endfunction
26 
27 function void base_test::report_phase(uvm_phase phase);
28    uvm_report_server server;
29    int err_num;
30    super.report_phase(phase);
31 
32    server = get_report_server();
33    err_num = server.get_severity_count(UVM_ERROR);
34 
35    if (err_num != 0) begin
36       $display("TEST CASE FAILED");
37    end
38    else begin
39       $display("TEST CASE PASSED");
40    end
41 endfunction
42 
43 `endif
base_test

  Interface:

 1 `ifndef MY_IF__SV
 2 `define MY_IF__SV
 3 
 4 interface my_if(input clk, input rst_n);
 5 
 6    logic [7:0] data;
 7    logic valid;
 8 endinterface
 9 
10 `endif
my_if

  testbench top:

 1 `timescale 1ns/1ps
 2 `include "uvm_macros.svh"
 3 
 4 import uvm_pkg::*;
 5 `include "my_if.sv"
 6 `include "my_transaction.sv"
 7 //`include "my_sequence.sv"
 8 `include "my_driver.sv"
 9 `include "my_monitor.sv"
10 `include "my_sequencer.sv"
11 `include "my_agent.sv"
12 `include "my_model.sv"
13 `include "my_scoreboard.sv"
14 `include "my_env.sv"
15 `include "base_test.sv"
16 `include "my_case0.sv"
17 `include "my_case1.sv"
18 
19 module top_tb;
20 
21 reg clk;
22 reg rst_n;
23 reg[7:0] rxd;
24 reg rx_dv;
25 wire[7:0] txd;
26 wire tx_en;
27 
28 my_if input_if(clk, rst_n);
29 my_if output_if(clk, rst_n);
30 
31 dut my_dut(.clk(clk),
32            .rst_n(rst_n),
33            .rxd(input_if.data),
34            .rx_dv(input_if.valid),
35            .txd(output_if.data),
36            .tx_en(output_if.valid));
37 
38 initial begin
39    clk = 0;
40    forever begin
41       #100 clk = ~clk;
42    end
43 end
44 
45 initial begin
46    rst_n = 1'b0;
47    #1000;
48    rst_n = 1'b1;
49 end
50 
51 initial begin
52    //run_test("my_env");
53    run_test();
54 end
55 
56 initial begin
57    uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.i_agt.drv", "vif", input_if);
58    uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.i_agt.mon", "vif", input_if);
59    uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.o_agt.mon", "vif", output_if);
60 end
61 
62     //Enable dump waveform
63     initial
64     begin
65       $shm_open("test.shm");
66       $shm_probe(top_tb,"ACTFM");
67       #1ms;
68       $shm_close;
69     end
70 
71 endmodule
top_tb

   需要注意是在定義class前,如果這個class會使用到其他class,最好在前面加type class <class name>,例如在class my_sequence extends uvm_sequence前一行加上type class my_transaction,否則如果my_sequence在my_transaction之前編譯,就會報錯,雖然可以通過在testbench top中先include my_transaction.sv解決,但是大大降低了代碼的重用性,

四、測驗用例及仿真

 1 `ifndef MY_CASE0__SV
 2 `define MY_CASE0__SV
 3 class case0_sequence extends uvm_sequence #(my_transaction);
 4    my_transaction m_trans;
 5 
 6    function  new(string name= "case0_sequence");
 7       super.new(name);
 8    endfunction 
 9    
10    virtual task body();
11       if(starting_phase != null) 
12          starting_phase.raise_objection(this);
13       repeat (10) begin
14          `uvm_do(m_trans)
15       end
16       #100;
17       if(starting_phase != null) 
18          starting_phase.drop_objection(this);
19    endtask
20 
21    `uvm_object_utils(case0_sequence)
22 endclass
23 
24 
25 class my_case0 extends base_test;
26 
27    function new(string name = "my_case0", uvm_component parent = null);
28       super.new(name,parent);
29    endfunction 
30    extern virtual function void build_phase(uvm_phase phase); 
31    `uvm_component_utils(my_case0)
32 endclass
33 
34 
35 function void my_case0::build_phase(uvm_phase phase);
36    super.build_phase(phase);
37 
38    uvm_config_db#(uvm_object_wrapper)::set(this, 
39                                            "env.i_agt.sqr.main_phase", 
40                                            "default_sequence", 
41                                            case0_sequence::type_id::get());
42 endfunction
43 
44 `endif
my_case0

  所用的測驗用例都擴展自自定義的base_test,后者又來自uvm_test,base_test例化整個UVM environment,用例中主要要做的事情就是啟動sequence, 包括呼叫start任務手動啟動和自動啟動方式,具體見參考文獻3.這里是最常見的自動啟動方式:用uvm_config_db將要啟動的sequence設定為sequencer main_phase的default_sequence.

  每個sequence中都有個叫body的task,當sequence被啟動時會自動呼叫這個task,通過`uvm_do宏來產生transaction,更靈活的方式是先后使用`uvm_create()和`uvm_send()實作這一功能,并在兩者間控制transaction的各個field,只有當消耗仿真時間的driver呼叫了item_done()后一次transaction的發送才算結束,

五、總結

   我們不創造知識,我們只是知識的搬運工,將知識靈活運用,創造出合理高效可重用的VIP,驗證環境乃至整個驗證流程方法是IC驗證的核心技能,這些技能都是為盡可能快速發現潛在問題這一核心任務做的準備,

六、參考文獻

1 UVM——基礎類結構圖(uvm樹、常用繼承關系結構)https://blog.csdn.net/weixin_46022434/article/details/105838815

2 UVM phase機制 https://blog.csdn.net/qq_41394155/article/details/81914826

3 UVM中啟動sequence的方法 https://aijishu.com/a/1060000000132327

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/251415.html

標籤:Verilog

上一篇:翻譯:《實用的Python編程》00_Setup

下一篇:通程序式自動設定網卡的“internet共享”選項

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more