def elaborate(self, platform):
m = Module()
perm = Signal(self.width, reset_less=True)
- rb64 = [Signal(1, reset_less=True, name=f"rb64_{i}") for i in range(64)]
- for i in range(64):
- m.d.comb += rb64[i].eq(self.rb[63-i])
+ rb64 = [Signal(1, reset_less=True, name=f"rb64_{i}")
+ for i in range(self.width)]
+ for i in range(self.width):
+ m.d.comb += rb64[i].eq(self.rb[self.width-1-i])
rb64 = Array(rb64)
- for i in range(8):
+ for i in range(self.width//8):
index = self.rs[8*i:8*i+8]
idx = Signal(8, name=f"idx_{i}", reset_less=True)
m.d.comb += idx.eq(index)
- with m.If(idx < 64):
+ with m.If(idx < self.width):
m.d.comb += perm[i].eq(rb64[idx])
m.d.comb += self.ra[0:8].eq(perm)
return m
# to the output stage
# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
+# Copyright (C) 2020, 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+
from nmigen import (Module, Signal, Cat, Repl, Mux, Const, Array)
from nmutil.pipemodbase import PipeModBase
from nmutil.clz import CLZ
return LogicalOutputData(self.pspec)
def elaborate(self, platform):
+ XLEN = self.pspec.XLEN
m = Module()
comb = m.d.comb
op, a, b, o = self.i.ctx.op, self.i.a, self.i.b, self.o.o
comb += o.ok.eq(1) # overridden if no op activates
- m.submodules.bpermd = bpermd = Bpermd(64)
- m.submodules.popcount = popcount = Popcount()
+ m.submodules.bpermd = bpermd = Bpermd(XLEN)
+ m.submodules.popcount = popcount = Popcount(XLEN)
##########################
# main switch for logic ops AND, OR and XOR, cmpb, parity, and popcount
par0 = Signal(reset_less=True)
par1 = Signal(reset_less=True)
comb += par0.eq(Cat(a[0], a[8], a[16], a[24]).xor())
- comb += par1.eq(Cat(a[32], a[40], a[48], a[56]).xor())
+ if XLEN == 64:
+ comb += par1.eq(Cat(a[32], a[40], a[48], a[56]).xor())
with m.If(op.data_len[3] == 1):
comb += o.data.eq(par0 ^ par1)
with m.Else():
comb += o[0].eq(par0)
- comb += o[32].eq(par1)
+ if XLEN == 64:
+ comb += o[32].eq(par1)
###################
###### cntlz v3.0B p99
count_right = Signal(reset_less=True)
comb += count_right.eq(XO[-1])
- cntz_i = Signal(64, reset_less=True)
+ cntz_i = Signal(XLEN, reset_less=True)
a32 = Signal(32, reset_less=True)
comb += a32.eq(a[0:32])
with m.Else():
comb += cntz_i.eq(Mux(count_right, a[::-1], a))
- m.submodules.clz = clz = CLZ(64)
+ m.submodules.clz = clz = CLZ(XLEN)
comb += clz.sig_in.eq(cntz_i)
comb += o.data.eq(Mux(op.is_32bit, clz.lz-32, clz.lz))
# input (and output) for logical initial stage (common input)
class LogicalInputData(FUBaseData):
- regspec = [('INT', 'ra', '0:63'), # RA
- ('INT', 'rb', '0:63'), # RB/immediate
- ('XER', 'xer_so', '32'), # bit0: so
- ]
def __init__(self, pspec):
super().__init__(pspec, False)
# convenience
self.a, self.b = self.ra, self.rb
+ @property
+ def regspec(self):
+ return [('INT', 'ra', self.intrange), # RA
+ ('INT', 'rb', self.intrange), # RB/immediate
+ ('XER', 'xer_so', '32'), # bit0: so
+ ]
# input to logical final stage (common output)
class LogicalOutputData(FUBaseData):
- regspec = [('INT', 'o', '0:63'), # RT
- ('CR', 'cr_a', '0:3'),
- ('XER', 'xer_so', '32'), # bit0: so
- ]
def __init__(self, pspec):
super().__init__(pspec, True)
# convenience
self.cr0 = self.cr_a
+ @property
+ def regspec(self):
+ return [('INT', 'o', self.intrange),
+ ('CR', 'cr_a', '0:3'),
+ ('XER', 'xer_so', '32'), # bit0: so
+ ]
+
# output from logical final stage (common output) - note that XER.so
# is *not* included (the only reason it's in the input is because of CR0)
class LogicalOutputDataFinal(FUBaseData):
- regspec = [('INT', 'o', '0:63'), # RT
- ('CR', 'cr_a', '0:3'),
- ]
def __init__(self, pspec):
super().__init__(pspec, True)
# convenience
self.cr0 = self.cr_a
+ @property
+ def regspec(self):
+ return [('INT', 'o', self.intrange),
+ ('CR', 'cr_a', '0:3'),
+ ]
class LogicalPipeSpec(CommonPipeSpec):
class Popcount(Elaboratable):
- def __init__(self):
- self.a = Signal(64, reset_less=True)
- self.b = Signal(64, reset_less=True)
+ def __init__(self, width=64):
+ self.width = width
+ self.a = Signal(width, reset_less=True)
+ self.b = Signal(width, reset_less=True)
self.data_len = Signal(4, reset_less=True) # data len up to... err.. 8?
- self.o = Signal(64, reset_less=True)
+ self.o = Signal(width, reset_less=True)
+ assert width in [32, 64], "only 32 or 64 bit supported for now"
def elaborate(self, platform):
m = Module()
# creating arrays big enough to store the sum, each time
pc = [a]
# QTY32 2-bit (to take 2x 1-bit sums) etc.
- work = [(32, 2), (16, 3), (8, 4), (4, 5), (2, 6), (1, 7)]
+ work = [(16, 3), (8, 4), (4, 5), (2, 6), (1, 7)]
+ if self.width == 64:
+ work = [(32, 2)] + work
for l, bw in work: # l=number of add-reductions, bw=bitwidth
pc.append(array_of(l, bw))
- pc8 = pc[3] # array of 8 8-bit counts (popcntb)
- pc32 = pc[5] # array of 2 32-bit counts (popcntw)
+ pc8 = pc[-4] # array of 8 8-bit counts (popcntb)
+ pc32 = pc[-2] # array of 2 32-bit counts (popcntw)
popcnt = pc[-1] # array of 1 64-bit count (popcntd)
# cascade-tree of adds
for idx, (l, bw) in enumerate(work):
# decode operation length (1-hot)
with m.If(data_len == 1):
# popcntb - pack 8x 4-bit answers into 8x 8-bit output fields
- for i in range(8):
+ for i in range(self.width//8):
comb += o[i*8:(i+1)*8].eq(pc8[i])
with m.Elif(data_len == 4):
- # popcntw - pack 2x 5-bit answers into 2x 32-bit output fields
- for i in range(2):
- comb += o[i*32:(i+1)*32].eq(pc32[i])
+ if self.width == 64:
+ # popcntw - pack 2x 5-bit answers into 2x 32-bit output fields
+ for i in range(2):
+ comb += o[i*32:(i+1)*32].eq(pc32[i])
+ else:
+ comb += o.eq(popcnt[0])
with m.Else():
# popcntd - put 1x 6-bit answer into 64-bit output
comb += o.eq(popcnt[0])
class LogicalIlangCase(TestAccumulatorBase):
def case_ilang(self):
- pspec = LogicalPipeSpec(id_wid=2, parent_pspec=None)
+ class PPspec:
+ XLEN = 64
+ pps = PPspec()
+ pspec = LogicalPipeSpec(id_wid=2, parent_pspec=pps)
alu = LogicalBasePipe(pspec)
vl = rtlil.convert(alu, ports=alu.ports())
with open("logical_pipeline.il", "w") as f:
f.write(vl)
-class TestRunner(FHDLTestCase):
- def __init__(self, test_data):
- super().__init__("run_all")
- self.test_data = test_data
+class TestRunner(unittest.TestCase):
def execute(self, alu, instruction, pdecode2, test):
print(test.name)
simulator, code)
yield Settle()
- def run_all(self):
+ def test_it(self):
+ test_data = LogicalIlangCase().test_data + \
+ LogicalTestCase().test_data
m = Module()
comb = m.d.comb
instruction = Signal(32)
m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
- pspec = LogicalPipeSpec(id_wid=2, parent_pspec=None)
+ class PPspec:
+ XLEN = 64
+ pps = PPspec()
+ pspec = LogicalPipeSpec(id_wid=2, parent_pspec=pps)
m.submodules.alu = alu = LogicalBasePipe(pspec)
comb += alu.p.i_data.ctx.op.eq_from_execute1(pdecode2.do)
sim.add_clock(1e-6)
def process():
- for test in self.test_data:
+ for test in test_data:
print(test.name)
program = test.program
with self.subTest(test.name):
if __name__ == "__main__":
- unittest.main(exit=False)
- suite = unittest.TestSuite()
- suite.addTest(TestRunner(LogicalIlangCase().test_data))
- suite.addTest(TestRunner(LogicalTestCase().test_data))
-
- runner = unittest.TextTestRunner()
- runner.run(suite)
+ unittest.main()