首页 > 解决方案 > 逻辑门的快速计算

问题描述

我创建了以下代码来计算逻辑门(AND、OR、NOT)的结果。该函数将用于从网表文件中读取电路的电路仿真中。一个电路最多可以包含 50000 个逻辑门。

基于在模拟过程中经常调用这个函数的事实,我想知道它是否可以以另一种方式实现,以便生成的机器代码更有效?

一个逻辑门可以有两个以上的输入(除了只有一个输入的 NOT),但大多数逻辑门只有两个。所以我想测试两个输入,然后写这样的东西:return input->predecessors[0]->result && return input->predecessors[1]->result;但这return input->predecessors[0]->result || return input->predecessors[1]->result;可能会引入新的分支。输入的数量可以直接存储在其中Node以防止调用该size()方法。

#include <vector>

enum class NodeType { NOT, AND, OR };

struct Node {
    NodeType type;
    bool result;
    std::vector<Node *> predecessors;
};

bool evaluate(Node *input) {
    switch (input->type) {
        case NodeType::NOT: {
            return !input->predecessors[0]->result;
        }

        case NodeType::AND: {
            bool result = true;

            for (const auto &node : input->predecessors) {
                result = result && node->result;
            }

            return result;
        }

        case NodeType::OR: {
            bool result = false;

            for (const auto &node : input->predecessors) {
                result = result || node->result;
            }

            return result;
        }
    };
};

标签: c++performancesimulation

解决方案


我很想获得第一个输入并将其状态合并到switch(); 喜欢:

    bool result = input->predecessors[0];
    switch((input->type << 1) | result) {
         case (NodeType::NOT << 1) | false:
             return true;
         case (NodeType::NOT << 1) | true:
             return false;
         case (NodeType::AND << 1) | false:
             return false;
         case (NodeType::OR << 1) | true:
             return true;
         case (NodeType::AND << 1) | true: {
             for (const auto &node : input->predecessors) {   // Note: Can skip 1st iteration
                 result = result && node->result;
                 if(result == false) {
                     return false;
                 }
             }
             return true;
         }
         case (NodeType::OR << 1) | false:
             for (const auto &node : input->predecessors) {   // Note: Can skip 1st iteration
                 result = result || node->result;
                 if(result == true) {
                     return true;
                 }
             }
             return false;
         }

希望编译器能够将其转换为跳转表(例如,单个“ jmp [table+rax*8]”指令替换所有switch()代码和其余代码的一半)。

警告:为此,您必须确保input->predecessors[0]将 1 用于“真”(并且没有其他值用于真)。如果这是一个潜在的问题;您可以使用bool result = !!input->predecessors[0];


推荐阅读