Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;支持三值逻辑的库:0,1,X 我正在做一个微处理器的模拟器,用C++编写。_C++_Tribool - Fatal编程技术网

C++;支持三值逻辑的库:0,1,X 我正在做一个微处理器的模拟器,用C++编写。

C++;支持三值逻辑的库:0,1,X 我正在做一个微处理器的模拟器,用C++编写。,c++,tribool,C++,Tribool,我正在寻找一种方法来模拟刚通电但尚未以任何方式重置的硬件中的状态元素。实状态元素的未知值为0或1,但在软件模型中,这通常被建模为X,表示未知 我正在寻找一个C++库,可以对这些代码< x >代码>值进行建模,包括它们的传播。也就是说,它必须知道如何使用Xes处理逻辑和算术运算: 1 AND X = X 0 AND X = 0 1 + X = X 等等 有没有这样的图书馆既稳定又快速 编辑: 我忘了提到我当前的代码是使用位向量的。更准确地说,我使用标准的uint_*t数据类型,这些是我想要替

我正在寻找一种方法来模拟刚通电但尚未以任何方式重置的硬件中的状态元素。实状态元素的未知值为0或1,但在软件模型中,这通常被建模为
X
,表示未知

我正在寻找一个C++库,可以对这些代码< x >代码>值进行建模,包括它们的传播。也就是说,它必须知道如何使用
X
es处理逻辑和算术运算:

1 AND X = X
0 AND X = 0
1  +  X = X
等等

有没有这样的图书馆既稳定又快速

编辑:


我忘了提到我当前的代码是使用位向量的。更准确地说,我使用标准的
uint_*t
数据类型,这些是我想要替换的数据类型。无论我使用什么库,它都必须支持算术、移位和逻辑运算符才能发挥作用。

Boost有一个tribool库,但我无法评论它的质量,因为我从未使用过它:

试试看

tribool类与内置的
bool
类型类似,但适用于三态布尔逻辑。这三种状态是:代码>真< /代码>,代码>虚伪< /代码>,和<代码>不确定< /C> >,其中前两个状态相当于C++ >代码> BOOL<代码>类型,最后一个状态表示未知布尔值(可能是代码>真< /COD>或<代码> false <代码>,我们不知道。 您可以看到该类支持的规则的和


Boost库的质量非常高,维护良好,所以您不必担心它的稳定性。和“快”。。。对于像这样的简单类来说,很难放慢速度:)。这些操作是通过2到3个整数与1或2
if
子句进行比较来实现的,因此应该足够有效。

如果您尝试对硬件线路建模,您可能需要考虑允许三种以上的状态。以下是Altera在其FPGA模拟器中使用的内容:

  • 1:强高电平(晶体管驱动至VDD)
  • 0:强低(晶体管驱动至VSS)
  • H:弱高(电阻上拉至VDD)
  • L:弱低(电阻下拉至VSS)
  • Z:高阻抗(未驱动线路)
  • X:未知
  • W:弱未知
  • U:未初始化
  • 华盛顿:不在乎
您可能不需要W、U和DC。如果你的公共汽车总是开着的话,你可以把H、L和Z抛到一边

Verilog使用了更多的驱动级别,每个逻辑级别有七个驱动强度。附加电平模拟信号线上的电容效应。这可能比你需要的要多

编辑:既然你提到了位向量,我不得不说,IMHO,你不会在公共场合找到这样一个库并保持最新,因为1)没有那么多程序员需要这样的东西,2)甚至在他们中间,由于前面提到的行级别建模选项,几乎没有兼容性。Boost的Tribool可以强制投入使用,但不会很快,因为操作将是逐元素的,存储也不会优化,但如果有人不愿意编写符合您需要的内部库,它们可能是您唯一的选择

例如,假设您想要一个表示具有四个可能级别的位向量的类:1、0、X和Z。首先,您必须为每个级别定义等效的位模式(例如,X=00、Z=01、0=10、1=11;X被选为重置状态)

对于每个操作,您必须写出真值表,最好采用以下形式:

(请注意,X赢了很多。大多数操作都是如此。)

然后从K图中算出布尔方程:

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;
    }
};   
模板类位向量
{私人:
枚举{NWords=(NBits+31)/32};
国际存储[NWords][2];
公众:
位向量运算符&(位向量和rhs)
{位向量结果;
for(无符号k=0;k
(注意:我还没有测试上面的代码,因此使用风险自负。)

如果允许的级别集发生更改,则必须重新执行所有这些操作。这就是为什么这些库往往过于专业化,无法放入像Boost这样的通用库中

EDIT2:我刚刚意识到BitVector模板类有少数几个重载逗号运算符的用例之一:

template<size_t NBitsR>
BitVector<NBits+NBitsR> operator ,(const BitVector<NBitsR>& rhs);
模板
位向量运算符(常量位向量和rhs);
这使您可以连接位向量:

BitVector<8> a("1110 0111");
BitVector<4> b("0000");
BitVector<12> c = (a, b); // == BitVector<12>("0000 1110 0111")
位向量a(“1110 0111”);
位向量b(“0000”);
位向量c=(a,b);//=位向量(“0000 1110 0111”)
。。。这似乎是将一个向量填充到另一个向量的大小(很容易证明这种填充不应该是隐式的)或将向量合并在一起的最直观的方法

EDIT3:我突然意识到(是的,我很慢),如果你真的想做一个通用的版本,你可以用:

结构TwoLevelLogic {enum {kNumPlanes=1 }; 静态无效和(int32_t[]结果、int32_t[]左侧、int32_t[]右侧) {result[0]=lhs[0]&rhs[0]; } }; 结构四层逻辑 {enum {kNumPlanes=2 }; 静态无效和(int32_t[]结果、int32_t[]左侧、int32_t[]右侧) {int32_t x=lhs[1]&rhs[1]; 结果[1]=x; 结果[0]=lhs[0]&rhs[0]&x; } }; 模板 类位向量 {私人: 枚举{NWords=(NBits+31)/32}; int32_t存储[nWord][LogicType::kNumPlanes]; 公众: 位向量运算符&(位向量和rhs) {位向量结果; 对于(无符号k=0;
BitVector<8> a("1110 0111");
BitVector<4> b("0000");
BitVector<12> c = (a, b); // == BitVector<12>("0000 1110 0111")
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> {};
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));
    }
};