【问题标题】:How to simulate digital logic circuits with feedback loops?如何模拟带有反馈回路的数字逻辑电路?
【发布时间】:2015-06-23 10:29:17
【问题描述】:

我正在学习如何模拟数字逻辑电路。 我在这里展示我第一次尝试的源代码。 它是用于模拟电路的小程序,包括 AND、OR 和 NOT 门。

此代码适用于没有循环的电路。 当引入电路循环时,由于无限递归,它会导致堆栈溢出。 请帮我删除这个错误。

请注意,这是一个爱好项目,我们将不胜感激。

源代码:

#include <cstdlib>
#include <iostream>
using namespace std;

class LogicGate
{
    int type;//gate type: 0 for NOT, 1 for OR, 2 for AND
  //pins 
  bool ina;//input a
  bool inb;//input b::this pin is not used for NOT gate
  bool outc;//output

  //fan-in
  LogicGate* ga;//gate connected to input a
  LogicGate* gb;//gate connected to input b

  //fan-out
  LogicGate* gc;//gate connected to output 
  int gctarget;//target input to which the gate "gc" is connected, 0 for input a, 1 for input c 



public:
    char* name;
    LogicGate()
    { 
        ina = inb = outc = false;
        ga = gb = gc = (LogicGate*)0;
        type = 0;
    }
    LogicGate(bool a, bool b)
    { 
        ina = a; inb = b; outc = false;
        ga = gb = gc = (LogicGate*)0;
        type = 0;
    }

    //set logic
    void settype(int t){if(t>=0&&t<3)type=t;else type=0;}

    //set input
    void seta(bool a){ ina = a; }
    void setb(bool b){ inb = b; }
    void setab(bool a, bool b){ina = a; inb = b; }

    //connect gate
    void cona(LogicGate* cga){ ga = cga; }
    void conb(LogicGate* cgb){ gb = cgb; }
    void conab(LogicGate* cga, LogicGate* cgb){ ga = cga; gb = cgb; }

    //connect the output of this gate to another gate's input
    void chainc(LogicGate* cgc, int target)
    { 
        gc = cgc; 
        gctarget = target;
        if(target==0) cgc->cona(this); else cgc->conb(this);
    }

    //calculate output
    bool calcout()
    {
        //if the input is not available make it available by forcing the connected gates to calculate
        if(ga){ ina = ga->calcout(); } //BUG:this may cause Stack overflow for circuits with loops
        if(gb){ inb = gb->calcout(); }//BUG:this may cause Stack overflow for circuits with loops

        //do the logic when inputs are available
        switch(type)
        {
        case 0:
            outc = !ina; break;
        case 1:
            outc = ina || inb; break;
        case 2:
            outc = ina && inb; break;
        }

        //if a gate is connected to output pin transfer the output value to the target input pin of the gate 
        if(gc){
            if(gctarget==0){
                gc->seta(outc);
            }else{
                gc->setb(outc);
            }
        }

        //for debugging only
        cout<<name<<" outputs "<<outc<<endl;
        return outc;
    }


};
int main(int argc, char *argv[])
{   
    LogicGate x,z;

    //AND gate
    z.settype(2);
    z.seta(false);
    z.setb(true);
    z.name = "ZZZ";


    //OR gate
    x.settype(1);
    x.cona(&z); // take one input from AND gate's output
    x.setb(true);
    x.name = "XXX";

    //z.cona(&x);// take one input from OR gate's output to make a loop:: results in stack overflow
    x.chainc(&z,0);//connect the output to AND gate's input "a" to form loop:: results in stack overflow 

    cout<<"final output"<<x.calcout()<<endl;

    return 0;
}

【问题讨论】:

  • 如果存在反馈循环,您希望您的模拟会做什么?你打电话给calcout 然后......会发生什么?
  • 我的观点是:如果系统开始振荡怎么办?
  • 在硬件实验室中,我们将输出定向到 CRO,这里我应该在控制台中连续打印输出值。感谢 Horvath 先生让我思考。

标签: c++ data-structures circuit-diagram


【解决方案1】:

这里的问题是你在无限循环。程序的行为方式与 真正的 逻辑门有所不同。我在这里看到了两种可能性:

1) 实施周期

您可以像 cpu 一样实现它。对 calcout 的调用只计算一个门的输出并迭代到下一个门。你可以为你的门创建一个 Container 类:

class GateContainer
{
    //Contains all gates of your "circuit"
    std::vector<LogicalGate> allGates;

    //Contains all current gates to be processed
    std::queue<LogicalGate*> currentGates;

    void nextStep();
}

nextStep 函数可能如下所示:

void GateContainer::nextStep()
{
    //Get first gate from queue
    LogicalGate *current = currentGates.front();
    currentGates.pop();

    //Do all the calculations with th current gate

    //Push the gate connected to the Output to the list
    currentGates.push(current->gc);
}

请注意此代码未经测试,可能还需要一些错误检查

2) 尝试捕捉循环

您也可以尝试在calcout 中捕获循环。您可以通过在 LogicalGate 中创建一个标志并在每次调用 calcout 之前重置它来实现这一点:

class LogicalGate
{
    ...
    bool calculated;
    ...
}

现在在调用calcout() 之前,您需要为每个门设置计算为false。然后,calcout 可能看起来像这样:

bool calcout()
{
    calculated = true;

    if(ga && !ga->calculated){ ina = ga->calcout(); }
    if(gb && !ga->calculated){ inb = gb->calcout(); }

    ...
}

【讨论】:

    猜你喜欢
    • 2023-04-10
    • 2021-07-06
    • 2021-04-28
    • 2015-06-21
    • 1970-01-01
    • 2012-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多