分析 1 个可变寄存器指令集?

Posted

技术标签:

【中文标题】分析 1 个可变寄存器指令集?【英文标题】:Analyzing a 1-mutable-register instruction set? 【发布时间】:2014-01-12 21:00:46 【问题描述】:

问题总结

我需要能够为概念 CPU + 指令集生成指令。我有一个几乎可以工作的算法。

CPU 只有 1 个始终以 1 开头的可变寄存器(名为 mut),以及一些包含值的不可变寄存器(名为 input[0..n])。此 CPU 的指令只是 mut 上的逻辑门,其中一个输入寄存器将结果存储回 mut。

我需要一种算法来生成指令,使 CPU 能够从某个定义的真值表中为每组可能的输入生成正确的答案。

示例

作为一个例子,也许我希望这个 CPU 像一个 AND 门(它的真值表为 00=0,01=0,10=0,11=1)。我应该能够为算法提供这个真值表并让它吐出指令“AND[0] AND[1]”。如果你跟着你的脑袋,你会看到只有当 INPUT[0] 和 INPUT[1] 都为 1 时,MUT 才会保持为 1。

尝试

目前,我有一个简单的算法实现,它简单地对所有可能的指令集进行广度优先搜索,在每个真值表输入/输出对上测试它们以查看它是否有效。对于我为算法提供的许多期望,它仅在几个级别的搜索中就返回了正确的指令集。但是,对于其他人来说,它会在找到结果之前消耗我整个CPU的内存,所以我只能假设它找不到结果。

问题

是否有 a) 任何有效的方法来设计这个算法,b) 有什么方法可以证明,对于某个指令集,可以实现任何预期的真值表,或者 c) 对这个问题的任何现有见解?

我知道卡诺图,但它们会生成 2D 逻辑电路,而这本质上是 1D 逻辑电路。

如果您有任何问题,请告诉我。这是一个很难解释的问题,但我真的需要帮助。

指令集

作为参考,我的说明是:

AND[n]: MUT = MUT & INPUT[n]
OR[n]: MUT = MUT | INPUT[n]
NOT: MUT = ~MUT

我也许可以向 CPU 发送更多指令,但理想情况下,算法可以尝试使用任何给定指令集解决问题。

【问题讨论】:

您有哪些可用的说明?比如你有条件分支指令吗? 我们需要更多地了解 CPU 指令集。它可以原生执行哪些操作? “只是逻辑门”是不够的信息。我看到指令的形式是 mut reg[i] 但是可用的 集合是什么? 这些指令是严格线性的——一旦启动,它就会在指令中运行,没有可用的分支。我将使用“指令集”编辑主题。 MUT 有多大? 1位?大小无限? 在不移位的情况下无法使用按位运算进行加法。要检查是否所有可能的逻辑表都是可能的,您必须检查 16 种可能性。如果你有一个 NOT 指令,你只需要检查 8 种可能性。我检查了 NOT、AND、OR 和 XOR 的组合是否可以在不读取输入两次的情况下工作。如果没有第二个 MUT 寄存器,就无法摆脱 XOR 指令。 【参考方案1】:

我同意 Martin Rosenau 的观点,我怀疑您的 CPU 是否可以在没有额外功能的情况下处理任何给定的真值表。正如你现在所拥有的,我看不到如何实现例如异或。

因此,我冒昧地添加了一个累加器注册器 ACC(将被初始化为 False)和一个附加命令 ACC

ACC <- ACC or MUT
MUT <- True

鉴于此,以下例程采用参数rules,它是一个布尔列表列表,每行首先表示结果,然后是真值表的输入寄存器 0..n。例如二元异或将是[[True, True, True], [False, False, True], [False, True, False], [True, False, False]]

这有望生成正确的指令:

def generateCode (rules):
    rules = [rule for rule in rules if rule [0] ]
    if not rules: return []
    opcodes = []
    for rule in rules:
        rule = rule [1:]
        negs = [i for i, e in enumerate (rule) if not e]
        poss = [i for i, e in enumerate (rule) if e]
        if negs:
            opcodes.append ('NOT')
            for neg in negs: opcodes.append ('OR[]'.format (neg) )
            opcodes.append ('NOT')
        if poss:
            for pos in poss: opcodes.append ('AND[]'.format (pos) )
        opcodes.append ('ACC')
    return opcodes

例如,从上面获取样本输入,得到['AND[0]', 'AND[1]', 'ACC', 'NOT', 'OR[0]', 'OR[1]', 'NOT', 'ACC'],这似乎是正确的。

这是我测试过的 CPU。我添加了一个重置​​按钮,结果将在执行结束时出现在 ACC 中。

class CPU:
    def reset (self, inputs):
        self.MUT = True
        self.ACC = False
        self.INP = inputs [:]

    def __call__ (self, opcodes):
        for opcode in opcodes:
            if opcode == 'NOT':
                self.MUT = not self.MUT
                continue
            if opcode == 'ACC':
                self.ACC = self.ACC or self.MUT
                self.MUT = True
                continue
            if opcode [0] == 'O':
                inp = int (opcode [3:-1] )
                self.MUT = self.MUT or self.INP [inp]
                continue
            if opcode [0] == 'A':
                inp = int (opcode [4:-1] )
                self.MUT = self.MUT and self.INP [inp]
                continue
            raise Exception ('Need more dried frog pills.')
        return self.ACC

再次抱歉,由于您指定的限制,我无法回答您的问题,但希望我的 sn-p 对您有所帮助。

【讨论】:

首先,我必须真诚地赞扬您的如此出色的反应。 :) 我明白你现在在做什么......对于每一个真理,你检查输入是否符合那个真理条件,如果是,则返回 True。要检查这一点,您将 MUT 的(假设为真)值与所有预期为真的输入相加,然后翻转 MUT,并将其与所有预期为假的输入进行或运算.然后将其存储到 ACC 中。您基本上已将操作拆分为检查输入是否与任何应返回 True 的输入匹配,如果是,则将 ACC 永久设置为 True。这是一个简单的方法,非常聪明。但是,有几个问题... 没有 ACC 的问题如下: (a or b) and (c or d)(a and b) or (c and d) 等表达式需要对括号的结果进行操作,我们无处存储它们。而且我们也不能去掉括号。 a) 看来,对于具有更多 False 输出的真值表,您可以翻转 ACC 的工作方式并最终得到一组更小的指令,对吧? b) 我希望有一个最佳的方法。关于使这个返回尽可能少的指令有什么想法吗? c) 关于不添加 ACC 寄存器的任何想法?这在我的问题域中是可能的,但我想寻求一个没有 ACC 的解决方案。有正式的证明吗? a) 和 b) 你是对的,结果不是最小的。我什至不确定尝试最小化布尔输入项或采用非最佳代码并尝试最小化它是否更聪明......至于c:没有ACC,我不知道如何实现@ 987654330@。您无法摆脱括号,并且无处存储中间结果。这只是一个猜想,幸好我拿到学位时留下了正式的证明。

以上是关于分析 1 个可变寄存器指令集?的主要内容,如果未能解决你的问题,请参考以下文章

RISC-V指令集介绍 - 整数基本指令集

RV32I指令集

RISC处理器设计------指令集的设计

软考重点2 计算机系统

软考重点2 计算机系统

基于栈的指令集与基于寄存器的指令集