JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

可控制性與可觀測性:可測試性的核心

在第 1 階你學到,一次製造測試必須去搖動一個節點、再看它如何反應。但一顆晶片只有幾百根接腳、卻有數千萬個內部節點——其中絕大多數都深埋在你碰不到的地方。本篇為決定「任何單一節點到底能不能被測試」的兩個性質命名:[[ic-controllability-observability|可控制性]](你能不能從晶片的輸入把它逼到 0 和 1?)與**可觀測性**(你能不能在某個輸出看到它的值?)。只要兩者之一失效,故障就會躲起來——而我們將看到[[register|暫存器]]與迴授如何讓問題急遽惡化,從而帶出「掃描」這帖解藥。

搆到一個你摸不到的節點

想像一座龐大的工廠,數千台機器肩並肩擠在一起,而你是檢查員。只有一個問題:進入這棟建築的唯一通道,是外牆上寥寥幾扇門;而唯一的窗戶,也只從同一面牆向外看。位於廠房正中央的某台機器也許壞了,但你既無法餵給它那些會讓它出錯的零件,也看不到它吐出的瑕疵品——後面每一台機器都把那個輸出吞下去,再變成別的東西。那座工廠就是一顆晶片。門與窗就是它的接腳(pin)。而正中央那台機器,就是一個你必須隔著層層堆疊去測試的邏輯閘。

這是製造測試的核心張力,而它正是第 1 階的直接延伸。要為一個節點測試缺陷,你必須做兩件事:把它設定成一個已知的值,再檢查它是否真的取到了那個值。這兩個動作都只能在接腳上發生,因為接腳是測試機台與晶粒之間唯一的電氣接點。一顆最先進的 SoC 可能有一千萬個邏輯閘,卻只有幾百根功能接腳——所以平均而言,數十萬個節點得共用每一道通往晶片內部的門。「這個設計有多可測試?」這個問題,其實可以拆成對每一個節點分別提出的兩個更尖銳的問題。

可控制性:從邊緣強加一個值

可控制性是問題的*輸入*那一半。一個深埋在組合邏輯裡的節點,並不是一條你可以夾上探針的線——它的值是餵給它的那些閘所計算出來的,而那又取決於餵給*那些閘*的閘,如此一路回溯到接腳。要把一個埋藏的節點設成 1,你必須找出一組接腳值,使它在漣漪般穿過每一個中間的閘之後,恰好在那裡留下一個 1。有時這很容易。有時邏輯卻和你作對,沒有任何接腳樣式能產生你需要的值。

工程師用一個粗略的可控制性分數來量化這件事——非正式地說,就是要把每個值合理地推導出來所需的接腳指派數(或難度)。經典的 SCOAP 量度從輸入往前走過電路,給每個主要輸入一個基準成本 1(你直接控制它),然後逐閘累積成本。邏輯的圓錐越深、越窄,分數就越高,節點也就越難驅動。一個 1-可控制性極高、而 0 卻很便宜的節點是個警訊:你能輕易把它打到低,卻幾乎永遠抬不起來,於是它一半的故障永遠激發不出來。

  Primary inputs            buried node n         output
  ----------------          -------------         ------
  a ---|\                                                
       | & )---x---|\                                     
  b ---|/         | & )---n---|\                          
  c -------|\     |          | & )---+--- ... deeper ---  y
           | & )--/   d -----|/      |  (8 more gates)    
  d -------|/                        |                    
                                                          
  To set n = 1 you need  x = 1  AND  d = 1
     -> x = 1  needs  a = 1 AND b = 1   (the upper AND)
     -> d = 1  directly
  So n = 1  requires  a=1, b=1, d=1  ............  doable

  To set n = 0 you only need x = 0 OR d = 0 ......  many ways, easy
     -> n's 1-controllability is HARD, 0 is EASY  (asymmetric!)
一串 AND 閘讓「產生 1」變得昂貴:圓錐裡的每一個輸入都必須配合。而「產生 0」很便宜——任何地方出現任何一個 0 就夠了。這種不對稱,正是 ATPG 工具會標示為低可控制性節點的東西。

可觀測性:看著答案傳回來

就算你勝利地把一個埋藏的節點逼到你想要的值,除非你能*看到結果*,否則你什麼有用的事都還沒做。可觀測性是*輸出*那一半:一個節點的影響,必須往前穿過每一個下游的閘,並以可辨認的形式抵達一根你量得到的接腳。這裡的敵人,是會遮蔽(mask)節點的邏輯——它把節點的值吞掉,無論節點是對是錯都產生相同的輸出。一個你無法觀測的故障節點,和一個你無法控制的節點一樣徹底隱形。

讓一個節點變得可觀測的訣竅是敏化(sensitisation):你把路徑上每一個閘的*其他*輸入都設好,使得這條路徑變成一根暢通的管子——翻轉待測節點,就會翻轉最終輸出。對一個 AND 閘來說,那意味著把它其他的輸入維持在 1(讓它原封不動地讓節點通過);對 OR 閘則是把其他輸入維持在 0。注意這殘酷的轉折:那些旁路輸入本身也是必須被*控制*的埋藏節點。觀測一個節點,逼著你去控制一整組支援的配角,而節點越深,那組配角就越長。

  Sensitising a path so node n is OBSERVABLE at output y:

            n ----|\
                  | & )---p---|\
   side1 = 1 ----|/          | & )--- y
                  side2 = 1 -|/

  AND #1: hold side1 = 1  ->  p = n   (passes n through)
  AND #2: hold side2 = 1  ->  y = p = n

  Now:  n = 0  gives  y = 0
        n = 1  gives  y = 1     <-- y is a perfect mirror of n
  The path is SENSITISED: any fault flipping n is visible at y.

  But if side1 = 0 instead:  p = 0 always  ->  y is stuck,
  n is completely MASKED and its fault is unobservable.
要觀測 n,通往 y 的路徑上每一個閘都必須被設成讓它通過(AND 的旁路輸入 = 1,OR 的旁路輸入 = 0)。路徑上任何一處出現一個會遮蔽的旁路輸入,就會打斷整條鏈、把故障藏起來——這正是為什麼「觀測」其實是一個喬裝過的可控制性問題。

一個工作範例:那個躲起來的故障

讓我們用一個「已經能展現這個陷阱的最小電路」把它講具體。我們有一小塊組合邏輯:兩個 AND 閘餵給第三個,外加一個我們懷疑可能卡住的、深埋的內部節點 n。我們想測試 n 能不能被驅動到 1、以及那個 1 能不能抵達輸出。看看「控制 n」與「觀測 n」的要求是如何開始互相打架的。

  a --|\
      | & )--- g1 --|\
  b --|/            | & )--- n --|\
  c --|\           |            | & )--- y
      | & )--- g2 -|             |
  d --|/            e ----------|/

  GOAL: test node n for a 'stuck-at-0' fault.
  Step 1 - CONTROL n to 1 (to excite a stuck-at-0):
      n = g1 AND g2,  so need  g1 = 1 AND g2 = 1
      g1 = 1  ->  a = 1, b = 1
      g2 = 1  ->  c = 1, d = 1
      => inputs a=b=c=d=1 force n = 1.            (good)

  Step 2 - OBSERVE n at y through the last AND:
      y = n AND e,  so to pass n through we need  e = 1.
      With e = 1:  fault-free  y = n = 1
                   if n stuck-at-0  y = 0   <-- DIFFERENT, detected!

  Required test pattern:  a=b=c=d=e = 1, expect y = 1.
  If silicon returns y = 0, node n is stuck-at-0.
這裡諸事順遂:單一個樣式(所有輸入 = 1)同時把 n 驅動到 1、又敏化了通往 y 的路徑,所以那個固定為 0 的故障是可偵測的。在十一個閘那麼深的地方,這種好運很少自然發生——這正是 ATPG 工具一個樣式接著一個樣式去搜尋的東西。

現在改動一條線,畫面就暗了下來。假設節點 e 不是一個自由的主要輸入,而是它自己被算成 e = NOT(a)。那麼,正是那個控制 n 的樣式(a = 1)逼得 e = 0——這就遮蔽了最後那個 AND 閘,把 y 釘死在 0、無論 n 是什麼。控制 n 與觀測 n 現在要求 a 取*相反*的值。沒有任何單一樣式能同時滿足兩者,於是 n 上那個固定為 0 的故障,就以功能的手段變得不可測試:它可以就那樣帶著缺陷待在那裡,混在看起來會動的矽晶圓裡出貨。這不是一個牽強的恐怖故事;它是邏輯變得再收斂、變深時自然會發生的事。

為什麼循序邏輯讓情況急遽惡化

到目前為止的一切,都假設是純組合邏輯,其中節點的值只取決於*當前*的接腳。真實的晶片裡滿是循序邏輯——記得過去的正反器暫存器。一個正反器的輸出不是今天輸入的函數;它是某個更早的週期裡被時脈打進去的東西。要控制一個埋藏暫存器的資料輸入,你不能只是設定接腳——你必須驅動接腳、打一拍時脈、再驅動一次、再打一拍,帶著這部機器走過一連串的*狀態序列*,直到它終於抵達你想要的地方。可控制性不再是「找一個樣式」,而變成了「找一條穿越時間的路徑」。

可觀測性承受的是鏡像般的詛咒。翻轉一個埋藏節點的效應,可能得被時脈打進一個暫存器、保持住、在下一個週期傳播到下一個暫存器,再過好幾個週期之後才終於出現在某個輸出上。要偵測一個故障,你必須控制一段*跨多個週期的輸入序列*,再觀測一段*跨多個週期的輸出序列*——而測試產生器必須對晶片隨時間的行為進行推理,而不是在單一快照裡。它必須搜尋的狀態空間爆炸式膨脹:一個有 k 個正反器的設計,最多有 2^k 個狀態,而其中許多可能根本到不了、或只能透過漫長而脆弱的序列才到得了。

  Combinational test of one fault:
      apply 1 input pattern  ->  read 1 output   (one cycle)

  Sequential test of one fault buried behind 3 registers:
      cycle 0:  set pins, pulse clk   (load reg A)
      cycle 1:  set pins, pulse clk   (reg A -> reg B, set up reg C)
      cycle 2:  set pins, pulse clk   (excite the fault into reg C)
      cycle 3:  set pins, pulse clk   (propagate toward output)
      cycle 4:  read output           (fault finally visible?)

  One fault -> a 5-cycle JUSTIFY + PROPAGATE sequence.
  Millions of faults x long sequences x 2^k reachable states
      = ATPG run-time and fault coverage fall off a cliff.
一個本來只需一個組合樣式的故障,現在需要一段被仔細排序的跨週期序列——而工具必須為每一個故障都找出一段。隨著暫存器的深度增加,循序 ATPG 的執行時間與可達成的覆蓋率雙雙崩潰。這就是促使「掃描」誕生的那道牆。

而迴授又把螺絲再擰緊一圈。一部有限狀態機把它暫存器的輸出迴授進那些決定它們下一個值的邏輯裡。現在,一個你想控制的節點,取決於一個其值又取決於那個節點的暫存器——一個時間裡的迴圈。要抵達一個目標狀態,你也許需要一段精確的、長達數十個週期的序列;而某些狀態也許只能從一次開機重置抵達,而你每一次都得重播那次重置。更糟的是,一個藏在緊密迴授迴圈裡的節點,可能幾乎同時不可控制且不可觀測:你不擾動迴圈就設不了它,你不讓迴圈吞掉證據就看不了它。這類邏輯的功能測試覆蓋率,動不動就崩到任何產品都不能拿來出貨的水準之下。