【问题标题】:Shift 32 bit Numbers on a 16 bit Datapath在 16 位数据路径上移动 32 位数字
【发布时间】:2021-03-17 08:05:21
【问题描述】:

如何在 16 位数据路径上移动 32 位数字

这是一个计算机体系结构问题。


我的数据路径只有 16 位宽,这意味着我的 ALU 一次只能处理 16 位操作数。 我的寄存器是 32 位宽的,可以在低 16 位和高 16 位部分寻址。

每次我读取寄存器的下半部分时,我还会额外读取一点,告诉我上半部分是否包含任何 1(参考 1)。


到目前为止,我实现了逻辑左移。 (sll rd, rs1, rs2)

  • 读取 rs1 寄存器的下半部分,并将其移位低 rs2 寄存器中指定的量
  • 我从这 16 位中移出的位存储在 alu 内部的一个临时 16 位寄存器中
  • 移位后的值将被写回低 rd 寄存器并设置状态位(参见参考文献 1)

现在如果没有数据写入高位 rs1 寄存器(参见参考文献 1)并且 temp alu 寄存器中的位都是 0,那么我的移位操作就完成了。

否则上半部分需要第二个循环

  • 读取高位 rs1 寄存器并将其移位存储在低位 rs2 寄存器中的数量
  • 但是现在用存储在 alu 临时寄存器中的值填充 rs1(而不是像第一个周期那样使用 0)
  • 移出 16 位空间的位将被丢弃
  • 将结果写回较高的 rd 寄存器,并设置 rd 状态位(参见参考文献 1)

示例 1:假设 rs1 为 0x00001234,rs2 为 0x00000002(执行左移 2)

  • 首先我读取 rs1 和 rs2 的低 16 位,显示 0x1234 和 0x0002。但是通过阅读我也得到了两个寄存器的状态位,在这种情况下,rs1 为 0,rs2 为 0,因为两个寄存器的高 16 位都是 0。使用给定的数据,我可以执行左移 2 . 导致0x48D0。由于没有 1 从 sll 中移出,我可以将结果存储在较低的 rd 中并将其状态位设置为 0。(这一切都在一个周期内完成)

示例 2:假设 rs1 为 0x0000D234,rs2 为 0x00000005(执行左移 5)

  • 首先我读取 rs1 和 rs2 的低 16 位,显示 0xD234 和 0x0005。但是通过阅读我也得到了两个寄存器的状态位,在这种情况下,rs1 为 0,rs2 为 0,因为两个寄存器的高 16 位都是 0。使用给定的数据,我可以执行左移 5 . 导致0x4680。但现在我将 11010 (0x1A) 移出 16 位空间。该值存储在 Alu 临时寄存器中,由于它包含 1,我必须执行另一个循环。
  • 在第二个循环中,我读取了上 rs1 和下 rs2,呈现 0x0000 和 0x0005。我再次左移 5,但现在 Alu 临时寄存器用于填充移位值。 0x0000 -> 0x00__ -> 0x001A。然后将该结果写回上 rd。因此在两个 16 位周期内完成我的 32 位 sll。

示例 3:假设 rs1 为 0x01231234,rs2 为 0x00000002(执行左移 2)

  • 首先我读取 rs1 和 rs2 的低 16 位,显示 0x1234 和 0x0002。但是通过阅读我也得到了两个寄存器的状态位,在这种情况下,rs1 为 1,rs2 为 0,因为 rs1 的高 16 位非零。由于 rs1 的状态位非零,即使没有 1 从低 16 位移出,我也必须执行第二个周期(参见示例 2)。从现在开始,它遵循示例 2,通过写回 rd 并为高位执行第二个循环。

我希望这些示例能提供更好的见解。



现在我想实现一个右移操作(算术和逻辑)。但是如何做到这一点最多 2 个周期,如果我必须首先读取较低的 rs1 寄存器(包括状态位)?


感谢阅读;这是我在这里的第一个问题,所以请不要对我苛刻:D

【问题讨论】:

  • 逻辑左移操作的描述不清楚。所以你可以在一个周期内读取寄存器的下半部分,对其进行移位,检查状态位,将移位后的值写入目标寄存器?位置 15 的位应移至位置 16。何时完成?为什么需要用零填充临时寄存器?为什么需要“用存储在 alu 临时寄存器中的值填充 rs1”?
  • 是的,就像普通的 16 位操作一样;只是我没有从寄存器中读取 16 位,我正在读取 17 位……是 16 位是操作数,最后一位只是描述天气的一位,高 16 位是空的……所以我不如果没有必要,必须对高 16 位执行读取操作。
  • 我在原始问题中添加了示例以澄清
  • 我明白了。在我看来,您基本上可以将临时 ALU 寄存器中的值与另一个给定值合并。此外,如果寄存器的高 16 位为零(如示例 1 中所示),您无需将它们显式设置为零。仅仅通过将状态位设置为零,寄存器可能通过设计将所有这些位设置为零。这很重要,因为 dest 寄存器中的当前高 16 位值可能不为零。你不能指望我们知道这些细节而不准确描述它们。需要对数据路径进行更准确的描述。
  • 来吧,请不要喷我;这是我在 stackoverflow 上的第一次互动。事实上,您不必将高 16 位设置为 0,因为下次访问它们时,它们实际上并没有被读取。由于我们已经知道状态位,只有 16 个“0”通过多路复用器硬连线到 alu,保存读取的 reg 文件。但这与我的问题完全无关,所以我没有提到它

标签: cpu-architecture 32-bit riscv 16-bit riscv32


【解决方案1】:

从阅读较高的部分开始。 第一个周期您将阅读高位部分。进行右移,移出的位将出现在 tmp 寄存器的高位,并且移位的结果将被写回。 第二个周期,你读取低部分,你做一个移位和一个或结果出现在 tmp 寄存器中。那么这部分的结果将被写回。

【讨论】:

  • 感谢您的回答 :D 但是这样每次右移都需要 2 个周期。如果要移位的值仅存在于低 16 位,则无需移位高位。而我只能通过准备加到低16位的状态位来判断上半部分是空的
  • 如果从下半部分开始,如果上半部分等于0,则需要一个循环。但是,如果它与 0 不同,则需要 3 个周期,因为您需要移动低部分、移动高部分或 tmp 和低部分。由于您最多需要在 2 个周期内完成班次,因此这是不可接受的。
  • 绝对正确......但我想知道的是,考虑到这些标准,是否甚至可以在 2 个周期内完成
  • @Sun。左移就像add,因为“进位”(或至少是数据依赖性)从右向左传播。右移很特别,因为它是相反的。除非您可以检查 first 周期中的零上位标志并选择是先高后低,还是在同一周期中只做低,否则您会总是陷入右移i> 需要 2 个周期。除非您有 32 位输入/16 位输出桶形移位器(用于双精度/将一个寄存器移位到另一个寄存器),在这种情况下,您可以直接从输入的两半产生低半输出并跳过高。
  • 好的,谢谢 :D 这也是我对这个问题的看法......如果有任何数据在高 16 位中,则硬件可用 3 个周期;如果状态位被独立读取,则 2 个周期低 16 位
猜你喜欢
  • 2013-05-07
  • 1970-01-01
  • 2020-09-12
  • 2013-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多