SQLの条件部でif-then-elseを行う

SQLでwhere検索を行うときに、条件によって、さらに検索条件を切り替えたいということが生じることがあります。

例えば、テーブルにカラムC1, C2, C3が存在するとして、気持ちとして以下のように書きたくなる場合です。

select something from tbl where if p(C1) then q(C2) else r(C3)

カラムC1に依存する述語p(C1)がTRUEの時はq(C2)で検索し、FALSEの場合はr(C3)で検索する、というものです。

SQL: If clause within WHERE clause に答えがでていますが、この場合は、

select something from tbl where (p(C1) and q(C2)) or (not p(C1) and r(C3))

が答えになります。if p(C1) then q(C2) else r(C3)がTRUEになる場合を考えると、p(C1)がTRUEであれば、q(C2)がTRUEである必要があり、 p(C1)がFALSEであればr(C3)がTRUEでないといけません。これを論理式で書いたのが上になります。

あるいは、if p(C1) then q(C2) else r(C3)はp(C1)→q(C2)かつ¬p(C1)→r(C3)と書き直すこともできるので、 A→B = ¬A ⋁ Bを使って、

(not p(C1) or q(C2)) and (p(C1) or r(C3))

と書いても同じ結果になります。

今回の例では説明を具体的するためにカラムC1, C2, C3と書きましたが、大切なのは述語p, q, rですので、 カラムとは無関係に条件を書くことができます。

2023/1/6追記: SQLのwhere句でifで条件文を複数切り替えは不可 case式で代替可能に説明されていますが、whereの中でcaseを使うこともできるので、

select something from tbl where case when p(C1) then q(C2) else r(C3) end

と書くこともできますね。

24インチWQHDモニタ購入

コロナ禍で在宅勤務の時間が長くなっています。以前から27インチ4Kモニタで作業していましたが、 もう少し画面の広さが欲しくなりました。

それで、24QP500-Bを購入しました(2560x1440 23.8インチ)。 27インチを、座った正面に配置しており、その横に、まずは垂直の向きで(90度回転)置いてみましたが、 どうにも垂直方向が思ったより大きすぎて常用には耐えないように感じたので、普通に横置きで使うことにしました。

モニタを置いた状態を上から見たイメージはこんな感じです。縮尺は厳密ではありません。 右のモニタは机の端からはみ出ています(両方ともモニタアーム使用。こういうの)。 こういう自由度の高い配置をするためにも、モニタアームは強く推奨したいですね。 下手にピボットとか高さ調整機能のある台座がついた、数千円高いモニタを買うよりも、 最初から差額でモニタアームを買った方が幸せになれます。 モニタの高さを狙い通りにできるのと、モニタ下の空間が使えるようになるのは大きいです。

モニタ配置

これでも右側のモニタの右端は若干使いにくいです。普段ほとんど参照しないウィンドウを置いてます。 27インチ2枚だったら、この置き方だとさらに右側が使いにくくなってしまったと思います。 この配置であれば、これくらいの画面サイズの組み合わせがベストかもしれません。

これまで4Kに慣れていたので(Windowsでは125%で使用していますが)、 23.8インチWQHDでも画素の粗さが気になってしまう(100%で使用しても)のが予想外でした。 解像度が高いのは正義だと感じます。

愚直なRTLでソートを記述する

FPGAの部屋の記事、 RGB 24ビット・データ入出力対応のメディアン・フィルタをVitis HLS 2021.1で作成する1RGB 24ビット・データ入出力対応のメディアン・フィルタをVitis HLS 2021.1で作成する2にて、HLS記述にてバブルソートを記述し、Interval=1を得ている(1クロック毎にデータを入力できるパイプラインで動作)のを見て、 実はHLSではなく、愚直にRTLで書いてもInterval=1は達成できるのではないかと思い、実験してみました。

ソートをハードウェアで実装するための手法はよく研究されており、ソーティングネットワークと呼ばれているようです。

Wikipediaによれば、3x3(=9)画素のソートを行うためには、7段のソーティングネットワークが最小の段数であるそうです。

“sorting network generator"などと検索すると、ソーティングネットワークの自動生成ツールなどもあり、興味がある方には面白いかもしれません。

書いてみたRTL記述はこちら:

module sort (
    input            CLK,
    input [15:0]     in[0:8],
    output reg[15:0] out
);

    logic[15:0] tmp;
    logic[15:0] in_val[0:8];
    logic[15:0] result;

    int i,j;

    always @(*) begin
        in_val = in;
        for (i = 1; i < 9; i = i + 1) begin
            for (j = 0; j < 9 - i; j = j + 1) begin
                if (in_val[j] < in_val[j+1]) begin
                    tmp         = in_val[j];
                    in_val[j]   = in_val[j+1];
                    in_val[j+1] = tmp;
                end
            end
        end
        result = in_val[4];
    end

    always_ff @(posedge CLK) begin
        out <= result;
    end

endmodule

9個の数値(各16bit)からなる配列inを、上記記事ではC言語で書かれているのと同じ方法でソートしています。 このようなコードは、ある程度RTL記述に慣れた人の方が違和感を感じるかと思います。 ノンブロッキング代入(<=)ではなくブロッキング代入(=)を使っています。

RTLでforループを使用する場合、同じような回路の複数コピーを作成する、というのが用途の大部分を占めると思います。 上記記述もその一例と言えなくは無いですが、どのような回路が合成されるのか、直観的には把握しずらいです。

どのように論理合成が行われるのか、CRC生成回路に実例と共に説明されていますが、要するに、ループ内で使われている変数tmp, in_valに、i, jの値を添え字としてループ毎に別名を付けてあげると思えば、 理論的には展開できるというのが想像できると思います。内側のループ(j)が8,7,6,…,1回回るので、 合計36回ifの部分が展開されることになります。手計算で行おうと思うと気が遠くなりますが、合成ツールは賢いです。

次のようなテストベンチを作ってみます。

module sort_tb;

    logic CLK;
    logic [15:0] in[0:8];
    logic [15:0] out;

    sort dut (.*);

    initial begin
        CLK = 0;
    end

    always #10 CLK <= ~CLK;

    always @(posedge CLK) begin
        in[0]   <=  $urandom();
        in[1]   <=  $urandom();
        in[2]   <=  $urandom();
        in[3]   <=  $urandom();
        in[4]   <=  $urandom();
        in[5]   <=  $urandom();
        in[6]   <=  $urandom();
        in[7]   <=  $urandom();
        in[8]   <=  $urandom();
    end

endmodule

シミュレーションしてみた波形が次です。画面上のsynthはsortに置き換えてください。

シミュレーション画像

緑の入力に対して、1クロック遅れて黄色の出力が得られています。目視でチェックした限り、9つの値の中央値が得られてそうです。

論理合成してみた結果をRTL Viewerで確認してみます。

RTL Viewer

一番右側に一つだけ16bitのレジスタがあって、残りは比較器とマルチプレクサになっています。 何段になっているか、しっかり数えませんでしたが(12段?)、さすがに最小値の7までは行ってなさそうです。

配置配線まで実行してみたところ、Cyclone Vで、ALM 988個、Total registers 16となりました。

ちなみに、久々にQuartusでシミュレーションしようとしたら、ModelSimの起動方法に手間取って、Quartus Prime と ModelSim の NativeLink の使い方を参考にして解決しました。

Logicool K835 OWR購入

最近技術的記事がほとんど無くて商品レビューばかりになっていますが、 Logicool K835 OWRを購入しました。 赤軸リニアというものです。

以前職場で1万円位のサンワサプライの赤軸キーボードを使用していて、これがなかなか良かったので、 今回も赤軸を購入しました。

以前Realforceを購入しましたが、最近のRealforceは安いものでも2万円くらいになってしまいました。PFU Limited Editionに至っては3万円を超えてしまいます。毎日仕事でキーボード入力を行うとはいえ、さすがにこのレベルになると躊躇してしまいます。 一方で、今回のK835は7000円以下で購入できます。

感想としては、思ったより打鍵音が大きいです。前述のサンワサプライ赤軸より大きいと思われます (会社で使用していたため、正確なところは不明)。 もっとも、家で一人作業する分には全く問題はありません。

加えて、キーストロークが結構深いです。これは実際に使用してみて、かなり使いやすいと感じます。 ミスタッチが気持ち減ったかも知れません。キーの重さも比較的軽くて高速に入力できます。

全般的には満足できる買い物でした。

Excite MEC光 開通

先日申し込んでいた エキサイトMEC光 が本日開通しました。

早速、これまで使用していた回線との速度比較をしてみます。2/17(木) 19時台にfastで計測しました。

  • Excite MEC光 (VDSL):
  • iPadで計測:ダウンロード25Mbps, アップロード6.7Mbps, レイテンシ(アンロード済み)16ms, レイテンシ(ロード済み)17ms.
  • デスクトップパソコンのTP-Link AC600 Archer T2Uで計測:ダウンロード24Mbps, アップロード6.6Mbps, レイテンシ(アンロード済み)15ms, レイテンシ(ロード済み)41ms
  • ギガトラWiFi (Softbank回線): ダウンロード16Mbps, アップロード8.3Mbps. レイテンシ(アンロード済み)43ms, レイテンシ(ロード済み)908ms.

現在ルータはパソコンとは別の部屋に置いてあります。USB WiFiが小型であるせいか、間をふすまで仕切るだけで感度と速度が低下してしまいました。上記速度は、ルータとパソコンをほぼ見通せる状態にして計測したものです。iPadはふすまがあっても速度低下は無さそうでした。

LTE回線に対して、ダウンロードは改善し、アップロードは少し改悪。レイテンシは大幅改善でした。LTEだとページ読み込み時にちょっとひっかかる感じがありました。光でレイテンシが改善したせいか、スループットはそれほど向上していなくても、多少サクサク読み込まれている気がします。

また、日中回線が開通した12時頃には、上りは20Mbps程度出ていました。その際は、VDSL終端装置に付属していた1.5m程度の電話コードを使用していました。でも、これだと設置場所が限られたので、10mの電話コードでモジュラージャックに接続しました。上り速度が低下した原因はそのせいなのか、あるいは時間帯のせいなのかは、現在のところ分かっていません(また短いコードに戻すのが面倒なので)。

正直なところ、もう少し速いことを期待していましたが(できれば50Mbps位欲しかった)、気持ちとしてはLTEに対してちょっとの改善といったところです。 もっとも、レイテンシの改善と、通信量制限が無いというメリットはあるので、しばらく様子を見て、これくらいの速度で安定しているなら、ギガトラWiFiは解約しようかと思います。

« 3/23 »