【今週の関心記事】2018/9/8

news.mynavi.jp

僕自身がiPhoneをやめてファーウェイに乗り換えた口なので、安くて良いものを作ると感じます。
最初はローエンドの中華スマホの代表格でしたが、すっかり規模が大きくなり、APUも自前するレベルにまで到達。
さらには世界初の先端技術の開発も出来るようになってしまったか。
日本メーカーは完全に負けた。
けど僕は廃墟の中からこそ良いモノは生まれてくると思ってますよ。

wired.jp

これも同じくファーウェイ関連。
オランダでは締め出しを食らっているそうだ。
日本もセキュリティ意識は高めるべきなんじゃなかろうか。
安心して使えないものは販売停止にすべき。
この手の「中国製、危ないんじゃない?」的な話は、中国や韓国に変な気を使って表沙汰にされないような、そんな空気を日本では感じる。

www.businessinsider.jp

僕は完全に別意見。
もっと人材は流動化すべきだと思う。
自分が最も力を発揮できる場所を探しましょう。
また、組織としても人材の入れ替わりのない組織は、空気が淀んでしまいます。
大きな会社なら人事異動という形が良いのだが、そう都合よく人事は仕事してくれませんからね。

【今週の関心記事】2018/9/1

gigazine.net

GFが7nmの先端プロセスから脱落。
半導体ロジックのファウンダリは、TSMCSamsungの2社に絞られた。
あ、一応やる気あるか微妙だが、intelもか。

GF は設立した当初から他社に勝てるところの少ないところだった。
当初のまま差別化することもなく負けていった印象。

14nmと12nmで勝負していくということだが、差別化が微細化しかない領域だったので、どういう戦い方が出来るのか疑問。
トランプの保守政策の後押しで有利な立場にはあるのに肝心の技術が追いついてない。

news.biglobe.ne.jp

ルネサスがまたアメリカの半導体会社を買収。
IDTというあんまり有名でもない会社。
特許で稀に名前を見たことがある程度。

額が6000億円というから驚き。
IDTの2017の売り上げは800億円弱、営業利益は200億円弱。
2016からの売り上げからは微減。
営業利益率は高いが、6000億の価値はあるのかな。

主力は高速デジタルインターフェース関連製品。
SerdesもDRAMもさらに光通信まで、手広くやっており、製品のラインナップを見る限り、先端までキャッチアップされており、培ってきたものはかなりのレベル。
ルネサスに使いこなせるのか?

【今週の関心記事】2018/8/25

akiba-pc.watch.impress.co.jp

Phison製コントローラICを使用したM.2ドライブ。
PCIeカードとしても使用可能なところが特徴的。

ICはデータの圧縮機能までコントローラで担っている。
しかもICベンダの独自仕様。
単なるバッファや規格変換だけでなく、そういうところに付加価値をつけてるんですね。

ascii.jp

M.2ドライブをUSB外付けドライブに変換するケース。
USB3.1 Gen2の10Gbpsを活用して書き込み読み込みともに非常に高速。

ICはJMicron製のPCIe Gen3 x2-USB3.1 Gen2変換ICを使用。
この手のブリッジICは規格が立ち上がる度に登場するが、付加価値があんまりない。
しかも、高速IFはRevision更新が2-3年単位とめちゃくちゃ早いので、陳腐化も早い。
このICもこの用途しか使い道がないのではないかと思うと、短命で終わりそうですね。

【Serdes】Dual Dirac MethodをPythonで実装

Dual Dirac MethodをPythonで実装してみた。

Dual Dirac Methodの技術参考資料 (Keysight)
https://www.keysight.com/upload/cmc_upload/All/dualdirac1.pdf

1. Jitter Dataの準備

解析するモチーフをまず定義する。
Data Rate: 10Gbps (1UI=100psec)
Rj: 1ps RMS
Dj: 14ps PP (±7ps)のSj
Sample Size: 1MUI

Jitter Dataのデータは、各行に各UI毎のJitter値として、text file dataを作成。
RjとDjそれぞれのデータを作成してから、それらの和を取ることでTjのデータを作成することにした。

1.1 Rjの生成プログラム

乱数でRjデータを発生させ、rj.csvに保存。

import numpy as np
import csv

#Sample size
intSize = 1000000

#Jitter RMS = 1ps
fltJitterRms = 1e-12

#Generate random pattern
arrData = np.random.normal(0, fltJitterRms, intSize)

#Output Data
arrWriteData = []
for i,d in enumerate(arrData):
        arrWriteData.append([])
        arrWriteData[i].append(d)

with open('rj.csv', 'w') as f:
        wr = csv.writer(f)
        wr.writerows(arrWriteData)

1.2 Dj(Sj)の生成プログラム

14ps-pp, 周波数100MHzの正弦波でSjを発生し、sj.csvに保存。

import numpy as np
import csv

#Sample size 
intSize = 1000000
#Time step : 1UI = 100ps
fltStepTime = 100e-12

#Noise frequency = 101MHz
fltNoiseFreq = 101e6
#Noise Amp = 14ps-pp
fltNoiseAmp = 14e-12 / 2

#Generate sin pattern
arrTime = np.arange(0, intSize*fltStepTime, fltStepTime)
arrData = []
for t in arrTime:
	d = fltNoiseAmp*np.sin(2*np.pi*fltNoiseFreq*t)
	arrData.append(d)

#Output Data
arrWriteData = []
for i,d in enumerate(arrData):
	arrWriteData.append([])
	arrWriteData[i].append(d)

with open('sj.csv', 'w') as f:
	wr = csv.writer(f)
	wr.writerows(arrWriteData)

1.3 RjとDjの合成

rj.csv, sj.csvをコマンド因数で受け取り、2つのジッタの和を取り、rjsj.csvに保存。

import numpy as np
import csv 
import sys

args = sys.argv
path = []
path.append(args[1])
path.append(args[2])

arrData = []

#Read path[0] data
with open(path[0], 'r') as f:
	rr = csv.reader(f)
	for rd in rr:
		arrData.append(float(rd[0]))

#Add path[1] data
with open(path[1], 'r') as f:
	rr = csv.reader(f)
	for i,rd in enumerate(rr):
		arrData[i] += float(rd[0])

#Output data
arrWriteData = []
for i,d in enumerate(arrData):
	arrWriteData.append([])
	arrWriteData[i].append(d)

with open('rjsj.csv', 'w') as f:
	wr = csv.writer(f)
	wr.writerows(arrWriteData)

1.4 生成したジッタデータの確認

結果確認用にヒストグラムプロットのプログラムも作った。

import numpy as np
import csv
import sys
import matplotlib.pyplot as plt

args = sys.argv
path = args[1]
arrData = []

#Read data file
with open(path, 'r') as f:
        rr = csv.reader(f)
        for rd in rr:
                arrData.append(float(rd[0]))

#Plot Histgram
plt.figure()
plt.hist(arrData, bins=100, normed=True)
plt.show()

1.1で作ったrj.csvヒストグラム。ちゃんと正規分布が得られている。

f:id:kent_s:20180817140053p:plain
rj.csv

1.2で作ったsj.csvヒストグラム。正弦波による特徴的なジッタ分布が得られてる。

f:id:kent_s:20180817140241p:plain
sj.csv

1.3で作ったrjsj.csvの分布。正弦波に正規分布が重畳されているのが分かる。

f:id:kent_s:20180817140407p:plain
rjsj.csv

2. Dual Dirac Methodの実装

2.1 BERプロットの作成

1.3で作ったrjsj.csvを使ってBERプロットを作成。
1UIを1000等分にスライスし、ジッタがx番目の各スライスに含まれる確率をJ(x)と定義。
次にJ(x)の積分により、BER(x)を求めています。
出力はber.csvへのファイル出力です。

import numpy as np
import csv 
import sys
import matplotlib.pyplot as plt

fltUi = 100e-12
intRange = 1000

args = sys.argv
path = args[1]
arrJx = np.zeros(intRange, dtype='float')
intSize = sum(1 for line in open(path))

# Read Jitter Data
with open(path, 'r') as f:
	rr = csv.reader(f)
	for rd in rr:
		d = float(rd[0])/fltUi*intRange
		idx = int(round(d))
		arrJx[idx] += 1/float(intSize)

# Cal BER
arrBer = np.zeros(intRange, dtype='float')

for i in range(intRange/2, 0, -1):
	arrBer[i] = arrBer[i+1] + arrJx[i]

for i in range(-intRange/2, 0, 1):
	arrBer[i] = arrBer[i-1] + arrJx[i]

arrBer[0] = (arrBer[-1]+arrBer[1])/2 + arrJx[0]

#Generate Time axis
arrT = np.arange(0, fltUi, fltUi/intRange)

#Plot BER
plt.figure()
plt.plot(arrT, arrBer)
plt.yscale('log')
plt.show()

#Write BER
arrWriteData = []
for i,d in enumerate(arrBer):
	arrWriteData.append([])
	arrWriteData[i].append(d)

with open('ber.csv', 'w') as f:
	wr = csv.writer(f)
	wr.writerows(arrWriteData)

BER(x)の出力です。1MUI(=1e6UI)のデータなのでy軸は1e-6で切れています。

f:id:kent_s:20180817172225p:plain

左側のバスタブを拡大。
f:id:kent_s:20180817172340p:plain

BER=1e-5の後半あたりから曲線が荒い。
これもサンプル数が1MUIの為、BER=5e-5付近で精度が落ちている為。
x=7psec(赤で示したあたり)がDjが無くなるポイントだが非常に滑らか。
つまり、このプロットからRjを予測するのは困難。

2.2 Qプロットの作成

2.1で作ったber.csvからQプロットを作成。
信号遷移率ρTは1とした。
今回のデータは毎サイクルにジッタが発生しているので、信号遷移率は100%となる。

import numpy as np
import csv 
import sys
import matplotlib.pyplot as plt
from scipy import special

fltUi = 100e-12
intRange = 1000
fltRho = 1

args = sys.argv
path = args[1]

#Read BER data
arrBer = []
with open(path, 'r') as f:
	rr = csv.reader(f)
	for rd in rr:
		arrBer.append(float(rd[0]))

#Calc Q plot
arrQ = []
for ber in arrBer:
	q = np.sqrt(2) * special.erfinv(1 - 1/fltRho*ber)
	arrQ.append(q)

#Generate Time axis
arrT = np.arange(0, fltUi, fltUi/intRange)

#Plot Q
plt.figure()
#plt.scatter(np.arange(intRange), arrQ)
plt.plot(arrT, arrQ)
plt.ylim(8, 0)
plt.show()

#Output Data
arrWriteData = []
for i,d in enumerate(arrQ):
	arrWriteData.append([])
	arrWriteData[i].append(d)

with open('q.csv', 'w') as f:
	wr = csv.writer(f)
	wr.writerows(arrWriteData)

Q(x)の出力。
f:id:kent_s:20180817172742p:plain

左のバスタブの拡大。
f:id:kent_s:20180817172849p:plain

バスタブカーブが線形に近いことが確認できる。この線形性を利用してσを計算できる。
x=7psecのSjが無くなるポイントだが、変曲点よりも外側に来ている。
これは参考資料にある通り、Djのpp点Dj(pp)よりも、正規分布中心Dj(δδ)の方が内側に来ることが理由。

2.3 σの計算

最後にσの計算を行う。
BERのバスタブ底は精度が無いので、BER=2e-5のところで近似することにした。
BER=2e-5 ⇒ Q=4.265 (信号遷移率=1の時)なので、Q=4.265のところでfittingを取る。

import numpy as np
import csv 
import sys
import matplotlib.pyplot as plt
from scipy import special

fltUi = 100e-12
intRange = 1000
fltRho = 1

args = sys.argv
path = args[1]

#Read Q data
arrQ = []
with open(path, 'r') as f:
	rr = csv.reader(f)
	for rd in rr:
		arrQ.append(float(rd[0]))

#Search Q 
fltQs = 4.265

def getNearestIndex(list, val):
	return (abs(np.asarray(list) - val)).argmin()

intIlt = getNearestIndex(arrQ[:intRange/2], fltQs)
intIrt = getNearestIndex(arrQ[intRange/2:], fltQs) + intRange/2

#Generate Time axis
arrT = np.arange(0, fltUi, fltUi/intRange)

#Fitting
FitLt = np.polyfit(arrT[intIlt-2:intIlt+2], arrQ[intIlt-2:intIlt+2], 1)
FitRt = np.polyfit(arrT[intIrt-2:intIrt+2], arrQ[intIrt-2:intIrt+2], 1)

print FitLt
print FitRt

#Plot Q
plt.figure()
plt.scatter(arrT, arrQ, c='red')
plt.plot(arrT, np.poly1d(FitLt)(arrT))
plt.plot(arrT, np.poly1d(FitRt)(arrT))
plt.ylim(8, 0)
plt.xlim(0, fltUi)
plt.show()

QプロットとQ=4.265での線形近似直線。
f:id:kent_s:20180818054121p:plain

線形近似の係数はax+bとすると、バスタブ左側はa=9.19e11, b=-5.35. 右側はa=-1.04e12, b=97.0となった。

1/aがRjのσとなるが、計算すると、σ@左=1.1ps, σ@右=1.0psと計算できた。
これは1.1でRjを生成した時の1ps RMSと一致しており、Dual Dirac Methodで正しく見積もれていることが確認できた。

Dj(δδ)=-b/aなので、Dj(δδ)@左=5.8ps, Dj(δδ)@右=-6.3psとなる。
ここからBER=1e-12として、Tj=Dj(δδ)+7*σで見積もると、それぞれ13ps, -13psで、トータル26psとなる。
Dj(pp)=7psだったので、Tj=Dj(pp)+7σで見積もった場合は±14psとなるが、それよりも1psずつ悲観性を無くすことができている。

【Serdes】RjとJTFの関係

PCI Expressなどの高速SerdesのSystemの中で、TXのPLLとRXのCDRはジッタを抑制するフィルタの役割を果たす。これは、ジッタトランスファファンクション(Jitter Transfer Function: JTF)として数学的なモデル化が出来る。

下図の青線がUSB3.1 Gen2のリファレンスとして記載されているRX CDRのJTFである。一方、TX PLL側は同図の赤線のようになる。

RX側のHigh Pass FilterとTX側のLow Pass Filterの組み合わせにより、全帯域のJitterは抑制される。ただし、10MHz付近に関してはスイートスポットとなり、この帯域のジッタは排除することが出来ない。

f:id:kent_s:20180729094817p:plain

JTFはDetermistic Jitter(Dj)を抑える上で効果があることは容易に理解できる。Djは周波数分布が限定されており、その分布がJTFの不感帯に入っていなければ、抑制できると分かるからだ。

では、Random Jitterに対して、これらのフィルタは効くのだろうか?このことをPythonを使ったSimulationで検討した。

検証方法

検証モチーフはUSB3.1 Gen2である。手順をいかに示す。

  1. 乱数を使用し、1ps RMSの時系列データを作成
  2. 1をフーリエ変換
  3. 2にCDRのJTFを乗算
  4. 3を逆フーリエ変換し時系列波形を再生
  5. 4の標準偏差を計算

Simulationに使ったPythonのプログラムを本記事の末尾に記載する。

検証結果

結果は下記の通り、JTFによってほとんどジッタは減っていないことが分かった。

  • JTF通過前ジッタ: 1.00006781201 ps RMS
  • JTF通過後ジッタ: 0.996609674857 ps RMS

周波数スペクトルで見ると、下図の通り、JTFによって低周波数成分は明確に減衰していることは分かる。
ランダムジッタは非常に広い帯域で分布しており、かつ、広域側の強度が強い。したがって、低域側だけの減衰では効果が少ないことが原因と思われる。
にしても、RMSでここまで変化量が少ないというのはとても興味深い。

JTF通過前
f:id:kent_s:20180729105559p:plain

JTF通過後
f:id:kent_s:20180729105632p:plain

ソースコード

import numpy as np
import matplotlib.pyplot as plt

#Sample size
intSize = 1000000
#Time step : 1UI = 100ps
fltStepTime = 100e-12
#Freqency step : 10kHz
fltStepFreq = 1/(intSize*fltStepTime)

#Jitter RMS = 1ps
fltJitterRms = 1e-12

#Generate random pattern
arrData = np.random.normal(0, fltJitterRms, intSize)
arrTime = np.arange(0, intSize*fltStepTime, fltStepTime)

#Generate fft pattern
arrFftData = np.fft.fft(arrData)
arrFftFreq = np.fft.fftfreq(intSize,fltStepTime)

#Calc jitter suppressed spectrum
ks = 0.707
w3dB = 2 * np.pi * 1.5 * 10**7
wn = w3dB / (1 + 2 * ks**2 + ((1 + 2 * ks**2)**2 + 1)**0.5)**(-0.5)
arrFltFftData = np.zeros(intSize, complex)
for i in range(intSize):
        s = 2 * np.pi * arrFftFreq[i] * 1j
        arrFltFftData[i] = (s**2 / (s**2 + 2*ks*wn*s + wn**2)) * arrFftData[i]

#Calc jitter suppressed time domain data
arrFltData = np.fft.ifft(arrFltFftData)

#Output jitter RMS value
print np.std(arrData.real)
print np.std(arrFltData.real)

#Plot Raw Jitter @ Time Domain
#plt.figure()
#plt.plot(arrTime, arrData)

#Plot Raw Jitter @ Histgram
#plt.figure()
#plt.hist(arrData)

#Plot Raw Jitter @ Freq Domain
plt.figure()
plt.plot(arrFftFreq, abs(arrFftData))
plt.axis([1e6,max(arrFftFreq),0,max(abs(arrFftData))])
plt.xscale("log")

#Plot Filtered Jitter @ Time Domain
#plt.figure()
#plt.plot(arrTime, arrFltData.real)

#Plot Filtered Jitter @ Freq Domain
plt.figure()
plt.plot(arrFftFreq, abs(arrFltFftData))
plt.axis([1e6,max(arrFftFreq),0,max(abs(arrFftData))])
plt.xscale("log")

plt.show()

iPhone6sのバッテリー交換を諦めた話

iPhone6sのバッテリー無償交換プログラムが始まって大分経ったかと思う。

僕は思いっきり対象機種で、バッテリー切れによるシャットダウンが頻発していた。一日持たないどころか、1時間くらいウェブブラウジングするだけでバッテリー切れになる。気温低下に弱いのか、冬場は突然シャットダウンすることも多かった。はっきり言って、携帯として使えない状態。

すぐにでも無償交換をしたかったのだが、近所にAppleストアが無く行けなかった。首都圏はともかく、Appleストアは関西ではすごく少ない。Appleストアには電車で片道一時間くらいかけて、心斎橋まで行かなければならない。車はもちろん止める場所もないので、何かのついでに寄ることも出来ない。

なかなか時間を作ることが出来ないでいたのだが、仕事の大きな山場が過ぎ、ようやく時間が出来たので、Appleストア心斎橋まで行ってきた。

Appleストアの様子

心斎橋駅徒歩5分。おしゃれなビルの1・2階がAppleストアだった。洒落た美容院のように全面曇りガラスだった。

ストア内は平日昼間にも関わらず客で溢れかえっていた。しかし、客に対して店員の数が非常に多く、店に入ってすぐ店員に話しかけられた。流暢な日本語を話す白人だった。

予約時刻と名前を告げると、「ただいま込み合っているので10分ほどお待ちください」と言われた。混みあってるのに10分でできるのか~と思い、待つことに。

店内にはBose製のスピーカーなど、Apple製ではない商品も多く展示されていた。Appleは自前で作っている商品も増えてきた印象だったので、もっと前面に自社製品が展示されているのかと思いきや、意外でした。

しかし、買い物する気は全くないので、ウィンドウショッピングはすぐに飽きた。シアター席というのが空いていたので、そこに座った。シアターではiPhoneの使い方みたいなのがレクチャーされていたが、特に興味なく、Kindleに没頭。

約束の10分を大幅に上回り、30分が経った頃に名前が呼ばれた。10分って何やってん白人。応対してくれたのは、さっきの白人とは別のおしゃれパーマをかけた若者だった。

いざ、バッテリー交換…?

「バッテリーの消耗が早いんです」

と伝えると、店員は手持ちのiPadを操作して、私の機種が無償交換プログラムの対象であることを確認。

「ディスプレイが破損していますが、交換しますか?」

スマホはディスプレイが割れていると修理不可能と聞いたことがあったので、何となく予想していた。あまりお金はかけたくないので、

「出来ればしない方向で」

「ディスプレイが破損しているので、バッテリー交換の際に、ディスプレイが嵌らないリスクがございます」

「はい」

「その場合は、ディスプレイ交換をすることになりますが、リスクをご承知おきいただけますか?」

「ディスプレイ交換することになった場合は、いくらかかるんですか?」

「1万7~8千円になります」

「⁉」

「バッテリー交換は無償なのですが、ディスプレイ交換は有償になります」

エンジニアとしての視点からディスプレイ交換になる確率は結構高いと思った。多分、ディスプレイを外した瞬間に端っこが欠ける。端っこが欠けてツメがなくなって、はまらなくなる…。むしろ無事にはまる確率の方が低い。大阪の心斎橋に器用な修理工がいるとも思えなかった。

何となくディスプレイ交換になる可能性は低くはない気がしていた。それでも4~5千円なら出してもいいかなと思っていたが、まさかの2万円弱。3年前の機種に対して2万弱もかけられるか~!ということでiPhone6sのバッテリー交換は諦めました。

iPhone卒業

Appleの瑕疵で不完全なバッテリーを積んだiPhoneを正規の値段で掴まされたのに、その交換が2万円弱とは。決して安くない買い物だけに、腑に落ちないですね…。

落として割ったのはこっちですが、ディスプレイの割れは端っこの1cmくらいの領域で表示には全く影響しないところです。もしバッテリーが正常であれば、修理の必要もありませんでした。

iPhone4s → iPhone5c → iPhone6sと使ってきた僕でしたが、これを機にiPhoneは卒業することにしました。修理のためにAppleストアまで出向くのももう嫌ですし、Appleストアでの店員の対応も何か馬鹿にされた気分でした。天下のAppleで働いてるんだぞ感が漂ってましたね。(バイトのくせに…。)

次はiPhoneに変えて何を買うかをブログネタにしようかと思います。

WiFiストレージ検討

スマホの容量不足によく陥る。

一時期はiPhoneiCloudで有料のストレージを使用していた。が、このサービス、自動でバックアップをしてくれる訳じゃないんです。

というか、どのデータがCloudに保存されているのかすら分からない。さらにいうと、Cloudに移動するための操作方法もよく分からない。

拡張メモリ的に、iPhone内蔵のストレージが大きく見えるような工夫が欲しかったですね。

Apple純正のサービスだし、てっきりシームレスにデータをバックアップしてくれるのかと思った。

ということで最近、考えているのが外部ストレージにバックアップを取る、というやり方。で、見つけたのがWiFiストレージというジャンル。

WiFiストレージとは?

WiFiカードリーダとも呼ばれる。WiFi経由でSDカードや外付けHDDにデータをバックアックすることができる。

無線LANルータ・モバイルバッテリーの機能が内蔵されたものも多い。1台3役で10000円弱だ。

以下の記事のように、多数のメーカーが参入している。

 

matome.naver.jp

欲しいものがない

このジャンル、便利かどうかはソフト次第と思う。いかにシームレスにデータをバックアップできるか。

ファイルを一個一個コピーしないとデータが移せないみたいな、そういう不便な機種は避けたいですね。

また、先に書いたように拡張ストレージとして使えるのが好ましいが、今のところそういう機種は無い。欲しいものが出てくるまで待ち、ですね。

ソフトの問題だと、実際に使うまで分からないところであり、失敗するには一万円は高いです。