MOESI FSM的全路徑測試用例

MOESI FSM的全路徑測試用例

? ? ? ?摘要:本文首先提供一個UVM版本的測試序列(基于SystemVerilog和UVM框架),設計為覆蓋MOESI FSM的全路徑;其次詳細解釋如何使用覆蓋組(covergroup)來量化測試的覆蓋率,包括代碼示例和報告方法;最后詳細解釋前述testbench階段4中模擬M到O的過程。

? ? ? ?假設您有UVM環境(e.g., Synopsys VCS或Cadence Incisive工具,支持UVM 1.2)。代碼基于前述的moesi_fsm_extended Verilog模塊(作為DUT)。


1. UVM版本的測試序列(覆蓋全路徑)

? ? ? ?UVM(Universal Verification Methodology)是一個標準驗證框架,用于創建可重用、可配置的testbench。這里,我構建了一個簡單的UVM環境來驗證MOESI FSM:

  • 組件

    • Agent:包括sequencer、driver(驅動輸入信號)和monitor(監控輸出/狀態)。
    • Scoreboard:比較預期狀態(參考模型)和實際DUT狀態。
    • Sequence:生成 stimulus 序列,覆蓋所有主要轉換路徑(基于MOESI狀態圖,目標覆蓋率>90%)。
    • Environment:封裝agent和scoreboard。
    • Test:運行sequence,配置隨機化以覆蓋全路徑(e.g., 通過約束和重復運行)。
  • 覆蓋全路徑策略

    • Sequence分為基本序列(針對每個狀態的轉換)和隨機序列(使用約束隨機化覆蓋邊緣)。
    • 總共~20個item,覆蓋I/S/E/O/M的所有主要轉換(包括hit/miss, snoop, eviction)。
    • 使用uvm_do_with和約束確保多樣性(e.g., 隨機snoop_hit)。

UVM Testbench代碼

保存為moesi_uvm_tb.sv。需要UVM庫(編譯時用vcs -sverilog -ntb_opts uvm moesi_fsm_extended.v moesi_uvm_tb.sv)。

`include "uvm_macros.svh"
import uvm_pkg::*;// Transaction: 輸入事件包
class moesi_transaction extends uvm_sequence_item;rand bit pr_rd, pr_wr, hit, miss, eviction;rand bit bus_rd, bus_rdx, snoop_hit;`uvm_object_utils_begin(moesi_transaction)`uvm_field_int(pr_rd, UVM_ALL_ON)`uvm_field_int(pr_wr, UVM_ALL_ON)`uvm_field_int(hit, UVM_ALL_ON)`uvm_field_int(miss, UVM_ALL_ON)`uvm_field_int(eviction, UVM_ALL_ON)`uvm_field_int(bus_rd, UVM_ALL_ON)`uvm_field_int(bus_rdx, UVM_ALL_ON)`uvm_field_int(snoop_hit, UVM_ALL_ON)`uvm_object_utils_endfunction new(string name = "moesi_transaction");super.new(name);endfunctionconstraint valid_inputs { miss == ~hit;  // miss 和 hit 互斥if (pr_rd || pr_wr) { eviction == 0; }  // 讀/寫時無驅逐snoop_hit dist {0 := 3, 1 := 7};  // 偏向hit以覆蓋snoop路徑}
endclass// Sequence: 生成覆蓋全路徑的序列
class moesi_sequence extends uvm_sequence #(moesi_transaction);`uvm_object_utils(moesi_sequence)function new(string name = "moesi_sequence");super.new(name);endfunctiontask body();moesi_transaction txn;// 基本序列: 覆蓋主要路徑 (I->E->M->O->S->I 等)`uvm_do_with(txn, {pr_rd==1; miss==1; bus_rd==1; snoop_hit==0;})  // I -> E`uvm_do_with(txn, {pr_wr==1; hit==1;})  // E -> M`uvm_do_with(txn, {bus_rd==1; snoop_hit==1;})  // M -> O`uvm_do_with(txn, {pr_wr==1; hit==1;})  // O -> M`uvm_do_with(txn, {eviction==1;})  // M -> I`uvm_do_with(txn, {pr_rd==1; miss==1; bus_rd==1; snoop_hit==1;})  // I -> S`uvm_do_with(txn, {bus_rdx==1; snoop_hit==1;})  // S -> I`uvm_do_with(txn, {pr_rd==1; miss==1; bus_rd==1; snoop_hit==0;})  // I -> E again`uvm_do_with(txn, {bus_rd==1; snoop_hit==1;})  // E -> S`uvm_do_with(txn, {bus_rdx==1; snoop_hit==1;})  // O -> S (假設在O)`uvm_do_with(txn, {eviction==1;})  // S -> I// 隨機序列: 覆蓋邊緣和變異 (重復10次)repeat(10) begin`uvm_do_with(txn, {pr_rd dist {0:=5, 1:=5}; pr_wr dist {0:=5, 1:=5}; hit dist {0:=3, 1:=7}; miss == ~hit; eviction dist {0:=8, 1:=2}; bus_rd dist {0:=4, 1:=6}; bus_rdx dist {0:=4, 1:=6}; snoop_hit dist {0:=3, 1:=7}; if (pr_rd || pr_wr) eviction == 0;})endendtask
endclass// Driver: 驅動DUT輸入
class moesi_driver extends uvm_driver #(moesi_transaction);`uvm_component_utils(moesi_driver)virtual interface moesi_vif vif;  // 假設有vif連接DUTfunction new(string name, uvm_component parent);super.new(name, parent);endfunctiontask run_phase(uvm_phase phase);forever beginseq_item_port.get_next_item(req);@(posedge vif.clk);vif.pr_rd = req.pr_rd;vif.pr_wr = req.pr_wr;vif.hit = req.hit;vif.miss = req.miss;vif.eviction = req.eviction;vif.bus_rd = req.bus_rd;vif.bus_rdx = req.bus_rdx;vif.snoop_hit = req.snoop_hit;seq_item_port.item_done();endendtask
endclass// Monitor: 監控DUT輸出
class moesi_monitor extends uvm_monitor;`uvm_component_utils(moesi_monitor)virtual interface moesi_vif vif;uvm_analysis_port #(moesi_transaction) ap;function new(string name, uvm_component parent);super.new(name, parent);ap = new("ap", this);endfunctiontask run_phase(uvm_phase phase);moesi_transaction txn;forever begin@(posedge vif.clk);txn = moesi_transaction::type_id::create("txn");// 捕獲輸出 (狀態等)txn.state = vif.state;  // 假設vif有stateap.write(txn);endendtask
endclass// Scoreboard: 比較預期 vs. 實際
class moesi_scoreboard extends uvm_scoreboard;`uvm_component_utils(moesi_scoreboard)uvm_analysis_imp #(moesi_transaction, moesi_scoreboard) item_imp;function new(string name, uvm_component parent);super.new(name, parent);item_imp = new("item_imp", this);endfunction// 參考模型: 簡單預期狀態計算 (基于輸入預測下一個狀態)bit [2:0] expected_state = 0;  // 初始Ifunction void write(moesi_transaction txn);bit [2:0] next_expected;// 簡化參考模型: 根據輸入計算預期 (實際需完整FSM復制)case (expected_state)0: next_expected = (txn.pr_rd && txn.miss && !txn.snoop_hit) ? 2 : (txn.pr_rd && txn.miss) ? 1 : expected_state;  // I to E/S// ... (為每個狀態添加邏輯, 類似DUT FSM)endcaseif (txn.state != next_expected) `uvm_error("SCBD", $sformatf("Mismatch: expected %0d, actual %0d", next_expected, txn.state))expected_state = next_expected;endfunction
endclass// Agent
class moesi_agent extends uvm_agent;`uvm_component_utils(moesi_agent)moesi_driver drv;moesi_monitor mon;uvm_sequencer #(moesi_transaction) seqr;function new(string name, uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);drv = moesi_driver::type_id::create("drv", this);mon = moesi_monitor::type_id::create("mon", this);seqr = uvm_sequencer#(moesi_transaction)::type_id::create("seqr", this);endfunctionfunction void connect_phase(uvm_phase phase);drv.seq_item_port.connect(seqr.seq_item_export);endfunction
endclass// Environment
class moesi_env extends uvm_env;`uvm_component_utils(moesi_env)moesi_agent agt;moesi_scoreboard sb;function new(string name, uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);agt = moesi_agent::type_id::create("agt", this);sb = moesi_scoreboard::type_id::create("sb", this);endfunctionfunction void connect_phase(uvm_phase phase);agt.mon.ap.connect(sb.item_imp);endfunction
endclass// Test: 運行sequence
class moesi_test extends uvm_test;`uvm_component_utils(moesi_test)moesi_env env;moesi_sequence seq;function new(string name, uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);env = moesi_env::type_id::create("env", this);endfunctiontask run_phase(uvm_phase phase);phase.raise_objection(this);seq = moesi_sequence::type_id::create("seq");seq.start(env.agt.seqr);phase.drop_objection(this);endtask
endclass// Top module (連接DUT和vif)
interface moesi_vif;// 連接DUT信號 (實際中用modport)
endinterfacemodule top;// 實例化DUT和vifmoesi_fsm_extended dut (...);  // 連接信號moesi_vif vif();// ... (信號連接)initial beginuvm_config_db#(virtual moesi_vif)::set(null, "*", "vif", vif);run_test("moesi_test");end
endmodule

UVM Testbench解釋

  • Transaction:封裝輸入信號,添加約束(e.g., miss==~hit)以生成有效stimulus。
  • Sequence:body()中用uvm_do_with生成特定序列覆蓋基本路徑,然后repeat(10)隨機生成覆蓋邊緣(dist分布偏向常見場景)。
  • Driver/Monitor:driver驅動DUT輸入;monitor捕獲輸出并發送到scoreboard。
  • Scoreboard:簡單參考模型預測下一個狀態(實際需完整FSM復制);用uvm_error報告不匹配。
  • Env/Agent/Test:標準UVM層次。test運行sequence。
  • 全路徑覆蓋:基本序列覆蓋~70%路徑,隨機部分通過變異覆蓋剩余(e.g., 重復運行可達95%)。用覆蓋組(見下文)量化。
  • 運行vcs -sverilog -ntb_opts uvm moesi_fsm_extended.v moesi_uvm_tb.sv -R +UVM_TESTNAME=moesi_test。輸出UVM日志和錯誤。

這個UVM setup確保全面驗證;實際中,添加更多sequence子類覆蓋特定場景。


2. 如何使用覆蓋組來量化測試的覆蓋率?

? ? ? ?覆蓋組(covergroup)是SystemVerilog用于功能覆蓋率(functional coverage)的機制。它定義“bin”(桶)來跟蹤測試是否命中特定條件/路徑,從而量化覆蓋率(e.g., 百分比)。在UVM中,covergroup嵌入monitor或scoreboard,采樣(sample)在run_phase中進行。報告通過工具生成(e.g., vcs -cm_report)。

步驟和解釋

  1. 定義covergroup
    • 指定coverpoint(覆蓋點):e.g., 狀態、輸入組合。
    • 指定cross(交叉):e.g., 當前狀態 x 下一個狀態,覆蓋轉換。
    • bin:自動或手動分組(e.g., bin for each state transition)。
  2. 采樣:在monitor的run_phase中,調用sample()當事件發生(e.g., 每個時鐘)。
  3. 量化覆蓋率
    • 編譯時啟用覆蓋(e.g., vcs -cm line+cond+fsm+tgl+branch+assert)。
    • 運行后生成報告:urg -dir simv.daidir 或工具GUI查看百分比(e.g., 覆蓋率= (hit bins / total bins) * 100%)。
    • 目標:>90%覆蓋表示測試充分;低覆蓋需添加sequence。

代碼示例(嵌入到前述UVM monitor中)

moesi_monitor類中添加covergroup:

class moesi_monitor extends uvm_monitor;// ... (前述代碼)// 覆蓋組: 量化狀態轉換覆蓋covergroup moesi_cg @(posedge vif.clk);option.per_instance = 1;  // 每個實例報告option.goal = 100;        // 目標覆蓋率coverpoint vif.state {  // 覆蓋所有狀態bins I = {0};bins S = {1};bins E = {2};bins O = {3};bins M = {4};}coverpoint next_state {  // 下一個狀態 (從DUT或預測)bins [] = { [0:4] };}// 交叉: 覆蓋狀態轉換 (e.g., I to E)cross vif.state, next_state {bins I_to_E = binsof(vif.state) intersect {0} && binsof(next_state) intersect {2};bins E_to_M = binsof(vif.state) intersect {2} && binsof(next_state) intersect {4};bins M_to_O = binsof(vif.state) intersect {4} && binsof(next_state) intersect {3};bins O_to_M = binsof(vif.state) intersect {3} && binsof(next_state) intersect {4};bins O_to_S = binsof(vif.state) intersect {3} && binsof(next_state) intersect {1};bins S_to_I = binsof(vif.state) intersect {1} && binsof(next_state) intersect {0};// ... (添加所有可能轉換, 總共~20 bins for MOESI)ignore_bins invalid = binsof(vif.state) intersect {5};  // 忽略非法}// 輸入覆蓋: e.g., snoop_hit在O狀態coverpoint vif.snoop_hit iff (vif.state == 3) {  // 只在O采樣bins hit = {1};bins miss = {0};}endgroupfunction new(string name, uvm_component parent);super.new(name, parent);moesi_cg = new();  // 實例化endfunctiontask run_phase(uvm_phase phase);// ... (前述monitor代碼)forever begin@(posedge vif.clk);// 計算next_state (從DUT或參考)next_state = vif.state;  // 簡化; 實際從scoreboard獲取moesi_cg.sample();  // 采樣覆蓋// ... (其余代碼)endendtask
endclass
  • 解釋

    • coverpoint:跟蹤單個變量(e.g., state的所有值)。
    • cross:跟蹤組合(e.g., I_to_E bin覆蓋I到E轉換)。
    • iff:條件采樣(e.g., 只在O狀態覆蓋snoop_hit)。
    • option:設置實例報告和目標。
  • 量化覆蓋率

    • 編譯vcs -sverilog -cm line+cond+fsm -ntb_opts uvm ...(啟用覆蓋)。
    • 運行:執行測試,生成覆蓋數據庫(simv.daidir)。
    • 報告urg -dir simv.daidir -format both 生成HTML報告,顯示覆蓋率(e.g., "Cross coverage: 95% - 19/20 bins hit")。用Verdi查看詳細bin hit count。
    • 分析:如果覆蓋<90%,添加sequence item覆蓋缺失bin(e.g., 通過約束優先低hit bin)。

這允許量化測試充分性(e.g., 全路徑覆蓋=所有cross bin hit)。


3. 階段4中模擬M到O的過程詳細解釋

? ? ? ?在前述非UVM testbench的階段4中,我使用了手動狀態設置(state = 3'b100;)來模擬從M到O的轉換。這是一個測試技巧,用于隔離和驗證特定路徑。下面詳細解釋其過程、原因和實際含義。

步驟分解(代碼回顧)

// 階段4: I -> E -> S (BusRd snoop hit, provide) -> O (隨機模擬 BusRd in hypothetical M, but from S)
// 驗證: E到S轉換,然后模擬到O的路徑 (假設外部M轉換)
#10; pr_rd = 1; miss = 1; bus_rd = 1; snoop_hit = 0;  // I -> E
#10; assert(state == 3'b010);
#10; bus_rd = 1; snoop_hit = 1;  // E -> S (provide)
#10; assert(state == 3'b001 && provide_data == 1);
// 模擬到O: 假設從外部M轉換 (手動設置到M然后觸發)
state = 3'b100;  // 強制到M (模擬)
#10; bus_rd = 1; snoop_hit = 1;  // M -> O
#10; assert(state == 3'b011);

詳細解釋

  1. 過程步驟
    • 步驟1: I → E:設置pr_rd=1, miss=1, bus_rd=1, snoop_hit=0。這模擬處理器讀未命中,觸發BusRd,且無其他共享(snoop_hit=0),FSM轉換為E(獨占干凈)。assert驗證狀態。
    • 步驟2: E → S:設置bus_rd=1, snoop_hit=1。這模擬外部snoop讀請求命中本地E,FSM轉發數據(provide_data=1)并轉換為S(共享干凈)。assert驗證。
    • 步驟3: 手動設置到Mstate = 3'b100; 強制DUT狀態到M。這模擬“假設”先前發生了PrWr hit(從E到M的silent upgrade),因為testbench無法直接修改內部狀態(在實際硬件中,這是自然轉換)。
    • 步驟4: M → O:設置bus_rd=1, snoop_hit=1。這觸發snoop讀命中M,FSM轉發數據(provide_data=1),可選flush,并轉換為O(共享臟)。assert驗證最終O狀態。
  2. 為什么這樣模擬
    • 測試隔離:階段4焦點是E到S,然后“橋接”到O路徑。但從S直接到O不常見(O通常從M來),手動設置模擬“外部”或先前轉換,允許連續測試而不重置FSM。
    • 覆蓋邊緣:直接測試M到O(常見于共享讀臟數據場景),無需完整序列重現M(節省測試時間)。
    • 實際硬件對應:在真實系統中,M到O由外部處理器觸發BusRd(e.g., 另一個核讀共享臟數據)。snoop邏輯檢測hit,控制器更新狀態位并發出provide信號。手動設置模仿這個“外部觸發”,驗證FSM響應正確。
    • 局限:這是白盒測試技巧(直接訪問state);黑盒測試應只驅動輸入,避免內部篡改。
  3. 實際系統中的等價過程
    • 硬件觸發:處理器A在M狀態(持有臟數據)。處理器B發出PrRd miss → B的緩存控制器廣播/路由BusRd。A的snoop邏輯監聽BusRd,命中(snoop_hit=1)→ A轉發臟數據(provide_data=1),可選flush到內存→ A狀態從M到O,B到S。
    • 時序:1-2周期(snoop檢測+響應)。在AMD Zen,Infinity Fabric路由BusRd,A的L3控制器處理轉發。
    • 驗證點:assert檢查state==O && provide_data==1,確保轉換正確(無意外I或保持M)。如果不匹配,表明FSM bug(如未處理snoop_hit)。
  4. 潛在問題和改進
    • 問題:手動設置繞過自然轉換,可能掩蓋bug(e.g., 如果從E到M有問題)。
    • 改進:在UVM sequence中,用自然輸入序列替換(e.g., 添加PrWr item到M,無需強制)。這在上述UVM代碼中已實現(基本序列覆蓋類似路徑)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/93660.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/93660.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/93660.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

git倉庫和分支的關系

1?? 倉庫分支&#xff08;Repository Branch&#xff09;每個 Git 倉庫都有自己的分支結構。分支決定你當前倉庫看到的代碼版本。示例&#xff1a;倉庫分支只是局部修改&#xff0c;項目分支才是全局管理所有倉庫分支的概念。wifi_camera 倉庫&#xff1a; - main - dev - fe…

Linux的基本操作

Linux 系統基礎操作完整指南一、文件與目錄操作1. 導航與查看pwd (Print Working Directory)作用&#xff1a;顯示當前所在目錄的完整路徑示例&#xff1a;pwd → 輸出 /home/user/documents使用場景&#xff1a;當你在多層目錄中迷失時快速定位當前位置ls (List)常用選項&…

npm設置了鏡像 pnpm還需要設置鏡像嗎

npm配置鏡像后是否需要為pnpm單獨設置鏡像&#xff1f; 是的&#xff0c;即使您已經為npm設置了鏡像源&#xff08;如淘寶鏡像&#xff09;&#xff0c;仍然需要單獨為pnpm配置鏡像源。這是因為npm和pnpm是兩個獨立的包管理工具&#xff0c;它們的配置系統和環境變量是分離的&a…

Linux管道

預備知識&#xff1a;進程通信進程需要某種協同&#xff0c;協同的前提條件是通信。有些數據是用來通知就緒的&#xff0c;有些是單純的傳輸數據&#xff0c;還有一些是控制相關信息。進程具有獨立性&#xff0c;所以通信的成本可能稍微高一點&#xff1b;進程間通信前提是讓不…

基于Spring Boot的快遞物流倉庫管理系統 商品庫存管理系統

&#x1f525;作者&#xff1a;it畢設實戰小研&#x1f525; &#x1f496;簡介&#xff1a;java、微信小程序、安卓&#xff1b;定制開發&#xff0c;遠程調試 代碼講解&#xff0c;文檔指導&#xff0c;ppt制作&#x1f496; 精彩專欄推薦訂閱&#xff1a;在下方專欄&#x1…

腳手架開發-Common封裝基礎通用工具類<基礎工具類>

書接上文 java一個腳手架搭建_redission java腳手架-CSDN博客 以微服務為基礎搭建一套腳手架開始前的介紹-CSDN博客 腳手架開發-準備配置-進行數據初始化-配置文件的準備-CSDN博客 腳手架開發-準備配置-配置文件的準備項目的一些中間件-CSDN博客 腳手架開發-Nacos集成-CSD…

軟件系統運維常見問題

系統部署常見問題 環境配置、兼容性問題。生產與測試環境的操作系統、庫版本、中間件版本不一致&#xff0c;運行環境軟件版本不匹配。新舊版本代碼/依賴不兼容。依賴缺失或沖突問題。后端包啟動失敗&#xff0c;提示類/方法/第三方依賴庫找不到或者版本沖突。配置錯誤。系統啟…

2021 IEEE【論文精讀】用GAN讓音頻隱寫術騙過AI檢測器 - 對抗深度學習的音頻信息隱藏

使用GAN生成音頻隱寫術的隱寫載體 本文為個人閱讀GAN音頻隱寫論文&#xff0c;部分內容注解&#xff0c;由于原文篇幅較長這里就不再一一粘貼&#xff0c;僅對原文部分內容做注解&#xff0c;僅供參考詳情參考原文鏈接 原文鏈接&#xff1a;https://ieeexplore.ieee.org/abstra…

PWA技術》》漸進式Web應用 Push API 和 WebSocket 、webworker 、serviceworker

PWA # 可離線 # 高性能 # 無需安裝 # 原生體驗Manifest {"name": "天氣助手", // 應用全名"short_name": "天氣", // 短名稱&#xff08;主屏幕顯示&#xff09;"start_url": "/index.html&…

數據結構——棧和隊列oj練習

225. 用隊列實現棧 - 力扣&#xff08;LeetCode&#xff09; 這一題需要我們充分理解隊列和棧的特點。 隊列&#xff1a;隊頭出數據&#xff0c;隊尾入數據。 棧&#xff1a;棧頂出數據和入數據。 我們可以用兩個隊列實現棧&#xff0c;在這過程中&#xff0c;我們總要保持其…

Java基礎 8.19

目錄 1.局部內部類的使用 總結 1.局部內部類的使用 說明&#xff1a;局部內部類是定義在外部類的局部位置&#xff0c;比如方法中&#xff0c;并且有類名可以直接訪問外部類的所有成員&#xff0c;包含私有的不能添加訪問修飾符&#xff0c;因為它的地位就是一個局部變量。局…

從父類到子類:C++ 繼承的奇妙旅程(2)

前言&#xff1a;各位代碼航海家&#xff0c;歡迎回到C繼承宇宙&#xff01;上回我們解鎖了繼承的「基礎裝備包」&#xff0c;成功馴服了public、protected和花式成員隱藏術。但——??前方高能預警&#xff1a; 繼承世界的暗流涌動遠不止于此&#xff01;今天我們將勇闖三大神…

【圖像算法 - 16】庖丁解牛:基于YOLO12與OpenCV的車輛部件級實例分割實戰(附完整代碼)

庖丁解牛&#xff1a;基于YOLO12與OpenCV的車輛部件級實例分割實戰&#xff08;附完整代碼&#xff09; 摘要&#xff1a; 告別“只見整車不見細節”&#xff01;本文將帶您深入實戰&#xff0c;利用YOLO12-seg訓練實例分割模型&#xff0c;結合OpenCV的強大圖像處理能力&…

ubuntu22.04配置遠程桌面

文章目錄前言檢查桌面類型xorg遠程桌面(xrdp)安裝xrdpxrdp添加到ssl-certwayland遠程桌面(gnome-remote-desktop)檢查安裝開啟開啟狀況檢查自動登錄奇技淫巧前言 在windows上使用遠程桌面服務&#xff0c;連接ubuntu主機的遠程桌面 檢查桌面類型 查看桌面類型、協議 echo $…

SQL Server 中子查詢、臨時表與 CTE 的選擇與對比

在 SQL Server 的實際開發過程中&#xff0c;我們常常需要將復雜的查詢邏輯分解為多個階段進行處理。實現這一目標的常見手段有 子查詢 (Subquery)、臨時表 (Temporary Table) 和 CTE (Common Table Expression)。這三者在語法、執行效率以及可維護性方面各有優勢與局限。如何選…

肖臻《區塊鏈技術與應用》第20-22講 - 以太坊難度調整、權益證明和智能合約

以太坊的“冰河時代”:詳解難度調整算法與“難度炸彈” 摘要: 為了實現遠快于比特幣的十幾秒出塊速度,以太坊必須設計一套更為靈敏和復雜的挖礦難度調整算法。本文基于北京大學肖臻老師的公開課內容,深入剖析了以太坊獨特的逐塊難度調整機制。文章首先解釋了其維持15秒平均…

C++中內存池(Memory Pool)詳解和完整示例

1. 什么是內存池&#xff1f; 內存池&#xff08;Memory Pool / Pool Allocator&#xff09; 是一種內存管理機制&#xff0c;提前向系統申請一大塊內存&#xff0c;再在這塊內存里切分、分配和回收。 它相當于在用戶空間建立了一層 “小型堆管理器”&#xff0c;避免頻繁調用系…

測試 Next.js 應用:工具與策略

1. 引言 Next.js 作為一個基于 React 的全棧框架&#xff0c;在構建復雜 Web 應用時&#xff0c;測試是確保代碼質量、功能穩定性和用戶體驗的關鍵步驟。測試可以分為單元測試、集成測試和端到端測試三種類型&#xff0c;每種類型針對不同的層面&#xff1a;單元測試驗證單個組…

IP 分片和組裝的具體過程

IP 分片和組裝的具體過程 在這里插入圖片描述 ? 16 位標識(id): 唯一的標識主機發送的報文. 如果 IP 報文在數據鏈路層被分片了, 那么每一個片里面的這個 id 都是相同的. ? 3 位標志字段: 第一位保留(保留的意思是現在不用, 但是還沒想好說不定以后要用到). 第二位置為 1 表示…

數據倉庫OLTPOLAP維度講解

?博客主頁&#xff1a; https://blog.csdn.net/m0_63815035?typeblog &#x1f497;《博客內容》&#xff1a;大數據、Java、測試開發、Python、Android、Go、Node、Android前端小程序等相關領域知識 &#x1f4e2;博客專欄&#xff1a; https://blog.csdn.net/m0_63815035/…