« 2009年7月 | トップページ | 2009年9月 »

2009年8月の3件の記事

【SystemC】 SystemC with MinGW, MSYS

システムシミュレーションをするべくSystemCを勉強中やねんけど、C++が使える人にとっては、これは楽やなぁ。
HDLを使ってるデジタルハード屋さんにはちょっと厳しいかもしれへんけどね。

ってな事で、基本的にソフト屋さんな僕としてはSystemCは特に違和感なく取っ掛かる事ができました。
まださわりだけやから、これから色々と調べなくちゃならん事があるかもしれへんけど...。

SystemCの動作環境についてです。
メインマシンはubuntuなので、殆ど問題なし。SystemCのサイトからパッケージをダウンロードしたら、普通に動きました。波形データもVCDファイルに落として、GTKwaveを使って見る事ができたしね。

Screenshotgtkwave_halfaddrvcd_2 ←半加算器を実装して波形観測した様子。





さて問題はWindows環境や。
Windows環境では僕は通常MinGW+MSYSを使ってるんやけど、SystemCのパッケージはcygwinを推奨しているみたい。
configureがMinGWには対応してないんですわ。そこで、ちょこちょこ〜っと変更してMinGW版のlibsystemc.aを作成してみました。以下、そのやり方を覚え書き。

MinGWで動作させるSystemC

  1. パッケージをダウンロードする
  2. ソースコードをコピー
  3. ソースを一部変更
  4. MinGW用のmakefileを作成してビルド
  5. オブジェクトファイルを抽出(バージョン2.2.0で78ファイル)
  6. アーカイバでライブラリ作成

こんな感じ。

1. は http://www.systemc.org/ にアクセスして、利用者登録してパッケージをダウンロードすればOK。
今現在の最新版は 2.2.0 ですわ。

2. 上でダウンロードしたパッケージを解凍すると

tar -zxvf systemc-2.2.0.tar.gz

config, docs, examples, src ...といったディレクトリができまする。
この内、srcのみを使いまする。
srcディレクトリを適当な場所にそっくりコピー。
元ファイルを取っておかなくてもよければ、このコピーは不要ですわ。

3. ソースを一部変更しまする。
SystemCのkernelやdatatypeといったコードはcygwinのg++に対応させているらしく、一部MinGWのg++ではエラーになる記述が存在するねん。あと、僕がgcc4を使っているからって事もあるのやけど、型不一致のエラーも出てたみたい。
という事で、以下のように修正します。

sysc/datatypes/int/sc_nbdefs.cpp
sysc/datatypes/int/sc_int64_mask.cpp

ファイルの先頭に以下の行を追加

#undef WIN32

これは、WIN32定義があると i64 記述子を使うようになっているためです。
MinGWのgccではi64記述子は使われへんようやね。コマンドオプションで何かあったような気がするんやけど、とりあえず手っ取り早くコードを変更しちゃいました。ご丁寧にもWIN32以外やったら、ULL記述子を使うようにコードが書かれてるし。

sysc/datatypes/int/sc_nbcommon.inc
2985行目で型不一致エラーになるので、std::_Ios_Fmtflagsへのキャストを追加。

os.setf((std::_Ios_Fmtflags)old_flags, ::std::ios::basefield);


sysc/kernel/sc_cor_fiber.h

PVOIDとかが未定義やってエラーになるんで、ファイル先頭に以下の行を追加。

#include <windows.h>

sysc/utils/sc_utils_ids.cpp
getenv関数とstrcmpの定義が見つからんってエラーになる。よってファイル先頭に以下の行を追加。

#include <stdlib.h>
#include <string.h>

110行目辺り、getenv関数を呼び出している所が、std::getenvを呼び出している。
stdlib.hのgetenvを使うので、stdスコープは余計ですな。削除しまする。

const char* deprecation_warn = getenv("SC_DEPRECATION_WARNINGS");

さぁ、これでコード修正が完了。

4. MinGW用のMakefileを作ってビルド。
まぁ、これは各自サクっとやっちゃってください。
僕の場合は普段から使っているmake ruleがあるんで、それで一期にやっちゃいました。
必要なんは、オブジェクトファイルを作る事なんで、リンクは不要っす。(というかできひん)
コンパイルだけやっちゃってくださいな。
findコマンドとg++でも一応できるけどね。
ちなみにコンパイル対象のディレクトリは

  • communications
  • datatypes
  • kernel
  • tracing
  • utils

だけでOKです。cygwinの環境では qt まで含めてるんやけど、とりあえず使わんでしょう。

5. コンパイルしてできた .oファイルをどこかのフォルダにコピーしてまとめて...

6. アーカイバでライブラリを作成しまする。

$ ar cq libsystemc.a *.o

こんな感じかな。
これで、MinGW環境で使えるlibsystemc.aがでけました。
あとは普通にSystemCのコード書いて、このライブラリをリンクしちゃってくださいな。

ふぅ、cygwinってシェルのパス変更するから好きやないんよなぁ。
という事で、何がなんでもMinGW+MSYSでという方向けの情報ですな。

【ubuntu】 CUPS with Canon iP4100の設定

ubuntu 8.04 LTS サーバでの Canon iP4100 プリンタの設定メモです。
こちらのサイトを参考にしました。

https://help.ubuntu.com/community/HardwareSupportComponentsPrinters/CanonPrinters/CanonPixmaIP4200#preview

手順は以下の通り。

  1. cupsysのインストール
  2. cups.confの編集
  3. alienのインストール
  4. CanonのサイトからiP4100のLinux版ドライバをダウンロード
  5. rpmパッケージをdebパッケージに変換
  6. ドライバのインストール
  7. プリンタの登録

迷うことはさほど無いんやけど、CUPSの立ち上げとドライバのインストールをそれぞれ行う必要がある事。
あと、Canonのサイトではrpm形式のパッケージしか提供されていないので、ubuntuではdebパッケージに変換する必要がある事くらいかな?

【C/C++】 マクロと関数呼び出し

仕事でちょっとはまったC言語の問題。
マルチプラットフォームでビルドしてたんやけど、謎なエラーが表示されててん。

コンパイルしたコードは以下の通り。

if ( condition ) test_func( ... );
else              test_func( ... );

エラー表示されたメッセージは

error: expected primary-expression before ‘else’

ってな感じでしたわ。
なんで else がパースされへんのか?と思って色々調査。

if ( condition ) test_func( ... )
else              test_func( ... );

とすると、コンパイルできました。
これはおかしい。
結局、よく調べてみると test_func というのは関数やなくて、マクロ関数で定義されていました。

#define test_func( ... ) { hogehoge(); fugafuga; ... }

こんな感じ。そのためプリプロで展開すると

if ( condition ) { hogehoge(); fugafuga(); ... };
else              { hogehoge(); fugafuga(); ... };

といった具合になって、1行目の末尾のセミコロンが悪さをしていました。
今回の問題は実はもうちょっと複雑で、片方のプラットフォームでは test_func は外部関数、もう片方のプラットフォームではマクロ関数で定義されていました。そのため、同じソースコードなのにプラットフォーム毎にエラーが起きたり起きなかったりと不可解な挙動をしたわけです。で、問題は回避方法。片方がマクロ関数である限り、セミコロンをつける事はできひんけど、外部関数の呼び出しでエラーになっていまう。逆もしかり。一番手軽な修正方法は中括弧をつける事かね。

if ( condition ) { test_func( ... ); }
else              { test_func( ... ); }

こんな感じにすればマクロ関数でも外部関数でも動作する。
せやけど、シングルステートメントの if〜else 文が書かれへんよなぁ。

色々悩んでいたんやけど、ふと昔見たことがあるテクニックを思い出しました。

#define test_func( ... ) do { hogehoge(); fugafuga(); } while(0)

って定義すれば良いんやった。
最後にセミコロンはつけへんように注意。
このマクロ関数はステートメントの末尾にセミコロンを持つ普通の関数のように扱えるわけや。
while(0)は結局ループなしになるので、コンパイラの最適化でループ自体が削除されて無駄な命令が出力される事もない。(はず。コンパイラの最適化機能によるかね。)

という訳で、無事に解決しました。

« 2009年7月 | トップページ | 2009年9月 »