题
我正在为用C ++编写的微处理器制作模拟器。
我正在寻找一种在硬件中建模状态元素的方法,这些元素刚刚被电源供电,并且尚未以任何方式重置。真实的状态元素将具有0或1的未知值,但是在软件模型中,通常将其建模为 X
, , 意义 未知.
我正在寻找C ++的库,可以建模这些 X
价值,包括它们的传播。也就是说,它必须知道如何处理逻辑和算术操作 X
ES:
1 AND X = X
0 AND X = 0
1 + X = X
ETC...
是否有既稳定又快速的库?
编辑:
我忽略了我当前的代码与BitVectors一起使用。更准确地说,我使用标准 uint_*t
数据类型,这些是我要替换的数据类型。我使用的任何图书馆, 必须 支持算术,转移和逻辑运算符,以使其有用。
解决方案
如果您试图建模硬件线,您可能想考虑允许三个以上的状态。这是Altera在其FPGA模拟器中使用的内容:
- 1:高高(晶体管驱动到VDD)
- 0:强低(晶体管驱动到VSS)
- h:弱高(电阻卷发到VDD)
- L:弱低(电阻下拉到VSS)
- Z:高阻抗(未发行线)
- X:未知
- W:虚弱的未知
- u:非初始化
- DC:不在乎
您可能不需要W,U和DC。如果您的公共汽车总是被驾驶,则可以抛弃H,L和Z。
Verilog使用更多级别 门级建模, ,每个逻辑水平具有七个驱动力强度。附加级别对信号线的电容效应。这可能比您需要的要多。
编辑: 由于您提到了零碎的矢量,因此我不得不说,恕我直言,您不会在公共使用中找到这样的图书馆,并且要保持最新状态,因为1)并不是太多的程序员需要这样的事情,以及2)即使在其中,由于上述建模线级别的选项,几乎没有兼容性。 Boost的Tribool可以被压入服务,但不会快速,因为操作将是逐元元素,并且不会优化存储,但是如果有人过敏,它们可能是您唯一的选择确实做您需要的。
例如,假设您想要一个代表具有四个可能级别的位的载体:1、0,x和z。 = 10,1 = 11; x被选择为重置状态)
对于每个操作,您都必须写出真相表,最好是 Karnaugh地图 形式:
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;
}
};
(注意:我尚未测试上述代码,因此请自行使用。)
全部 如果允许的级别更改,则必须重做。这就是为什么这些图书馆往往太专业而无法放入像Boost这样的通用库中的原因。
edit2: 我刚刚意识到,BitVector模板类具有少数用的用例之一:逗号运算符有意义:
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")
...这似乎是将一个向量填充到另一个矢量的最直观的方法(很容易证明这种填充应该应该 不是 隐含 曾经)或将向量合并在一起。
edit3: 它只是在我身上突然出现(是的,我很慢),如果你 真的 想要做一个通用版本,您可以使用 基于政策的设计:
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> {};
然后,如果您想使用不同的逻辑表示形式,例如九个级别,甚至两个级别,则可以定义新的政策以支持这些格式。此外,您可以在问题的不同域中使用不同的策略计算(例如,董事会的4个级别,芯片9级,处理器模拟器的2个),并定义转换功能以弥合间隙。
同样,我没有尝试构建这个,因此我不确定这是否完美地优化。
其他提示
尝试 boost.tribool.
这
tribool
类似于内置的班级bool
类型,但适用于三态布尔逻辑。这三个州是true
,false
, , 和indeterminate
, ,前两个状态等同于C ++的状态bool
类型和最后一个状态代表未知的布尔值(可能是true
或者false
, ,我们不知道)。
提升图书馆的质量非常高,维护得很好,因此您不必担心其稳定性。和“快速” ...对于这样的简单课程,很难慢慢:)。该操作以2到3个整数比较与1或2进行了实施 if
条款应足够高效。
Boost有一个Tribool图书馆,但我无法评论其质量,因为我从未使用过:
我不熟悉上面提到的Boost库,但似乎仅支持一个布尔值,而不是Bitfield。您可以使用以下技术来无需太多大惊小怪地做到这一点:
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位整数而不是单个Tribools。