DJ 與 dual-Dirac 模型:TJ@BER 的業界標準工具
先備:serdes_clocking_connection(RJ/DJ/TJ 初登場、eye 與 BER)、lab_12(RJ-only bathtub)、lab_08(σt 從 phase noise 積分而來)| 接下來:exercises、lab_13
serdes_clocking_connection 已經給出速記式
「TJ = DJ +2Q⋅RJ」。這一頁把這個式子從頭嚴格建立起來:什麼是 RJ、什麼是 DJ、
Q 從哪個積分來、bathtub 曲線怎麼從 jitter 的 CDF(累積分布函數)推出來、
以及業界(Fibre Channel MJSQ 以降的 SerDes 規格)實際在用的 dual-Dirac(雙 Dirac)模型
——包含它最常被誤解、也最 重要的誠實聲明:模型參數 DJδδ 天生
小於等於實際的 peak-to-peak DJ,而且這個「低報」是故意的,正是它讓 TJ 外插準確。
物理直覺(先講結論):jitter 有兩種本質不同的成分。RJ(random jitter,隨機抖動)
是振盪器 phase noise 的時域化身——高斯、無上界,你等得越久(BER 目標越嚴)它就「長」得越大,
所以必須用 σ 乘上一個隨 BER 變大的倍數來記帳。DJ(deterministic jitter,確定性抖動)
由確定的物理機制驅動(碼間干擾、佔空比失真、電源漣波),幅度有物理上限,
用 peak-to-peak 記帳、不隨 BER 放大。dual-Dirac 模型就是把「任意形狀的有界 DJ」
壓縮成兩支 Dirac、把 RJ 保留為高斯,換取一條可以外插到 10−12 的直線。
量測 10−12 的 BER 要等 1012 個位元——10 Gb/s 也要 100 秒才「平均看到一次錯」,
要有統計信心得等小時級;外插不是偷懶,是工程必需。
第 1 步:RJ——無界高斯,從 phase noise 一路走來(本站鏈)
RJ 就是本站前六章建立的整條鏈的終點,逐步回顧(每步有專頁):
- device 白噪 → 1/f² phase noise:[P1] Eq.(21), p.185 給
L{Δω}=10log10(qmax2Γrms2⋅4Δω2in2/Δf)
(Γrms 無因次、qmax 單位 C、in2/Δf 單位 A²/Hz)。
詳見 white_noise_to_phase_noise。
- phase noise 積分 → rms jitter:σt=2πf01∫f1f2Sϕ(f)df
(單位 s;canonical 例 C:f0=5 GHz、L(1MHz)=−100 dBc/Hz、1/f²、積 1→100 MHz
→ σt=447.9 fs)。詳見 lab_08。
- 時域觀點——隨機漫步:[P2] Eq.(8), p.792 給累積相位 jitter
σΔϕ=κΔt(κ 單位 1/s,由 [P2]
Eq.(11)/(12), p.793 κ=qmaxΓrms21in2/Δf;
注意式中沒有 ω0——換成時間版要再除 ω0)。
- 為什麼是高斯:每個週期振盪器吃進大量彼此獨立的微小雜訊踢擊,總相位誤差是
獨立增量之和 → 中央極限定理 → 高斯。lab_11
用 Monte-Carlo 直接驗證了直方圖是高斯、σ∝ΔN。
RJ 的關鍵性質:無上界。 高斯的尾巴永遠不為零——不存在「保證不越界」的 margin,
只能問「越界機率多小」。這就是為什麼 RJ 必須用 σ 搭配目標 BER 記帳(第 3 步的 Q 函數)。
第 2 步:DJ——有界,由確定機制驅動
DJ 是 ISF 理論「看不見」的那一半(它不來自振盪器的隨機雜訊),但 SerDes 量到的 TJ 裡它常常最大。
三個主要來源,各有明確物理與明確上限:
| DJ 種類 | 物理機制 | PDF 形狀 | 為何有界 |
|---|
| ISI(inter-symbol interference,碼間干擾) | 通道頻寬有限、有記憶:edge 位置依賴前面的位元 pattern | 多支離散尖峰(每種 pattern 一支) | 通道脈衝響應長度有限 |
| DCD(duty-cycle distortion,佔空比失真) | 上升/下降緣不對稱、threshold 偏移:上升緣系統性偏早、下降緣偏晚 | 恰好兩支 Dirac | 不對稱量固定 |
| PJ/SJ(periodic/sinusoidal jitter;電源 spur、串擾) | 電源漣波經 supply pushing 調變 VCO(見 varactor_tuning_supply_pushing)、鄰近時脈耦合 | arcsine(雙角)分布 | 弦波幅度固定 |
注意 DCD 的 PDF 本來就是兩支 Dirac——dual-Dirac 模型對它是精確的;
模型的名字與形狀正是從這種「最壞情況形狀」來的。
弦波 DJ 的 PDF(arcsine 分布),逐步推導。 這是 lab_31 用的 DJ,也是電源 spur 的標準模型。
設 edge 的時間偏移 x=Asinθ,A 為幅度(單位 s),spur 與資料不同步,
所以取樣到的相位 θ 在 [0,2π) 均勻分布,pΘ(θ)=2π1(單位 1/rad)。
變數變換:一個週期內每個 x∈(−A,A) 對應兩個 θ 分支,每支貢獻
pΘ/∣dx/dθ∣,而 ∣dx/dθ∣=A∣cosθ∣=A2−x2:
pDJ(x)=2⋅2π1⋅A2−x21=πA2−x21,∣x∣<A
- 單位:1/[s2]=1/[s] ✓(PDF 對 x 積分無因次)。
- 歸一化檢查:∫−AAπA2−x2dx=π1[arcsinAx]−AA=π1(2π+2π)=1 ✓。
- 物理:弦波在轉折點附近停留最久 → 機率密度在 ±A 兩端發散(可積的「雙角」)。
lab_31 圖 (a) 的直方圖清楚可見這兩支角。
- 有界:DJpp=2A(peak-to-peak,單位 s)。適用條件:spur 與資料 asynchronous
(相位均勻);若 spur 與資料鎖定(synchronous),PDF 退化成離散尖峰,仍有界。
第 3 步:Q 函數——高斯尾巴積分,Q−1(10−12)=7.03 從哪來
RJ 的記帳工具是高斯尾巴機率。標準常態 X∼N(0,1)(無因次):
Q(x)≡P(X>x)=∫x∞2π1e−u2/2du
逐步化成 erfc(這樣才接得上 scipy 與本站 serdes_utils.Q)。代換 u=2s、du=2ds,
積分下限變 x/2:
Q(x)=2π2∫x/2∞e−s2ds=π1∫x/2∞e−s2ds=21erfc(2x)
最後一步用了定義 erfc(z)=π2∫z∞e−s2ds。
一般高斯(平均 μ、標準差 σ,單位皆 s)再代換一次 u=(v−μ)/σ 得
P(V>v)=Q(σv−μ)——Q 的引數永遠是「離平均幾個 σ」,無因次 ✓。
深尾漸近式(分部積分一次):
Q(x)≈x2πe−x2/2(x≫1, 相對誤差約 1/x2)
用它口算 Q(7.03):指數 7.0342/2=24.7、e−24.7≈1.8×10−11、
除以 7.03×2.507≈17.6 → ≈1.0×10−12 ✓。這就是全站 jitter 章一直在用的
「BER 10−12 ↔ 7.03σ」對照(與 06 exercises 的 Q 表一致):
| 目標 BER | Q−1(BER) | RJ peak-to-peak =2Q−1σ |
|---|
| 10−9 | 5.998 | 12.0σ |
| 10−12 | 7.034(本站記 7.03) | 14.07σ |
| 10−15 | 7.941(本站記 7.94) | 15.88σ |
一行 Python 驗證(引用本站真實 API;Q−1 用 erfcinv 反解上面的尾巴積分):
import numpy as np
from scipy.special import erfcinv
from simulations.common.serdes_utils import Q
q = np.sqrt(2) * erfcinv(2 * 1e-12)
print("Qinv(1e-12) =", round(float(q), 3))
print("Q(7.034) =", float(Q(7.034)))
第 4 步:dual-Dirac 模型——定義與 PDF
模型做兩件事(外部文獻,非本站 5 篇 PDF;方法論出處見頁尾):
- TJ 的 PDF 是 DJ 的 PDF 與高斯 RJ 的卷積(RJ 與 DJ 統計獨立):
pTJ=pDJ∗gσ,其中 gσ(x)=σ2π1e−x2/2σ2(單位 1/s)。
- 把任意形狀的有界 pDJ 壓縮成兩支等權 Dirac,間距記作 DJδδ:
pDJ(x) ⟶ 21δ(x−μR)+21δ(x−μL),DJδδ≡μR−μL
卷積用 Dirac 的取樣性質 ∫δ(v−μ)gσ(x−v)dv=gσ(x−μ),一步得模型 PDF:
pδδ(x)=21gσ(x−μR)+21gσ(x−μL)
——兩顆同 σ 的高斯,各佔一半機率。對稱情形(本頁與 lab_31)μR=−μL=μ=DJδδ/2。
尾巴(tail)函數,逐步積分。 定義 T(x)≡P(jitter>x)=1−F(x)(F 為 CDF)。
對模型 PDF 逐項用第 3 步的結果 ∫x∞gσ(v−μ)dv=Q(σx−μ):
Tδδ(x)=21Q(σx−μR)+21Q(σx−μL)
深尾只剩一項。 兩項之比(用漸近式,對稱情形):
Q(σx−μ)Q(σx+μ)≈exp(−2σ2(x+μ)2−(x−μ)2)=exp(−σ22μx)=exp(−σ2DJδδx)
以 lab_31 的數字(DJδδ=3.16 ps、σ=1.03 ps、關心的 x≈8.6 ps)
這個比值 ≈e−25.6≈8×10−12——完全可忽略。所以深尾就是單顆權重 ½ 的高斯:
Tδδ(x)≈21Q(σx−μ)(x 在右深尾)
Q-scale 直線——萃取 (DJδδ,σ) 的原理。 把上式反解:
Q−1(2T(x))=σx−μ
——在「Q-scale」上(縱軸畫 Q−1(2T)、橫軸 x),深尾是一條直線:斜率 1/σ、
橫軸截距 μ=DJδδ/2。儀器(BERT scan 或示波器的 TIE 直方圖)就是對量到的
尾巴做這條直線擬合。注意 Q−1 裡的 factor 2:它記帳的是「每支 Dirac 只佔一半機率」
——這是本頁第一個要盯住的 factor-of-2(第 7 步還有兩個)。
第 5 步:bathtub 曲線——從 jitter CDF 逐步導出
設 NRZ 資料、UI(unit interval)=Tb(單位 s)。eye 中心為時間原點,取樣時刻 offset 為 t;
左 data edge 名目在 −UI/2、右 edge 在 +UI/2,各自帶 jitter x(同分布,尾巴 T、CDF F)。
- 錯誤事件一(左 edge 遲到):左 edge 實際落在 −UI/2+x;若它晚於取樣時刻,
即 −UI/2+x>t⇔x>UI/2+t,取樣器讀到前一個位元。機率 =T(UI/2+t)。
- 錯誤事件二(右 edge 早到):右 edge 實際落在 +UI/2+x;若它早於取樣時刻,
即 UI/2+x<t⇔x<−(UI/2−t),機率 =F(−(UI/2−t)),
對稱分布下 =T(UI/2−t)。
- 只有「有跳變」才會錯:隨機資料相鄰位元不同的機率是 21(transition density
ρT=21)。兩事件都是稀有事件,聯集機率 ≈ 相加(交集是二階小量):
BER(t)=21[T(2UI−t)+T(2UI+t)]
一致性檢查:純 RJ 時 T(x)=Q(x/σt),上式退化成
BER(t)=21[Q(σtUI/2−t)+Q(σtUI/2+t)]
——正是 lab_12 與 serdes_utils.ber_bathtub
的公式 ✓。bathtub 的兩面「壁」就是 jitter CDF 的左右尾巴,只是橫軸從「jitter 大小」
換成「取樣位置」重畫。DJ 的效果一目了然:它把整條尾巴平移 ≈μ → 兩壁往內推;
RJ 決定壁的斜率(在 log-BER 座標,斜率由 σ 定)。
- Dimension check:T 的引數 [s]、輸出是機率(無因次);BER 無因次 ✓。
- 適用:稀有事件(BER≪1)、edge jitter 平穩且與資料獨立(ISI 嚴格說與資料相關,
見第 8 步失效條件)。
第 6 步:TJ(BER) 外插公式——推導與 factor 稽核
推導。 目標:在指定 BER 下,eye 被 jitter「吃掉」多寬。右壁位置 xR 定義為右深尾的
主導高斯掉到目標 BER 的位置(業界慣例直接用 per-Gaussian 尾巴 = BER 記帳,稽核見下):
Q(σxR−μ)=BER ⟹ xR=μ+σQ−1(BER)
對稱地左壁 xL=−μ−σQ−1(BER)。total jitter 定義為兩壁吃掉的總寬:
TJ(BER)=xR−xL=DJδδ+2Q−1(BER)σ
BER =10−12 時 TJ=DJδδ+14.07σ。eye 水平開度
=UI−TJ(BER)。
- Dimension check:[s]+[無因次]×[s]=[s] ✓。
- 物理意義:DJ 部分不隨 BER 變(有界、一次吃掉);RJ 部分隨 BER 變嚴而以
Q−1 緩慢長大(10−12→10−15 只從 14.07σ 到 15.88σ——高斯尾巴的
對數增長)。
Factor-of-2 稽核(本站慣例:把每個 2 講清楚)。上式用 Q−1(BER)=7.034,
隱含「每顆高斯的尾巴 = BER」。嚴格照第 4、5 步的記帳還有兩個 ½:
Dirac 權重 ½(per-side 尾巴 T=21Q)與 transition density ρT=21(bathtub 再乘 ½)。
全部算進去,壁的位置由 Q=4×BER 決定:
| 慣例 | 壁條件 | 倍數(BER =10−12) | lab_31 實得 TJ |
|---|
| per-Gaussian(業界公式) | Q=BER | 7.034 | 17.65 ps |
| per-side 尾巴 T=BER | Q=2BER | 6.937 | 17.43 ps |
| bathtub(ρT=21,本站 lab_12 慣例) | Q=4BER | 6.839 | 17.23 ps |
三者相差 Q−1(10−12)−Q−1(4×10−12)=0.196σ/側——本例共 0.40 ps、
約 TJ 的 2%,業界公式偏保守。實務上這不構成問題,因為 (DJδδ,σ)
是用同一套慣例從尾巴擬合出來再代回去外插的——慣例一致時誤差幾乎對消;
但比較不同儀器的 DJ/RJ 報告時,必須先問它用哪個慣例。(lab_31 把三個數字都印出來。)
第 7 步:誠實聲明——DJδδ≤DJpp,而且低報是故意的
這是 dual-Dirac 最常被誤解的一點:DJδδ 是模型參數,不是實際的
peak-to-peak DJ。lab_31 的數字:真實弦波 DJ 的 DJpp=4.0 ps,擬合出的
DJδδ=3.16 ps。
為什麼一定偏小(推導)。 總 jitter 尾巴是 DJ 分布對高斯尾巴的平均
(把卷積的積分順序交換一次即得):
T(x)=P(u+n>x)=∫−AApDJ(u)Q(σx−u)du
因為 u≤A 且 Q 嚴格遞減,被積函數逐點滿足 Q(σx−u)≤Q(σx−A)。
把積分拆成右半(u>0,總質量 ½)與左半(u≤0,深尾時貢獻再小 e−Ax/σ2 倍):
T(x) ≤ 21Q(σx−A)+指數小21Q(σx)
等號只在右半質量全部集中在 u=A(即 DCD 那種兩點分布)時成立。翻到 Q-scale:
Q−1(2T(x)) ≥ σx−A——真實尾巴曲線永遠在「Dirac 放在真極值 A」
那條線的上方(lab_31 圖 (b) 的藍線 vs 灰虛線)。對真實曲線做直線擬合,截距必然
μ≤A,即:
DJδδ=2μ ≤ 2A=DJpp
為什麼低報反而讓 TJ 準。 外插要準,需要的是「在目標 BER 那幾個 decade,直線貼住
真實的尾巴高度」——擬合正是這樣錨定的(lab_31:dual-Dirac 外插的 eye opening
82.76 ps vs 精確複合的 82.77 ps,差 0.01 ps)。反過來,若把 Dirac 硬放在真極值
±A(把 DJpp=4.0 ps 當 DJδδ 用),光 DJ 項就多報
4.0−3.16=0.84 ps:代入公式(真 σ=1.0 ps)得 TJ=4.0+14.07×1.0=18.07 ps,
比精確 bathtub 的 17.23 ps 悲觀 0.84 ps——白白丟掉 margin。
直覺:DJ 分布靠近極值處只有有限的機率質量(弦波雖有雙角、仍是可積奇點),
深尾實際上是「打了折的高斯」,等效中心自然縮進來。
代價(也要誠實說):
- DJδδ 依賴擬合深度。lab_31 掃三個擬合窗:
T∈[10−8,10−4]→3.07 ps、[10−10,10−6]→3.16 ps、
[10−14,10−10]→3.27 ps——越深越靠近(但不超過)DJpp。
報告 DJ/RJ 分解時應註明擬合窗;規格文件(MJSQ 系)對此有明確方法論。
- DJ 會「漏」進 σ:擬合出 σ=1.03 ps,比真實 RJ 的 1.00 ps 略大——
DJ 尾巴殘餘的曲率被直線吸收成斜率的一部分。所以別把儀器報的 RJ 直接當
振盪器 phase noise 的積分值去對帳(差幾 % 屬正常); 對帳要用乾淨時脈 pattern 隔離 DJ。
第 8 步:lab_31 數值驗證
完整 script:simulations/lab_31_dual_dirac.py(相依:simulations/common/serdes_utils.py
的 Q、simulations/common/plot_utils.py 的 savefig;執行 python scripts/run_all_sims.py
會一併重跑)。合成 RJ(σ=1 ps 高斯)+ 弦波 DJ(A=2 ps → DJpp=4 ps)
於 UI=100 ps(10 Gb/s,同 lab_12)。尾巴 T(x) 用「對弦波相位取平均」半解析算到
10−15 深度(無 Monte-Carlo 雜訊),擬合按第 4 步的 Q-scale 直線。
| 參數 | 變數 | 值 | 單位 | 說明 |
|---|
| RJ rms | sigma_rj | 1×10−12 | s | 高斯、無界(教學上放大;canonical 例 C 的時脈是 447.9 fs) |
| DJ 幅度 | a_dj | 2×10−12 | s | 弦波(電源 spur 型),DJpp=2A=4 ps |
| 單位間隔 | ui | 100×10−12 | s | 10 Gb/s NRZ |
| 目標 BER | ber_target | 10−12 | — | 常見 SerDes 規格 |
| 擬合窗 | t_deep, t_shallow | [10−10,10−6] | —(尾巴機率) | Q-scale 直線擬合區 |
| MC 樣本數 | n_mc | 2×106 | — | 只用於直方圖 |
執行輸出(節錄,# -> 為可驗證標記):
extracted DJ_dd = 3.16 ps # -> 3.16 (< DJ_pp = 4.0)
extracted sigma = 1.03 ps # -> 1.03 (true RJ rms 1.0)
TJ@1e-12 (formula) = 17.65 ps # -> 17.65
TJ@1e-12 (bathtub) = 17.23 ps # -> 17.23
eye opening @1e-12: composite 82.77 ps vs dual-Dirac 82.76 ps

怎麼讀這張圖:
- (a) PDF:藍色(真實)有 arcsine 雙角被高斯抹圓;紅虛線(dual-Dirac)在中段明顯
不貼——模型從不宣稱 PDF 貼合,它只對深尾負責。紅點虛線(Dirac 位置 ±μ=±1.58 ps)
在灰點虛線(真極值 ±2 ps)內側:這就是 DJδδ<DJpp。
- (b) Q-scale:深尾區藍線筆直 → 高斯主導;紅虛線是擬合直線(斜率 1/σ、截距 μ);
灰點線是「Dirac 硬放 ±A」的悲觀預測,落在真實曲線下方(同一 x 給更大的尾巴機率)。
- (c) bathtub:藍(精確)與紅虛(dual-Dirac 外插)在 10−12 幾乎重合(開口差 0.01 ps)
—— 模型的本職;綠點線(RJ-only、無 DJ)開口寬得多:DJ 平移壁、RJ 定斜率。
互動:親手擬合一次。 下面的小工具讓你直接操控 RJ σ 與弦波 DJ 幅度 A(合成母體,
seeded PRNG,N=20,000),並在兩個 BER decade 擬合窗(淺:[10−3,10−6];深:
[10−6,10−9])之間切換,即時看到 DJδδ、σfit、
兩者的差 Δ=DJpp−DJδδ,以及 TJ@10−12
外插值如何隨擬合深度移動——這正是第 7 步「擬合越深、DJδδ
越逼近但不超過 DJpp」的量化版本,換成你自己選的 σ,A 也成立。
Dual-Dirac Q-scale 擬合器 — 萃取 DJ_δδ 與 σ_fit,比較擬合深度
1.00 ps
2.0 ps
(a) TJ 直方圖(N=20,000,seeded)— 雙角+高斯抹圓
(b) Q-scale bathtub 尾巴 — 用下方按鈕拖動擬合區
― 淺擬合區(橘)― 深擬合區(藍)― 真實尾巴(半解析、精確—— 與 lab_31 同法;粗線=目前選取的擬合深度)。
σ_fit / σ_true
1.03 / 1.00
ps
淺([10⁻³, 10⁻⁶]):DJ_δδ = 2.99 ps、σ_fit = 1.05 ps、TJ@10⁻¹² = 17.74 ps。 深([10⁻⁶, 10⁻⁹]):DJ_δδ = 3.15 ps、σ_fit = 1.03 ps、TJ@10⁻¹² = 17.65 ps。 教訓:DJ_δδ 恆小於 DJ_pp,且擬合越深,DJ_δδ 越逼近(但不超過)DJ_pp——因為深尾巴主要由弦波的轉折點主導, 那裡才是 DJ 機率質量真正集中的地方。
模型:RJ ~ N(0, σ²) ⊛ 弦波 DJ = A·sin(θ),θ ~ U[0, 2π)(arcsine「雙角」分布;見本頁第 2 步)。 直方圖/CDF 面板用 N = 20,000 筆 seeded 樣本(mulberry32)純示意;擬合本身用半解析尾巴 T(x) = ⟨Q((x−A sinθ)/σ)⟩_θ(與 simulations/lab_31_dual_dirac.py 同法),因為這麼深的 BER 窗口 任何有限樣本都無法誠實估計。Q(x) 用 Numerical Recipes 的 erfc 近似;Q⁻¹ 用 Acklam 對反常態 CDF 的有理函數近似。 Pedagogical toy model——真實鏈路是 ISI+DCD+PJ 疊加、且 ISI 與資料相關(見本頁第 8 步/適用條件表)。
一行式驗證(引用 lab_31 的真實函式;跑一次約數秒):
from simulations.lab_31_dual_dirac import fit_dual_dirac, q_inv
dj_dd, sigma_fit, _ = fit_dual_dirac(a_dj=2e-12, sigma_rj=1e-12)
print("DJ_dd =", round(dj_dd * 1e12, 2), "ps")
print("sigma =", round(sigma_fit * 1e12, 2), "ps")
tj = dj_dd + 2 * q_inv(1e-12) * sigma_fit
print("TJ@1e-12 =", round(float(tj) * 1e12, 2), "ps")
這是 pedagogical 模型(非 transistor-level):DJ 只取單一弦波、RJ 取白噪積分後的
等效高斯;真實鏈路的 DJ 是 ISI+DCD+PJ 的疊加、且 ISI 與資料 pattern 相關。
Worked examples 數值例題
例 1(TJ 預算:canonical 時脈 + 給定 DJ)
10 Gb/s(UI=100 ps)。時脈 RJ 用 canonical 例 C:σt=447.9 fs
(f0=5 GHz、L(1MHz)=−100 dBc/Hz、1/f²、積 1→100 MHz)。
鏈路量得 DJδδ=3 ps。求 BER =10−12 的 TJ 與 eye 開度。
逐步代入(帶單位):
TJeye 開度=DJδδ+2Q−1(10−12)σt=3 ps+14.07×0.4479 ps=3 ps+6.30 ps=9.30 ps,=UI−TJ=100−9.30=90.7 ps=0.907 UI.
RJ 項 6.30 ps 與 serdes_clocking_connection
第 4 步「448 fs → RJ 吃掉 6.3 ps」一致 ✓。Dimension check:[s]+[−]×[s]=[s] ✓。
sigma_t = 447.9e-15; dj_dd = 3e-12; ui = 100e-12
tj = dj_dd + 14.07 * sigma_t
print("TJ@1e-12 =", round(tj * 1e12, 2), "ps")
print("eye opening =", round((ui - tj) * 1e12, 1), "ps")