質問
私は、C ++で書かれたマイクロプロセッサのシミュレーターに取り組んでいます。
私は、電源を入れたばかりで、まだリセットされていないハードウェアの状態要素をモデル化する方法を探しています。実際の状態要素は0または1のいずれかの未知の値を持っていますが、ソフトウェアモデルではこれは一般的にとしてモデル化されます X
, 、 意味 わからない.
私はこれらをモデル化できるC ++のライブラリを探しています X
繁殖を含む値。つまり、論理的および算術的な操作を処理する方法を知る必要があります X
ES:
1 AND X = X
0 AND X = 0
1 + X = X
等...
安定した速いライブラリはありますか?
編集:
現在のコードがBitVectorsで動作していることに言及することを怠った。より正確には、標準を使用します uint_*t
データ型、そしてこれらは私が交換したいものです。私が使用しているライブラリが何であれ、それ しなければならない 算術、シフト、論理演算子をサポートしてください。
解決
ハードウェアラインをモデル化しようとしている場合は、3つ以上の状態を許可することを考えてください。 AlteraがFPGAシミュレーターで使用するものは次のとおりです。
- 1:強いハイ(VDDへのトランジスタ駆動)
- 0:強い低い(VSSに駆動されるトランジスタ)
- H:弱い高(VDDへの抵抗のプルアップ)
- L:弱い低い(VSSへの抵抗器のプルダウン)
- Z:高インピーダンス(非駆動線)
- X:不明
- W:弱い不明
- U:非初期化
- DC:気にしないでください
w、u、dcは必要ないかもしれません。バスが常に運転されている場合は、H、L、Zを捨てることができます。
Verilogはさらに多くのレベルを使用します ゲートレベルモデリング, 、各ロジックレベルに7つのドライブ強度があります。追加レベルは、信号線に対する容量性効果をモデル化します。これはおそらくあなたが必要とする以上のものです。
編集: あなたはビットのベクトルについて言及したので、私はそう言わなければなりません、私は、あなたは公共の場でそのようなライブラリを見つけることはないだろうと言わなければなりません。 、および2)その中でさえ、ラインレベルをモデリングする前述のオプションにより、互換性はほとんどありません。 BoostのTriboolはサービスに押し込むことができますが、操作は要素ごとになり、ストレージが最適化されないため、高速ではありませんが、誰かが社内ライブラリを書くことにアレルギーがある場合は唯一の選択肢かもしれません。必要なことを正確に行います。
たとえば、4つの可能なレベルのビットのベクトルを表すクラスが必要だとします:1、0、X、およびZ。まず、各レベルの同等のビットパターンを定義する必要があります(x = 00、z = 01、0 = 10、1 = 11; xはリセット状態として選択されました)
各操作について、あなたは真実のテーブル、できれば カルノー地図 形:
op: & | X (00) | Z (01) | 1 (11) | 0 (10)
-------+--------+--------+--------+--------
X (00) | X (00) | X (00) | X (00) | X (00)
-------+--------+--------+--------+--------
Z (01) | X (00) | X (00) | X (00) | X (00)
-------+--------+--------+--------+--------
1 (11) | X (00) | X (00) | 1 (11) | 0 (10)
-------+--------+--------+--------+--------
0 (10) | X (00) | X (00) | 0 (10) | 0 (10)
(Xが多くの勝利を収めていることに注意してください。これはほとんどの操作に当てはまります。)
次に、k-mapのブール方程式を作成します。
C = A & B
=> C1 = A1 & B1
C0 = A1 & B1 & A0 & B0 = C1 & A0 & B0
最後に、それをC ++に変換します。
template<size_t NBits> class BitVector
{private:
enum { NWords = (NBits+31)/32 };
int32_t storage[NWords][2];
public:
BitVector<NBits> operator &(BitVector<NBits>& rhs)
{ BitVector<NBits> result;
for(unsigned k = 0; k < NWords; ++k)
{ int32_t x = storage[k][1] & rhs.storage[k][0];
result.storage[k][1] = x;
result.storage[k][0] = storage[k][0] & rhs.storage[k][0] & x;
}
return result;
}
};
(注:上記のコードをテストしていないので、あなた自身の責任で使用してください。)
全て 許可されたレベルのセットが変更された場合、これの再度をやり直す必要があります。これが、これらのライブラリがブーストのような一般的なライブラリに入れるには専門的すぎる傾向がある理由です。
編集2: Bitvectorテンプレートクラスには、コンマオペレーターのオーバーロードが理にかなっている数少ないユースケースの1つがあることがわかりました。
template<size_t NBitsR>
BitVector<NBits+NBitsR> operator ,(const BitVector<NBitsR>& rhs);
これにより、ビットベクトルを連結できます。
BitVector<8> a("1110 0111");
BitVector<4> b("0000");
BitVector<12> c = (a, b); // == BitVector<12>("0000 1110 0111")
...これは、1つのベクトルを別のサイズに合わせてパッドパッドする最も直感的な方法のようです(そのようなパディングは簡単に示すのは簡単です いいえ 暗黙のうちに これまで)またはベクトルをマージします。
編集3: それは私に夜明けしました(ええ、私は遅いです) 本当 これの一般化されたバージョンをやりたかった、あなたはそれをすることができます ポリシーベースの設計:
struct TwoLevelLogic
{ enum
{ kNumPlanes = 1
};
static void And(int32_t[] result, int32_t[] lhs, int32_t[] rhs)
{ result[0] = lhs[0] & rhs[0];
}
};
struct FourLevelLogic
{ enum
{ kNumPlanes = 2
};
static void And(int32_t[] result, int32_t[] lhs, int32_t[] rhs)
{ int32_t x = lhs[1] & rhs[1];
result[1] = x;
result[0] = lhs[0] & rhs[0] & x;
}
};
template<typename LogicType, size_t NBits>
class BitVector
{private:
enum { NWords = (NBits+31)/32 };
int32_t storage[NWords][LogicType::kNumPlanes];
public:
BitVector<LogicType, NBits> operator &(BitVector<LogicType, NBits>& rhs)
{ BitVector<LogicType, NBits> result;
for(unsigned k = 0; k < NWords; ++k)
LogicType::And(result.storage[k], storage[k], rhs.storage[k]);
return result;
}
};
template<size_t NBits>
class BitVector4L: public BitVector<FourLevelLogic, NBits> {};
次に、別のロジック表現、たとえば9レベル、または2つさえ2つを使用する場合は、これらの形式をサポートする新しいポリシーを定義できます。さらに、問題のさまざまなドメイン(ボードの4つのレベル、チップで9、プロセッサシミュレーターの場合は2)のさまざまなポリシーを計算し、ギャップを橋渡しする変換関数を定義できます。
繰り返しますが、私はこれを構築しようとしていないので、これが完全に最適化されるかどうかはわかりません。
他のヒント
試す boost.tribool.
tribool
クラスは組み込みのように機能しますbool
タイプですが、3状態のブールロジック用です。 3つの州はそうですtrue
,false
, 、 とindeterminate
, 、最初の2つの状態はC ++の状態と同等ですbool
タイプと最後の状態は未知のブール値を表します(それはtrue
またfalse
, 、私たちは知りません)。
あなたは見ることができます テストスーツ そしてその ヘッダードキュメント このクラスがサポートするルールについて。
ブーストライブラリは非常に高品質で手入れが行き届いているため、その安定性を心配する必要はありません。そして、「速い」...まあ、このような単純なクラスでは遅くなるのは難しいです:)。操作は、1または2との2〜3の整数比較で実装されます if
節が十分に効率的である必要があります。
BoostにはTribool Libraryがありますが、使用したことがないので、その品質についてコメントすることはできません。
上記のブーストライブラリには精通していませんが、ビットフィールドではなく、単一のブール値だけをサポートしているようです。次のような手法を使用して、あまりにも大騒ぎせずに自分でそれを行うことができます:
class Logic
{
unsigned x, xu;
public:
Logic(unsigned x, unsigned xu)
{
this->x = x;
this->xu = xu;
}
Logic operator&(const Logic &rhs) const
{
return Logic(
x & rhs.x,
xu & (rhs.x | rhs.xu) | rhs.xu & (x | xu));
}
Logic operator|(const Logic &rhs) const
{
return Logic(
x | rhs.x,
xu & (~rhs.x | rhs.xu) | rhs.xu & (~x | xu));
}
};
免責事項 - これには確認が必要です!
これらの多くを一度に行う予定がある場合は、個々の部族の代わりに64ビットの整数を使用する方が良いでしょう。