+++ /dev/null
-<!-- SVP64 Butterfly DCT Instructions here described are based on -->
-
-<!-- PLEASE NOTE THESE ARE UNAPPROVED AND DRAFT, NOT SUBMITTED TO OPF ISA WG -->
-
-# [DRAFT] Integer Butterfly Multiply Add/Sub FFT/DCT
-
-A-Form
-
-* maddsubrs RT,RA,SH,RB
-
-Pseudo-code:
-
- n <- SH
- sum <- (RT) + (RA)
- diff <- (RT) - (RA)
- prod1 <- MULS(RB, sum)
- prod2 <- MULS(RB, diff)
- if n = 0 then
- prod1_lo <- prod1[XLEN:(XLEN*2) - 1]
- prod2_lo <- prod2[XLEN:(XLEN*2) - 1]
- RT <- prod1_lo
- RS <- prod2_lo
- else
- round <- [0]*(XLEN*2)
- round[XLEN*2 - n] <- 1
- prod1 <- prod1 + round
- prod2 <- prod2 + round
- m <- MASK(XLEN - n - 2, XLEN - 1)
- res1 <- prod1[XLEN - n:XLEN*2 - n - 1]
- res2 <- prod2[XLEN - n:XLEN*2 - n - 1]
- signbit1 <- prod1[0]
- signbit2 <- prod2[0]
- smask1 <- ([signbit1]*XLEN) & ¬m
- smask2 <- ([signbit2]*XLEN) & ¬m
- RT <- (res1 | smask1)
- RS <- (res2 | smask2)
-
-Special Registers Altered:
-
- None
-
-# [DRAFT] Integer Butterfly Multiply Add and Accumulate FFT/DCT
-
-A-Form
-
-* maddrs RT,RA,SH,RB
-
-Pseudo-code:
-
- n <- SH
- prod <- MULS(RB, RA)
- if n = 0 then
- prod_lo <- prod[XLEN:(XLEN*2) - 1]
- RT <- (RT) + prod_lo
- RS <- (RS) - prod_lo
- else
- res1[0:XLEN*2-1] <- (EXTSXL((RT)[0], 1) || (RT)) + prod
- res2[0:XLEN*2-1] <- (EXTSXL((RS)[0], 1) || (RS)) - prod
- round <- [0]*XLEN*2
- round[XLEN*2 - n] <- 1
- res1 <- res1 + round
- res2 <- res2 + round
- signbit1 <- res1[0]
- signbit2 <- res2[0]
- m <- MASK(XLEN -n - 2, XLEN - 1)
- res1 <- res1[XLEN - n:XLEN*2 - n -1]
- res2 <- res2[XLEN - n:XLEN*2 - n -1]
- smask1 <- ([signbit1]*XLEN) & ¬m
- smask2 <- ([signbit2]*XLEN) & ¬m
- RT <- (res1 | smask1)
- RS <- (res2 | smask2)
-
-Special Registers Altered:
-
- None
--- /dev/null
+<!-- SVP64 Butterfly DCT Instructions here described are based on -->
+
+<!-- PLEASE NOTE THESE ARE UNAPPROVED AND DRAFT, NOT SUBMITTED TO OPF ISA WG -->
+
+# [DRAFT] Integer Butterfly Multiply Add and Accumulate FFT/DCT
+
+A-Form
+
+* maddrs RT,RA,RB,SH
+
+Pseudo-code:
+
+ n <- SH
+ prod <- MULS(RB, RA)
+ if n = 0 then
+ prod_lo <- prod[XLEN:(XLEN*2) - 1]
+ RT <- (RT) + prod_lo
+ else
+ res[0:XLEN*2-1] <- (EXTSXL((RT)[0], 1) || (RT)) + prod
+ round <- [0]*XLEN*2
+ round[XLEN*2 - n] <- 1
+ res <- res + round
+ RT <- res[XLEN - n:XLEN*2 - n -1]
+
+Special Registers Altered:
+
+ None
--- /dev/null
+<!-- SVP64 Butterfly DCT Instructions here described are based on -->
+
+<!-- PLEASE NOTE THESE ARE UNAPPROVED AND DRAFT, NOT SUBMITTED TO OPF ISA WG -->
+
+# [DRAFT] Integer Butterfly Multiply Add/Sub Round Shift for FFT/DCT
+
+A-Form
+
+* maddsubrs RT,RA,RB,SH
+
+Pseudo-code:
+
+ n <- SH
+ sum <- (RT[0] || RT) + (RA[0] || RA)
+ diff <- (RT[0] || RT) - (RA[0] || RA)
+ prod1 <- MULS(RB, sum)
+ prod2 <- MULS(RB, diff)
+ if n = 0 then
+ prod1_lo <- prod1[XLEN+1:(XLEN*2)]
+ prod2_lo <- prod2[XLEN+1:(XLEN*2)]
+ RT <- prod1_lo
+ RS <- prod2_lo
+ else
+ round <- [0]*(XLEN*2 + 1)
+ round[XLEN*2 - n + 1] <- 1
+ prod1 <- prod1 + round
+ prod2 <- prod2 + round
+ res1 <- prod1[XLEN - n + 1:XLEN*2 - n]
+ res2 <- prod2[XLEN - n + 1:XLEN*2 - n]
+ RT <- res1
+ RS <- res2
+
+Special Registers Altered:
+
+ None
--- /dev/null
+<!-- SVP64 Butterfly DCT Instructions here described are based on -->
+
+<!-- PLEASE NOTE THESE ARE UNAPPROVED AND DRAFT, NOT SUBMITTED TO OPF ISA WG -->
+
+# [DRAFT] Integer Butterfly Multiply Add and Accumulate FFT/DCT
+
+A-Form
+
+* msubrs RT,RA,RB,SH
+
+Pseudo-code:
+
+ n <- SH
+ prod <- MULS(RB, RA)
+ if n = 0 then
+ prod_lo <- prod[XLEN:(XLEN*2) - 1]
+ RT <- (RT) - prod_lo
+ else
+ res[0:XLEN*2-1] <- (EXTSXL((RT)[0], 1) || (RT)) - prod
+ round <- [0]*XLEN*2
+ round[XLEN*2 - n] <- 1
+ res <- res + round
+ RT <- res[XLEN - n:XLEN*2 - n -1]
+
+Special Registers Altered:
+
+ None
30/6=fmrgew,NORMAL,,1P,EXTRA3,NO,d:FRT,s:FRA,s:FRB,0,FRA,FRB,0,FRT,0,0,0
maddsubrs,NORMAL,,1P,EXTRA3,NO,s:RT;d:RT,s:RA,s:RB,0,RA,0,RB,RT,0,0,0
maddrs,NORMAL,,1P,EXTRA3,NO,s:RT;d:RT,s:RA,s:RB,0,RA,0,RB,RT,0,0,0
+msubrs,NORMAL,,1P,EXTRA3,NO,s:RT;d:RT,s:RA,s:RB,0,RA,0,RB,RT,0,0,0
rlwnm,NORMAL,,1P,EXTRA3,NO,d:RA;d:CR0,s:RB,s:RS,0,0,RB,RS,RA,0,CR0,0
minmax,NORMAL,,1P,EXTRA3,NO,d:RT;d:CR0,s:RA,s:RB,0,RA_OR_ZERO,RB,0,RT,0,CR0,0
sadd,NORMAL,,1P,EXTRA3,NO,d:RT;d:CR0,s:RA,s:RB,0,RA,RB,0,RT,0,CR0,0
-----01011-,ALU,OP_FISHMV,FRS,CONST_UI,NONE,FRS,NONE,NONE,0,0,ZERO,0,NONE,0,0,0,0,0,0,NONE,0,0,fishmv,DX,,1,unofficial until submitted and approved/renumbered by the opf isa wg
------01000,ALU,OP_MADDSUBRS,RA,CONST_SH,RB,RT,NONE,NONE,0,0,ZERO,0,NONE,0,0,0,0,1,0,NONE,0,0,maddsubrs,A,,1,unofficial until submitted and approved/renumbered by the opf isa wg
------01001,ALU,OP_MADDRS,RA,CONST_SH,RB,RT,NONE,NONE,0,0,ZERO,0,NONE,0,0,0,0,1,0,NONE,0,0,maddrs,A,,1,unofficial until submitted and approved/renumbered by the opf isa wg
+------01011,ALU,OP_MSUBRS,RA,CONST_SH,RB,RT,NONE,NONE,0,0,ZERO,0,NONE,0,0,0,0,1,0,NONE,0,0,msubrs,A,,1,unofficial until submitted and approved/renumbered by the opf isa wg
/bcd.py
/bitmanip.py
/branch.py
-/butterfly.py
/byterev.py
/comparefixed.py
/condition.py
/fpmove.py
/fpstore.py
/fptrans.py
+/maddsubrs.py
+/maddrs.py
+/msubrs.py
/pifixedload.py
/pifixedstore.py
/sprset.py
"mffpr", "mffprs",
"ctfpr", "ctfprs",
"mtfpr", "mtfprs",
- "maddsubrs", "maddrs"
+ "maddsubrs", "maddrs", "msubrs"
]:
illegal = False
ins_name = dotstrp
--- /dev/null
+""" Decoder tests
+
+related bugs:
+
+ *
+"""
+
+import unittest
+
+from openpower.test.alu.maddrs_cases import MADDRSTestCase
+from openpower.test.runner import TestRunnerBase
+
+# writing the test_caller invocation this way makes it work with pytest
+
+
+class TestMADDRS(TestRunnerBase):
+ def __init__(self, test):
+ assert test == 'test'
+ super().__init__(MADDRSTestCase().test_data)
+
+ def test(self):
+ # dummy function to make unittest try to test this class
+ pass
+
+
+if __name__ == "__main__":
+ unittest.main()
with m.If((major == 22) & xo6.matches(
'-01000', # maddsubrs
'-01001', # maddrs
+ '-01011', # msubrs
)):
comb += self.implicit_rs.eq(1)
comb += self.extend_rb_maxvl.eq(1) # extend RB
"maddhd", "maddhdu", "maddld", # INT multiply-and-add
"maddsubrs", # Integer DCT Butterfly Add Sub and Round Shift
"maddrs", # Integer DCT Butterfly Add and Accumulate and Round Shift
+ "msubrs", # Integer DCT Butterfly Subtract from and Round Shift
"mcrf", "mcrxr", "mcrxrx", "mfcr/mfocrf", # CR mvs
"mfmsr", "mfspr",
"minmax", # AV bitmanip
OP_SHADD = 103
OP_MADDSUBRS = 104
OP_MADDRS = 105
- OP_BYTEREV = 106
+ OP_MSUBRS = 106
+ OP_BYTEREV = 107
class SelType(Enum):
--- /dev/null
+from openpower.insndb.asm import SVP64Asm
+from openpower.test.common import TestAccumulatorBase, skip_case
+from openpower.endian import bigendian
+from openpower.simulator.program import Program
+from openpower.decoder.isa.caller import SVP64State
+from openpower.test.state import ExpectedState
+from nmutil.sim_util import hash_256
+import math
+from fractions import Fraction
+
+
+class MADDRSTestCase(TestAccumulatorBase):
+ def case_0_maddrs(self):
+ isa = SVP64Asm(["maddsubrs 1,10,11,0",
+ "maddrs 1,10,12,0",
+ "msubrs 2,10,12,0"])
+ lst = list(isa)
+
+ initial_regs = [0] * 32
+ initial_regs[1] = 0x00000a71
+ initial_regs[10] = 0x0000e6b8
+ initial_regs[11] = 0x00002d41
+ initial_regs[12] = 0x00000d00
+
+ e = ExpectedState(pc=12)
+ e.intregs[1] = 0x3658c869
+ e.intregs[2] = 0xffffffffcd583ef9
+ e.intregs[10] = 0x0000e6b8
+ e.intregs[11] = 0x00002d41
+ e.intregs[12] = 0x00000d00
+ self.add_case(Program(lst, bigendian), initial_regs, expected=e)
+
+ def case_1_maddrs(self):
+ isa = SVP64Asm(["maddsubrs 1,10,11,0",
+ "maddrs 1,10,12,14",
+ "msubrs 2,10,12,14"])
+ lst = list(isa)
+
+ initial_regs = [0] * 32
+ initial_regs[1] = 0x00000a71
+ initial_regs[10] = 0x0000e6b8
+ initial_regs[11] = 0x00002d41
+ initial_regs[12] = 0x00000d00
+
+ e = ExpectedState(pc=12)
+ e.intregs[1] = 0x0000d963
+ e.intregs[2] = 0xffffffffffff3561
+ e.intregs[10] = 0x0000e6b8
+ e.intregs[11] = 0x00002d41
+ e.intregs[12] = 0x00000d00
+ self.add_case(Program(lst, bigendian), initial_regs, expected=e)
+
+ def maddrs_many_helper(self, width, shift, prog, case_idx):
+ # if {'width': width, 'shift': shift, 'case_idx': case_idx} \
+ # != {'width': 8, 'shift': 1, 'case_idx': 0}:
+ # return # for debugging
+ gprs = [0] * 32
+ # make some reproducible random inputs
+ k = f"maddrs {width} {shift} {case_idx}"
+ gprs[10] = hash_256(k + " r10") % 2**64
+ gprs[11] = hash_256(k + " r11") % 2**64
+ gprs[20] = hash_256(k + " r20") % 2**64
+ gprs[30] = hash_256(k + " r30") % 2**64
+
+ svstate = SVP64State()
+ svstate.vl = 64 // width # one full 64-bit register
+ svstate.maxvl = 64 // width
+
+ e = ExpectedState(pc=8, int_regs=gprs)
+ e.intregs[10] = 0
+ e.intregs[11] = 0
+ for i in range(svstate.vl):
+ # extract elements
+ rt = (gprs[10] >> (i * width)) % 2 ** width
+ rs = (gprs[11] >> (i * width)) % 2 ** width
+ ra = (gprs[20] >> (i * width)) % 2 ** width
+ rb = (gprs[30] >> (i * width)) % 2 ** width
+ if rt >= 2 ** (width - 1):
+ rt -= 2 ** width # sign extend rt
+ if rs >= 2 ** (width - 1):
+ rs -= 2 ** width # sign extend rs
+ if ra >= 2 ** (width - 1):
+ ra -= 2 ** width # sign extend ra
+ if rb >= 2 ** (width - 1):
+ rb -= 2 ** width # sign extend rb
+ prod = rb * ra
+ rt += prod
+ rs -= prod
+ factor = Fraction(1, 2 ** shift) # shr factor
+ round_up = Fraction(1, 2)
+ # round & shr
+ rt = math.floor(rt * factor + round_up)
+ rs = math.floor(rs * factor + round_up)
+ # insert elements
+ e.intregs[10] |= (rt % 2 ** width) << (width * i)
+ e.intregs[11] |= (rs % 2 ** width) << (width * i)
+
+ with self.subTest(
+ width=width, shift=shift, case_idx=case_idx,
+ RT_in=hex(gprs[10]), RS_in=hex(gprs[11]),
+ RA_in=hex(gprs[20]), RB_in=hex(gprs[30]),
+ expected_RT=hex(e.intregs[10]), expected_RS=hex(e.intregs[11]),
+ ):
+ self.add_case(prog, gprs, expected=e, initial_svstate=svstate)
+
+ def case_maddrs_many(self):
+ for width in 8, 16, 32, 64:
+ shift_end = min(32, width)
+ for shift in range(0, shift_end, shift_end // 8):
+ w = "" if width == 64 else f"/w={width}"
+ prog = Program(list(SVP64Asm([
+ f"sv.maddrs{w} *10,*20,*30,{shift}",
+ ])), bigendian)
+
+ for case_idx in range(25):
+ self.maddrs_many_helper(width, shift, prog, case_idx)
class MADDSUBRSTestCase(TestAccumulatorBase):
def case_0_maddsubrs(self):
- isa = SVP64Asm(["maddsubrs 1,10,14,11"])
+ isa = SVP64Asm(["maddsubrs 1,10,11,14"])
lst = list(isa)
initial_regs = [0] * 32
self.add_case(Program(lst, bigendian), initial_regs, expected=e)
def case_1_maddsubrs(self):
- isa = SVP64Asm(["maddsubrs 1,10,0,11"])
+ isa = SVP64Asm(["maddsubrs 1,10,11,0"])
lst = list(isa)
initial_regs = [0] * 32
self.add_case(Program(lst, bigendian), initial_regs, expected=e)
def case_2_maddsubrs(self):
- isa = SVP64Asm(["maddsubrs 1,10,2,11"])
+ isa = SVP64Asm(["maddsubrs 1,10,11,2"])
lst = list(isa)
initial_regs = [0] * 32
self.add_case(Program(lst, bigendian), initial_regs, expected=e)
def case_3_maddsubrs(self):
- isa = SVP64Asm(["maddsubrs 1,10,16,11"])
+ isa = SVP64Asm(["maddsubrs 1,10,11,16"])
lst = list(isa)
initial_regs = [0] * 32
self.add_case(Program(lst, bigendian), initial_regs, expected=e)
def case_4_maddsubrs(self):
- isa = SVP64Asm(["maddsubrs 1,10,1,11"])
+ isa = SVP64Asm(["maddsubrs 1,10,11,1"])
lst = list(isa)
initial_regs = [0] * 32
def case_maddsubrs_16bit_s14(self):
p = Program(list(SVP64Asm([
- "sv.maddsubrs/w=16 *10,*20,14,*30",
+ "sv.maddsubrs/w=16 *10,*20,*30,14",
])), bigendian)
initial_regs = [0] * 32
for shift in range(0, shift_end, shift_end // 8):
w = "" if width == 64 else f"/w={width}"
prog = Program(list(SVP64Asm([
- f"sv.maddsubrs{w} *10,*20,{shift},*30",
+ f"sv.maddsubrs{w} *10,*20,*30,{shift}",
])), bigendian)
for case_idx in range(25):
self.maddsubrs_many_helper(width, shift, prog, case_idx)
-
- def case_0_maddrs(self):
- isa = SVP64Asm(["maddsubrs 1,10,0,11",
- "maddrs 1,10,0,12"])
- lst = list(isa)
-
- initial_regs = [0] * 32
- initial_regs[1] = 0x00000a71
- initial_regs[10] = 0x0000e6b8
- initial_regs[11] = 0x00002d41
- initial_regs[12] = 0x00000d00
-
- e = ExpectedState(pc=8)
- e.intregs[1] = 0x3658c869
- e.intregs[2] = 0xffffffffcd583ef9
- e.intregs[10] = 0x0000e6b8
- e.intregs[11] = 0x00002d41
- e.intregs[12] = 0x00000d00
- self.add_case(Program(lst, bigendian), initial_regs, expected=e)
-
- def case_1_maddrs(self):
- isa = SVP64Asm(["maddsubrs 1,10,0,11",
- "maddrs 1,10,14,12"])
- lst = list(isa)
-
- initial_regs = [0] * 32
- initial_regs[1] = 0x00000a71
- initial_regs[10] = 0x0000e6b8
- initial_regs[11] = 0x00002d41
- initial_regs[12] = 0x00000d00
-
- e = ExpectedState(pc=8)
- e.intregs[1] = 0x0000d963
- e.intregs[2] = 0xffffffffffff3561
- e.intregs[10] = 0x0000e6b8
- e.intregs[11] = 0x00002d41
- e.intregs[12] = 0x00000d00
- self.add_case(Program(lst, bigendian), initial_regs, expected=e)
-
- def maddrs_many_helper(self, width, shift, prog, case_idx):
- # if {'width': width, 'shift': shift, 'case_idx': case_idx} \
- # != {'width': 8, 'shift': 1, 'case_idx': 0}:
- # return # for debugging
- gprs = [0] * 32
- # make some reproducible random inputs
- k = f"maddrs {width} {shift} {case_idx}"
- gprs[10] = hash_256(k + " r10") % 2**64
- gprs[11] = hash_256(k + " r11") % 2**64
- gprs[20] = hash_256(k + " r20") % 2**64
- gprs[30] = hash_256(k + " r30") % 2**64
-
- svstate = SVP64State()
- svstate.vl = 64 // width # one full 64-bit register
- svstate.maxvl = 64 // width
-
- e = ExpectedState(pc=8, int_regs=gprs)
- e.intregs[10] = 0
- e.intregs[11] = 0
- for i in range(svstate.vl):
- # extract elements
- rt = (gprs[10] >> (i * width)) % 2 ** width
- rs = (gprs[11] >> (i * width)) % 2 ** width
- ra = (gprs[20] >> (i * width)) % 2 ** width
- rb = (gprs[30] >> (i * width)) % 2 ** width
- if rt >= 2 ** (width - 1):
- rt -= 2 ** width # sign extend rt
- if rs >= 2 ** (width - 1):
- rs -= 2 ** width # sign extend rs
- if ra >= 2 ** (width - 1):
- ra -= 2 ** width # sign extend ra
- if rb >= 2 ** (width - 1):
- rb -= 2 ** width # sign extend rb
- prod = rb * ra
- rt += prod
- rs -= prod
- factor = Fraction(1, 2 ** shift) # shr factor
- round_up = Fraction(1, 2)
- # round & shr
- rt = math.floor(rt * factor + round_up)
- rs = math.floor(rs * factor + round_up)
- # insert elements
- e.intregs[10] |= (rt % 2 ** width) << (width * i)
- e.intregs[11] |= (rs % 2 ** width) << (width * i)
-
- with self.subTest(
- width=width, shift=shift, case_idx=case_idx,
- RT_in=hex(gprs[10]), RS_in=hex(gprs[11]),
- RA_in=hex(gprs[20]), RB_in=hex(gprs[30]),
- expected_RT=hex(e.intregs[10]), expected_RS=hex(e.intregs[11]),
- ):
- self.add_case(prog, gprs, expected=e, initial_svstate=svstate)
-
- def case_maddrs_many(self):
- for width in 8, 16, 32, 64:
- shift_end = min(32, width)
- for shift in range(0, shift_end, shift_end // 8):
- w = "" if width == 64 else f"/w={width}"
- prog = Program(list(SVP64Asm([
- f"sv.maddrs{w} *10,*20,{shift},*30",
- ])), bigendian)
-
- for case_idx in range(25):
- self.maddrs_many_helper(width, shift, prog, case_idx)