Software

この章では制御用のLinuxソフトウェアについて述べます。

開発環境

  • CentOS7
  • gcc version 4.8.5

HR-TDC用のソースコードのみROOTファイルを作るためにCERN ROOTに依存します。 ROOTがインストールできない環境ではHR-TDCをmake対象から外してください。

ディレクトリ構造
CoreLibはこのソフトウェアり利用される共通のライブラリを提供します。CommonはSDSやFMPの制御など、各ファームウェアで共通の要素を制御するためのプログラムを提供します。そのほか各ファームウェア専用のソースコードはFW名がついたディレクトリ内に存在します。

hul_software.git
├── Makefile
├── CoreLib
├── Common
└── FW directories

ソースファイル

ソースファイルには他のDAQシステムへ移植する際にそのままコピーするべきなライブラリ的なファイルと、同じように動作さえすればどのように書いてもいい物、デバッグ用で移植の必要がない物が存在します。重要な物だけ説明します。
全ての実行体は引数無しで起動するとusageが表示されるようになっています。

CoreLib

rbcp.hh
RBCPパケットの構造体です。そのまま移植してください。
Uncopyable.hh
自身のクラスのコピーコンストラクタと代入演算子を禁止するメソッドです。かなり古い実装方法で今はc++の標準機能で同様の事が出来るためそのうちなくします。
BitDump
整数値を渡してbit列を標準出力するためのクラスです。元々はUnpackerの中で使われていたものを移植しました。UDPRBCPの中で使っています。デバッグに便利です。
Utility
コンソール上でプログレスバーを表示したり文字を点滅させたりします。移植の必要はないのですがFlashMemoryProgrammerの中で利用しています。
UDPRBCP
SiTCPのUDP通信を行うためのクラスで、重要なソースコードです。コンストラクタはIP address、upd portを必要とし、最後の引数は表示モードです。UDPRBCP.hh内にRbcpDebugModeという列挙体で定義されています。
  • NoDisp: 通信時に何も表示しません。
  • Interactive: 何をしている程度の情報を出力します。
  • Debug: 全ての情報を標準出力します。

通常使う際はNoDispでいいでしょう。UDPRBCPはSiTCPの生のUDP通信レベルの機能を制御しています。最低限これがあればHULの制御が可能です。

FPGAModule
UDPRBCPを隠蔽してBusControllerレベルの通信機能を提供するクラスです。UDPRBCPを包含するためコンストラクタはUDPRBCPを引数に取ります。BCTを通じて多バイトの読み書きをサポートすることが主な機能です。
int32_t WriteModule(const uint32_t local_address,
                    const uint32_t write_data,
                    const int32_t  n_cycle = 1);

レジスタを書き込むメソッドです。第1引数はRBCP addressです。4章のレジスタマップ、および後述するRegisterMap.hhを参照してください。第2引数が書き込むレジスタです。第3引数は書き込みバイト数です。戻り値はUDCPRBCP::DoRBCPの結果です。この関数は32-bitと64-bitレジスタ用にオーバーロードされています。n_cycleが取れる範囲はそれぞれ1-4と1-8です。

uint32_t ReadModule(const uint32_t local_address,
                    const int32_t  n_cycle = 1);

レジスタを読み出すためのメソッドです。第1引数はRBCP address。第2引数は多バイト読み出しの回数を設定します。読み出した結果は関数の戻り値に現れます。n_cycleの値に限らずuint32_tの型で与えられます。この関数も32-bitと64-bit用にオーバーロードされています。

int32_t WriteModule_nByte(const uint32_t  local_address,
                          const uint32_t* write_data,
                          const int32_t   n_byte);

同一のアドレスに複数バイト書き込むための関数です。この関数では書き込みのたびにアドレスの最下位をインクリメントしません。想定する書き込み先はFIFOです。

int32_t ReadModule_nByte(const uint32_t  local_address,
                         const int32_t   n_byte);

同一のアドレスから複数バイト読み出すための関数です。この関数では読み出しのたびにアドレスの最下位をインクリメントしません。想定する読み出し元はFIFOです。読み出したデータはrd_data_というクラス変数に格納されます。GetDataIteratorでイテレータを取得してアクセスしてください。

SiTCPController
SiTCPの予約領域に直接アクセスするための関数です。EraseEEPROMはEEPROMを全消去するための関数です。EEPROMの領域に読み書きする関数は危険なため作っていません。SiTCP Utilityを使うことをお勧めします。
void ResetSiTCP(const std::string ip)

SiTCPをソフトリセットします。

void WriteSiTCP(const std::string ip,
                const uint32_t addr_ofs,
                const uint32_t reg)

SiTCP予約領域アドレスに1-byteのレジスタを書き込むための関数です。SiTCPの予約領域は0xffffff00から始まっており、そこからのオフセットをaddr_ofsで指定します。この関数ではEEPROM領域にはアクセスできません。

void ReadSiTCP(const std::string ip,
                   const uint32_t addr_ofs)

SiTCP予約領域から1byteのレジスタを読み出すための関数です。addr_ofsの意味はWrite_SiTCPと同様です。

void EraseEEPROM(const std::string ip)

EEPROMを全消去するための特殊な関数です。IPアドレスやMACやライセンス情報など全部消えるため、SiTCPのライセンスファイルは再書き込みする必要があります。この関数はBBTのSiTCPコミュニティに報告が挙がっている“一度TCPコネクションを張るとしばらく再接続することができなくなる“問題の解決に使います。詳しくは該当スレッドを見てください。

Common
FlashMemoryProgrammerとSelf Diagnosis Systemの制御用のプログラムがまとめられています。これらはHULのFWの共通部分のため、レジスタはRegisterMapCommon.hhとしてまとめられています。HUL制御の例題集のような側面があるので、各main関数の動きを説明します。

assert_bctreset
BCT::ResetにアクセスしFW内でリセット信号をアサートさせます。
erase_eeprom
SiTCPControllerのEraseEEPROMを呼び出しす実行体です。
reconfig_fpga
能動的にFPGAをSPIフラッシュメモリからリコンフィグする実行体です。FPGAは電源投入時にSPIフラッシュメモリからコンフィグされますが、それを任意のタイミングで行うためのプログラムです。FPGA放射線ダメージを受けた、新しいMCSをFMPを使ってSPIフラッシュメモリへダウンロードした、などのタイミングで使います。
read_xadc
SDS内のXADCインターフェースにアクセスして、FPGAの温度、VCCINT電圧、VCCAUX電圧を取得します。
read_sem
SDS内のSEMインターフェースにアクセスして、訂正可能なSEUを修正した回数、SEMの動作状態 (watchdog)、修正不可能な放射線損傷を検知したかどうか (uncorrectable)を読み出します。SEUを訂正した回数はBCTリセット以上のリセット信号かSemRstCorCountにアクセスで0に戻ります。Uncorrectableに1が立っている場合FPGAの再コンフィグが必要です。
reset_sem
SEMのソフトリセットをアサートします。
inject_sem_error
SEMを使って人工的にSEUを発生させます。デバッグ用です。DRPを使ってSEMにアクセスしているので、理解すれば他の動作もさせる事が出来ます。詳しくはXilinxのPG036を参照してください。
flash_memory_programmer
MCSファイルをSiTCPを通じてSPIフラッシュメモリへ書き込むためのプログラムです。MCSファイルをバイナリに変換(MCSは実はテキストファイルです)、SPIメモリの型番のチェック、メモリイレース、プログラム、リードバックとベリファイを順番に実行します。
mcs_converter
MCSファイルをあらかじめバイナリに変換しておくためのプログラムです。
check_spi_device
HUL上にのっているSPIフラッシュメモリの型番を調べます。何が乗っているか分からないときに使ってください。
verify_mcs
SPIフラッシュメモリからリードバックして指定のMCSファイルとの整合性をチェックします。

各FW用のプログラム

殆どのFWではdebugdaqの実行体だけが実装されています。daqはデータ取得するための実行体です。DAQコードのサンプルとして使ってください。RegisterMap.hhにはFW特有のレジスタのアドレスが書かれています。ここではFW特有のプログラムについて説明します。

DaqFuncs.cc
DAQを行うための関数をまとめたソースコードです。ベタ移植する必要は無いですが、ConnectSocket、Event_Cycle、receive関数はそのまま移植したほうがいいでしょう。また、MH-TDCのSetTdcWindowもそのまま移植してください。基本的には計測ブロックの設定を行い、DCTでgateを開いて、EventCycleを呼び続ける、RUNが終わったらDCTでgateを閉じる、という流れになります。
Gateを閉じた後タイムアウトするまでEventCycleを呼びつづける事でHUL内部のバッファを空にしているので、while(-1 != EvenCycle)の処理は必ず行ってください。これをやらないと次のRUNの先頭に前のRUNで読まれなかったイベントが返ってくる可能性があります。
daq
HULからデータ読み出しを実行します。 次の様にIP address、RUN番号、および取得するイベント数を引数に与えてください。./bin/daq [ip address] [RUN no] [# of events]. データファイルはdata/run1.datのようにコマンドが実行されたディレクトリのサブディレクトリdata内に生成されます。そのため、この実行体は各ファームウェアディレクトリの下で実行されることが想定されています。dataディレクトリが存在しない場合make実行時に生成されます。
データ収集中、読み出したデータが何イベントかに1回コンソール上に表示されます。

HR-TDC

initialize
DDR receiverの初期化、および校正クロックを使ってestimator用のLUTの校正を行います。電源投入後に1度実行するする必要があります。
decoder
デバッグ用にデコーダが用意されています。次のようにRUN番号を与えて実行してください./bin/decoder [RUN no]. このプログラムはdataディレクトリ内のデータファイルを読み、rootfileディレクトリにデコード結果のroot fileを生成します。daqと同様に各ファームウェアディレクトリの下で実行されることが想定されています。

TTreeの構造

Branch name Description
through 各メザニンHR-TDCのTDC::Throughの設定を示します。 インデックス0と1はスロットUとスロットDに対応します。
stop_out 各メザニンHR-TDCのTDC::StopDoutの設定を示します。 インデックス0と1はスロットUとスロットDに対応します。
over_flow Sub-headersのOverFlow bitを示します。インデックス0と1はスロットUとスロットDに対応します。
Decoded common stop TDC data.
stop_fine_count Common stop dataのFine count (TDC dataの下位13 bit)です。TDC::StopDoutが1である場合利用可能なデータです。
stop_estimator Common stop dataのestimator値です。TDC::StopDoutが1である場合利用可能なデータです。
stop_coarse_count Common stop dataのcouarse count (TDCデータの上位11 bit)。TDC::StopDoutが1である場合利用可能なデータです。
common_stop Common stopのTDC値。TDC::StopDoutが1である場合利用可能なデータです。
Decoded data for leading edge measurement.
num_hit リーディングエッジデータのヒット数です。
num_hit_ch 各チャンネルにおけるリーディングエッジデータのヒット数です。
channel チャンネル番号です。この配列のインデックス番号はデコードされた順番を示します。
fine_count リーディングエッジデータのfine count値です。TDC::Throughが1の時有効なデータです。この配列のインデックス番号はデコードされた順番を示します。
estimator リーディングエッジデータのestimator値です。TDC::Throughが0の時有効なデータです。この配列のインデックス番号はデコードされた順番を示します。
coarse_count リーディングエッジデータのcoarse count値です。この配列のインデックス番号はデコードされた順番を示します。
tdc_leading リーディングエッジデータのTDC値です。この配列のインデックス番号はデコードされた順番を示します。
Decoded data for trailing edge measurement.
tdc_trailing トレーリングエッジデータのTDC値です。この配列のインデックス番号はデコードされた順番を示します。
ブランチ名がtから始まる物はトレーリングエッジデータのデコード結果を示します。
xadcとsem
Mezzanine HR-TDCにもSDSが実装されているので、メザニンのXADCとSEMへアクセスする実行体が用意されています。

Three-dimensional matrix trigger

このFW用のソースコードはMtx3D_E03E42というフォルダにまとめてあります。Mtx3D_E03E42/example_register以下にはレジスタのサンプル集が置かれています。各実行体はレジスタファイルを読み込んでFPGAへ反映させるために用います。レジスタファイルでは#から始まる行はコメント扱いになります。

レジスタファイル

dwg/dwg_register.txt
各ブロック内のDWGレジスタを設定します。各信号の遅延量と幅の調整が可能です。取れる値の範囲はテキストファイルに書かれている通りです。
mtx/matrix3d(2d)_pattern.txt
Trigger出力を行うためのmatrix patternの設定を行います。FWの章で説明した通り3次元のパターンを多ビットのシフトレジスタへ展開しています。TOFとSCHの若い方の組み合わせから8ビットのパターンを順番に設定していきます。各行にはSCHのセグメント番号が記述されていますが、ソフトウェアではSCHの番号は読み取っていません。この並びはFPGA内部のシフトレジスタの配置で決まっているので、テキストファイル内で行の入れ替えは出来ません。つまり、行の追加や削除も出来ません。matrix2d_patternの方は2次元の各行列要素を1次元に並べた表記になっています。
nimo/nimo_register.txt
NIM出力ポートにどの内部信号を出力するかを決めるレジスタです。

実行体

load_register
dwgレジスタファイルを読み込んでFPGAへ設定します。
load_matrix3d(2d)
matrix_patternレジスタファイルを読み込んでFPGAへ設定します。
set_nimo
nimoレジスタファイルを読み込んでFPGAへ設定します。

Mass trigger

このFW用のソースコードはMsTというフォルダにまとめてあります。MsT/example_register以下にはレジスタのサンプル集が置かれています。レジスタファイルでは#から始まる行はコメント扱いになります。MsTはDAQ昨日とトリガー生成機能の両方が存在するため、データ収集用の実行体とレジスタ設定用の実行体の両方が存在します。