From: Luke Kenneth Casson Leighton Date: Fri, 23 Apr 2021 14:42:29 +0000 (+0100) Subject: more openpower import conversion X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=72cfe77d308f810439c49517e4aba18c26225e4e;p=soc.git more openpower import conversion --- diff --git a/src/soc/fu/alu/test/svp64_cases.py b/src/soc/fu/alu/test/svp64_cases.py index 15f4211c..f6b8046b 100644 --- a/src/soc/fu/alu/test/svp64_cases.py +++ b/src/soc/fu/alu/test/svp64_cases.py @@ -1,556 +1,5 @@ -from soc.fu.test.common import (TestAccumulatorBase, skip_case) -from soc.config.endian import bigendian -from openpower.simulator.program import Program -from openpower.decoder.isa.caller import SVP64State -from soc.sv.trans.svp64 import SVP64Asm +# moved to openpower-isa +# https://git.libre-soc.org/?p=openpower-isa.git;a=summary +# wildcard imports here ONLY to support migration - -class SVP64ALUTestCase(TestAccumulatorBase): - - def case_1_sv_add(self): - # adds: - # 1 = 5 + 9 => 0x5555 = 0x4321 + 0x1234 - # 2 = 6 + 10 => 0x3334 = 0x2223 + 0x1111 - isa = SVP64Asm(['sv.add 1.v, 5.v, 9.v']) - lst = list(isa) - print("listing", lst) - - # initial values in GPR regfile - initial_regs = [0] * 32 - initial_regs[9] = 0x1234 - initial_regs[10] = 0x1111 - initial_regs[5] = 0x4321 - initial_regs[6] = 0x2223 - # SVSTATE (in this case, VL=2) - svstate = SVP64State() - svstate.vl[0:7] = 2 # VL - svstate.maxvl[0:7] = 2 # MAXVL - print("SVSTATE", bin(svstate.spr.asint())) - - self.add_case(Program(lst, bigendian), initial_regs, - initial_svstate=svstate) - - def case_2_sv_add_scalar(self): - # adds: - # 1 = 5 + 9 => 0x5555 = 0x4321 + 0x1234 - isa = SVP64Asm(['sv.add 1, 5, 9']) - lst = list(isa) - print("listing", lst) - - # initial values in GPR regfile - initial_regs = [0] * 32 - initial_regs[9] = 0x1234 - initial_regs[5] = 0x4321 - svstate = SVP64State() - # SVSTATE (in this case, VL=1, so everything works as in v3.0B) - svstate.vl[0:7] = 1 # VL - svstate.maxvl[0:7] = 1 # MAXVL - print("SVSTATE", bin(svstate.spr.asint())) - - self.add_case(Program(lst, bigendian), initial_regs, - initial_svstate=svstate) - - # This case helps checking the encoding of the Extra field - # It was built so the v3.0b registers are: 3, 2, 1 - # and the Extra field is: 101.110.111 - # The expected SVP64 register numbers are: 13, 10, 7 - # Any mistake in decoding will probably give a different answer - def case_3_sv_check_extra(self): - # adds: - # 13 = 10 + 7 => 0x4242 = 0x1230 + 0x3012 - isa = SVP64Asm(['sv.add 13.v, 10.v, 7.v']) - lst = list(isa) - print("listing", lst) - - # initial values in GPR regfile - initial_regs = [0] * 32 - initial_regs[7] = 0x3012 - initial_regs[10] = 0x1230 - svstate = SVP64State() - # SVSTATE (in this case, VL=1, so everything works as in v3.0B) - svstate.vl[0:7] = 1 # VL - svstate.maxvl[0:7] = 1 # MAXVL - print("SVSTATE", bin(svstate.spr.asint())) - - self.add_case(Program(lst, bigendian), initial_regs, - initial_svstate=svstate) - - def case_4_sv_add_(self): - # adds when Rc=1: TODO CRs higher up - # 1 = 5 + 9 => 0 = -1+1 CR0=0b100 - # 2 = 6 + 10 => 0x3334 = 0x2223+0x1111 CR1=0b010 - - isa = SVP64Asm(['sv.add. 1.v, 5.v, 9.v']) - lst = list(isa) - print("listing", lst) - - # initial values in GPR regfile - initial_regs = [0] * 32 - initial_regs[9] = 0xffffffffffffffff - initial_regs[10] = 0x1111 - initial_regs[5] = 0x1 - initial_regs[6] = 0x2223 - - # SVSTATE (in this case, VL=2) - svstate = SVP64State() - svstate.vl[0:7] = 2 # VL - svstate.maxvl[0:7] = 2 # MAXVL - print("SVSTATE", bin(svstate.spr.asint())) - - self.add_case(Program(lst, bigendian), initial_regs, - initial_svstate=svstate) - - def case_5_sv_check_vl_0(self): - # adds: - # 1 = 5 + 9 => 0x5555 = 0x4321 + 0x1234 - isa = SVP64Asm([ - 'sv.add 13.v, 10.v, 7.v', # skipped, because VL == 0 - 'add 1, 5, 9' - ]) - lst = list(isa) - print("listing", lst) - - # initial values in GPR regfile - initial_regs = [0] * 32 - initial_regs[9] = 0x1234 - initial_regs[5] = 0x4321 - initial_regs[7] = 0x3012 - initial_regs[10] = 0x1230 - svstate = SVP64State() - # SVSTATE (in this case, VL=0, so vector instructions are skipped) - svstate.vl[0:7] = 0 # VL - svstate.maxvl[0:7] = 0 # MAXVL - print("SVSTATE", bin(svstate.spr.asint())) - - self.add_case(Program(lst, bigendian), initial_regs, - initial_svstate=svstate) - - # checks that SRCSTEP was reset properly after an SV instruction - def case_6_sv_add_multiple(self): - # adds: - # 1 = 5 + 9 => 0x5555 = 0x4321 + 0x1234 - # 2 = 6 + 10 => 0x3334 = 0x2223 + 0x1111 - # 3 = 7 + 11 => 0x4242 = 0x3012 + 0x1230 - # 13 = 10 + 7 => 0x2341 = 0x1111 + 0x1230 - # 14 = 11 + 8 => 0x3012 = 0x3012 + 0x0000 - # 15 = 12 + 9 => 0x1234 = 0x0000 + 0x1234 - isa = SVP64Asm([ - 'sv.add 1.v, 5.v, 9.v', - 'sv.add 13.v, 10.v, 7.v' - ]) - lst = list(isa) - print("listing", lst) - - # initial values in GPR regfile - initial_regs = [0] * 32 - initial_regs[9] = 0x1234 - initial_regs[10] = 0x1111 - initial_regs[11] = 0x3012 - initial_regs[5] = 0x4321 - initial_regs[6] = 0x2223 - initial_regs[7] = 0x1230 - # SVSTATE (in this case, VL=3) - svstate = SVP64State() - svstate.vl[0:7] = 3 # VL - svstate.maxvl[0:7] = 3 # MAXVL - print("SVSTATE", bin(svstate.spr.asint())) - - self.add_case(Program(lst, bigendian), initial_regs, - initial_svstate=svstate) - - def case_7_sv_add_2(self): - # adds: - # 1 = 5 + 9 => 0x5555 = 0x4321 + 0x1234 - # r1 is scalar so ENDS EARLY - isa = SVP64Asm(['sv.add 1, 5.v, 9.v']) - lst = list(isa) - print("listing", lst) - - # initial values in GPR regfile - initial_regs = [0] * 32 - initial_regs[9] = 0x1234 - initial_regs[10] = 0x1111 - initial_regs[5] = 0x4321 - initial_regs[6] = 0x2223 - # SVSTATE (in this case, VL=2) - svstate = SVP64State() - svstate.vl[0:7] = 2 # VL - svstate.maxvl[0:7] = 2 # MAXVL - print("SVSTATE", bin(svstate.spr.asint())) - self.add_case(Program(lst, bigendian), initial_regs, - initial_svstate=svstate) - - def case_8_sv_add_3(self): - # adds: - # 1 = 5 + 9 => 0x5555 = 0x4321+0x1234 - # 2 = 5 + 10 => 0x5432 = 0x4321+0x1111 - isa = SVP64Asm(['sv.add 1.v, 5, 9.v']) - lst = list(isa) - print("listing", lst) - - # initial values in GPR regfile - initial_regs = [0] * 32 - initial_regs[9] = 0x1234 - initial_regs[10] = 0x1111 - initial_regs[5] = 0x4321 - initial_regs[6] = 0x2223 - # SVSTATE (in this case, VL=2) - svstate = SVP64State() - svstate.vl[0:7] = 2 # VL - svstate.maxvl[0:7] = 2 # MAXVL - print("SVSTATE", bin(svstate.spr.asint())) - self.add_case(Program(lst, bigendian), initial_regs, - initial_svstate=svstate) - - def case_9_sv_extsw_intpred(self): - # extsb, integer twin-pred mask: source is ~r3 (0b01), dest r3 (0b10) - # works as follows, where any zeros indicate "skip element" - # - sources are 9 and 10 - # - dests are 5 and 6 - # - source mask says "pick first element from source (5) - # - dest mask says "pick *second* element from dest (10) - # - # therefore the operation that's carried out is: - # GPR(10) = extsb(GPR(5)) - # - # this is a type of back-to-back VREDUCE and VEXPAND but it applies - # to *operations*, not just MVs like in traditional Vector ISAs - # ascii graphic: - # - # reg num 0 1 2 3 4 5 6 7 8 9 10 - # src ~r3=0b01 Y N - # | - # +-----+ - # | - # dest r3=0b10 N Y - - # expected results: - # r5 = 0x0 dest r3 is 0b10: skip - # r6 = 0xffff_ffff_ffff_ff91 2nd bit of r3 is 1 - isa = SVP64Asm(['sv.extsb/sm=~r3/dm=r3 5.v, 9.v']) - lst = list(isa) - print("listing", lst) - - # initial values in GPR regfile - initial_regs = [0] * 32 - initial_regs[3] = 0b10 # predicate mask - initial_regs[9] = 0x91 # source ~r3 is 0b01 so this will be used - initial_regs[10] = 0x90 # this gets skipped - # SVSTATE (in this case, VL=2) - svstate = SVP64State() - svstate.vl[0:7] = 2 # VL - svstate.maxvl[0:7] = 2 # MAXVL - print("SVSTATE", bin(svstate.spr.asint())) - - self.add_case(Program(lst, bigendian), initial_regs, - initial_svstate=svstate) - - def case_10_intpred_vcompress(self): - # reg num 0 1 2 3 4 5 6 7 8 9 10 11 - # src r3=0b101 Y N Y - # | | - # +-------+ | - # | +-----------+ - # | | - # dest always Y Y Y - - # expected results: - # r5 = 0xffff_ffff_ffff_ff90 (from r9) - # r6 = 0xffff_ffff_ffff_ff92 (from r11) - # r7 = 0x0 (VL loop runs out before we can use it) - isa = SVP64Asm(['sv.extsb/sm=r3 5.v, 9.v']) - lst = list(isa) - print("listing", lst) - - # initial values in GPR regfile - initial_regs = [0] * 32 - initial_regs[3] = 0b101 # predicate mask - initial_regs[9] = 0x90 # source r3 is 0b101 so this will be used - initial_regs[10] = 0x91 # this gets skipped - initial_regs[11] = 0x92 # source r3 is 0b101 so this will be used - # SVSTATE (in this case, VL=3) - svstate = SVP64State() - svstate.vl[0:7] = 3 # VL - svstate.maxvl[0:7] = 3 # MAXVL - print("SVSTATE", bin(svstate.spr.asint())) - - self.add_case(Program(lst, bigendian), initial_regs, - initial_svstate=svstate) - - def case_11_intpred_vexpand(self): - # reg num 0 1 2 3 4 5 6 7 8 9 10 11 - # src always Y Y Y - # | | - # +-------+ | - # | +------+ - # | | - # dest r3=0b101 Y N Y - - # expected results: - # r5 = 0xffff_ffff_ffff_ff90 1st bit of r3 is 1 - # r6 = 0x0 skip - # r7 = 0xffff_ffff_ffff_ff91 3nd bit of r3 is 1 - isa = SVP64Asm(['sv.extsb/dm=r3 5.v, 9.v']) - lst = list(isa) - print("listing", lst) - - # initial values in GPR regfile - initial_regs = [0] * 32 - initial_regs[3] = 0b101 # predicate mask - initial_regs[9] = 0x90 # source is "always", so this will be used - initial_regs[10] = 0x91 # likewise - initial_regs[11] = 0x92 # the VL loop runs out before we can use it - # SVSTATE (in this case, VL=3) - svstate = SVP64State() - svstate.vl[0:7] = 3 # VL - svstate.maxvl[0:7] = 3 # MAXVL - print("SVSTATE", bin(svstate.spr.asint())) - - self.add_case(Program(lst, bigendian), initial_regs, - initial_svstate=svstate) - - def case_12_sv_twinpred(self): - # reg num 0 1 2 3 4 5 6 7 8 9 10 11 - # src r3=0b101 Y N Y - # | - # +-----+ - # | - # dest ~r3=0b010 N Y N - - # expected results: - # r5 = 0x0 dest ~r3 is 0b010: skip - # r6 = 0xffff_ffff_ffff_ff90 2nd bit of ~r3 is 1 - # r7 = 0x0 dest ~r3 is 0b010: skip - isa = SVP64Asm(['sv.extsb/sm=r3/dm=~r3 5.v, 9.v']) - lst = list(isa) - print("listing", lst) - - # initial values in GPR regfile - initial_regs = [0] * 32 - initial_regs[3] = 0b101 # predicate mask - initial_regs[9] = 0x90 # source r3 is 0b101 so this will be used - initial_regs[10] = 0x91 # this gets skipped - initial_regs[11] = 0x92 # VL loop runs out before we can use it - # SVSTATE (in this case, VL=3) - svstate = SVP64State() - svstate.vl[0:7] = 3 # VL - svstate.maxvl[0:7] = 3 # MAXVL - print("SVSTATE", bin(svstate.spr.asint())) - - self.add_case(Program(lst, bigendian), initial_regs, - initial_svstate=svstate) - - # checks integer predication. - def case_13_sv_predicated_add(self): - # adds: - # 1 = 5 + 9 => 0x5555 = 0x4321 + 0x1234 - # 2 = 0 (skipped) - # 3 = 7 + 11 => 0x4242 = 0x3012 + 0x1230 - # - # 13 = 0 (skipped) - # 14 = 11 + 8 => 0xB063 = 0x3012 + 0x8051 - # 15 = 0 (skipped) - isa = SVP64Asm([ - 'sv.add/m=r30 1.v, 5.v, 9.v', - 'sv.add/m=~r30 13.v, 10.v, 7.v' - ]) - lst = list(isa) - print("listing", lst) - - # initial values in GPR regfile - initial_regs = [0] * 32 - initial_regs[30] = 0b101 # predicate mask - initial_regs[9] = 0x1234 - initial_regs[10] = 0x1111 - initial_regs[11] = 0x3012 - initial_regs[5] = 0x4321 - initial_regs[6] = 0x2223 - initial_regs[7] = 0x1230 - initial_regs[8] = 0x8051 - # SVSTATE (in this case, VL=3) - svstate = SVP64State() - svstate.vl[0:7] = 3 # VL - svstate.maxvl[0:7] = 3 # MAXVL - print("SVSTATE", bin(svstate.spr.asint())) - - self.add_case(Program(lst, bigendian), initial_regs, - initial_svstate=svstate) - - # checks an instruction with no effect (all mask bits are zeros) - def case_14_intpred_all_zeros_all_ones(self): - # adds: - # 1 = 0 (skipped) - # 2 = 0 (skipped) - # 3 = 0 (skipped) - # - # 13 = 10 + 7 => 0x2341 = 0x1111 + 0x1230 - # 14 = 11 + 8 => 0xB063 = 0x3012 + 0x8051 - # 15 = 12 + 9 => 0x7736 = 0x6502 + 0x1234 - isa = SVP64Asm([ - 'sv.add/m=r30 1.v, 5.v, 9.v', - 'sv.add/m=~r30 13.v, 10.v, 7.v' - ]) - lst = list(isa) - print("listing", lst) - - # initial values in GPR regfile - initial_regs = [0] * 32 - initial_regs[30] = 0 # predicate mask - initial_regs[9] = 0x1234 - initial_regs[10] = 0x1111 - initial_regs[11] = 0x3012 - initial_regs[12] = 0x6502 - initial_regs[5] = 0x4321 - initial_regs[6] = 0x2223 - initial_regs[7] = 0x1230 - initial_regs[8] = 0x8051 - # SVSTATE (in this case, VL=3) - svstate = SVP64State() - svstate.vl[0:7] = 3 # VL - svstate.maxvl[0:7] = 3 # MAXVL - print("SVSTATE", bin(svstate.spr.asint())) - - self.add_case(Program(lst, bigendian), initial_regs, - initial_svstate=svstate) - - # checks that we are able to resume in the middle of a VL loop, - # after an interrupt, or after the user has updated src/dst step - # let's assume the user has prepared src/dst step before running this - # vector instruction - # make sure we skip mask bits before the initial step - def case_15_intpred_reentrant(self): - # reg num 0 1 2 3 4 5 6 7 8 9 10 11 12 - # srcstep=1 v - # src r3=0b0101 Y N Y N - # : | - # + - - + | - # : +-------+ - # : | - # dest ~r3=0b1010 N Y N Y - # dststep=2 ^ - # - # expected results: - # r5 = 0x0 # skip - # r6 = 0x0 # dststep starts at 3, so this gets skipped - # r7 = 0x0 # skip - # r8 = 0xffff_ffff_ffff_ff92 # this will be used - - isa = SVP64Asm(['sv.extsb/sm=r3/dm=~r3 5.v, 9.v']) - lst = list(isa) - print("listing", lst) - - # initial values in GPR regfile - initial_regs = [0] * 32 - initial_regs[3] = 0b0101 # mask - initial_regs[9] = 0x90 # srcstep starts at 2, so this gets skipped - initial_regs[10] = 0x91 # skip - initial_regs[11] = 0x92 # this will be used - initial_regs[12] = 0x93 # skip - - # SVSTATE (in this case, VL=4) - svstate = SVP64State() - svstate.vl[0:7] = 4 # VL - svstate.maxvl[0:7] = 4 # MAXVL - # set src/dest step on the middle of the loop - svstate.srcstep[0:7] = 1 - svstate.dststep[0:7] = 2 - print("SVSTATE", bin(svstate.spr.asint())) - - self.add_case(Program(lst, bigendian), initial_regs, - initial_svstate=svstate) - - def case_16_shift_one_by_r3_dest(self): - # reg num 0 1 2 3 4 5 6 7 8 9 10 11 - # src r30=0b100 N N Y - # | - # +-----------+ - # | - # dest r3=1: 1< not to be touched (skipped) - # 2 = 6 + 10 => 0x3334 = 0x2223+0x1111 - # expected results: - # r1 = 0xbeef skipped since CR4 is 1 and test is inverted - # r2 = 0x3334 CR5 is 0, so this is used - isa = SVP64Asm(['sv.add/m=ne 1.v, 5.v, 9.v']) - lst = list(isa) - print("listing", lst) - - # initial values in GPR regfile - initial_regs = [0] * 32 - initial_regs[1] = 0xbeef # not to be altered - initial_regs[9] = 0x1234 - initial_regs[10] = 0x1111 - initial_regs[5] = 0x4321 - initial_regs[6] = 0x2223 - # SVSTATE (in this case, VL=2) - svstate = SVP64State() - svstate.vl[0:7] = 2 # VL - svstate.maxvl[0:7] = 2 # MAXVL - print("SVSTATE", bin(svstate.spr.asint())) - - # set up CR predicate - CR4.eq=1 and CR5.eq=0 - cr = 0b0010 << ((7-4)*4) # CR4.eq (we hope) - - self.add_case(Program(lst, bigendian), initial_regs, - initial_svstate=svstate, initial_cr=cr) +from openpower.test.fu.alu.svp64_cases import * diff --git a/src/soc/sv/trans/svp64.py b/src/soc/sv/trans/svp64.py index e8f592fb..06e27ea8 100644 --- a/src/soc/sv/trans/svp64.py +++ b/src/soc/sv/trans/svp64.py @@ -1,672 +1,5 @@ -# SPDX-License-Identifier: LGPLv3+ -# Copyright (C) 2021 Luke Kenneth Casson Leighton -# Funded by NLnet http://nlnet.nl +# moved to openpower-isa +# https://git.libre-soc.org/?p=openpower-isa.git;a=summary +# wildcard imports here ONLY to support migration -"""SVP64 OpenPOWER v3.0B assembly translator - -This class takes raw svp64 assembly mnemonics (aliases excluded) and -creates an EXT001-encoded "svp64 prefix" followed by a v3.0B opcode. - -It is very simple and straightforward, the only weirdness being the -extraction of the register information and conversion to v3.0B numbering. - -Encoding format of svp64: https://libre-soc.org/openpower/sv/svp64/ -Bugtracker: https://bugs.libre-soc.org/show_bug.cgi?id=578 -""" - -import os, sys -from collections import OrderedDict - -from openpower.decoder.isa.caller import (SVP64PrefixFields, SV64P_MAJOR_SIZE, - SV64P_PID_SIZE, SVP64RMFields, - SVP64RM_EXTRA2_SPEC_SIZE, - SVP64RM_EXTRA3_SPEC_SIZE, - SVP64RM_MODE_SIZE, SVP64RM_SMASK_SIZE, - SVP64RM_MMODE_SIZE, SVP64RM_MASK_SIZE, - SVP64RM_SUBVL_SIZE, SVP64RM_EWSRC_SIZE, - SVP64RM_ELWIDTH_SIZE) -from openpower.decoder.pseudo.pagereader import ISA -from openpower.decoder.power_svp64 import SVP64RM, get_regtype, decode_extra -from openpower.decoder.selectable_int import SelectableInt -from soc.consts import SVP64MODE - - -# decode GPR into sv extra -def get_extra_gpr(etype, regmode, field): - if regmode == 'scalar': - # cut into 2-bits 5-bits SS FFFFF - sv_extra = field >> 5 - field = field & 0b11111 - else: - # cut into 5-bits 2-bits FFFFF SS - sv_extra = field & 0b11 - field = field >> 2 - return sv_extra, field - - -# decode 3-bit CR into sv extra -def get_extra_cr_3bit(etype, regmode, field): - if regmode == 'scalar': - # cut into 2-bits 3-bits SS FFF - sv_extra = field >> 3 - field = field & 0b111 - else: - # cut into 3-bits 4-bits FFF SSSS but will cut 2 zeros off later - sv_extra = field & 0b1111 - field = field >> 4 - return sv_extra, field - - -# decodes SUBVL -def decode_subvl(encoding): - pmap = {'2': 0b01, '3': 0b10, '4': 0b11} - assert encoding in pmap, \ - "encoding %s for SUBVL not recognised" % encoding - return pmap[encoding] - - -# decodes elwidth -def decode_elwidth(encoding): - pmap = {'8': 0b11, '16': 0b10, '32': 0b01} - assert encoding in pmap, \ - "encoding %s for elwidth not recognised" % encoding - return pmap[encoding] - - -# decodes predicate register encoding -def decode_predicate(encoding): - pmap = { # integer - '1<> 1) == 0, \ - "scalar GPR %s cannot fit into EXTRA2 %s" % \ - (rname, str(extras[extra_idx])) - # all good: encode as scalar - sv_extra = sv_extra & 0b01 - else: - # range is r0-r127 in increments of 4 - assert sv_extra & 0b01 == 0, \ - "vector field %s cannot fit into EXTRA2 %s" % \ - (rname, str(extras[extra_idx])) - # all good: encode as vector (bit 2 set) - sv_extra = 0b10 | (sv_extra >> 1) - elif regmode == 'vector': - # EXTRA3 vector bit needs marking - sv_extra |= 0b100 - - # encode SV-CR 3-bit field into extra, v3.0field - elif rtype == 'CR_3bit': - sv_extra, field = get_extra_cr_3bit(etype, regmode, field) - # now sanity-check (and shrink afterwards) - if etype == 'EXTRA2': - if regmode == 'scalar': - # range is CR0-CR15 in increments of 1 - assert (sv_extra >> 1) == 0, \ - "scalar CR %s cannot fit into EXTRA2 %s" % \ - (rname, str(extras[extra_idx])) - # all good: encode as scalar - sv_extra = sv_extra & 0b01 - else: - # range is CR0-CR127 in increments of 16 - assert sv_extra & 0b111 == 0, \ - "vector CR %s cannot fit into EXTRA2 %s" % \ - (rname, str(extras[extra_idx])) - # all good: encode as vector (bit 2 set) - sv_extra = 0b10 | (sv_extra >> 3) - else: - if regmode == 'scalar': - # range is CR0-CR31 in increments of 1 - assert (sv_extra >> 2) == 0, \ - "scalar CR %s cannot fit into EXTRA2 %s" % \ - (rname, str(extras[extra_idx])) - # all good: encode as scalar - sv_extra = sv_extra & 0b11 - else: - # range is CR0-CR127 in increments of 8 - assert sv_extra & 0b11 == 0, \ - "vector CR %s cannot fit into EXTRA2 %s" % \ - (rname, str(extras[extra_idx])) - # all good: encode as vector (bit 3 set) - sv_extra = 0b100 | (sv_extra >> 2) - - # encode SV-CR 5-bit field into extra, v3.0field - # *sigh* this is the same as 3-bit except the 2 LSBs are - # passed through - elif rtype == 'CR_5bit': - cr_subfield = field & 0b11 - field = field >> 2 # strip bottom 2 bits - sv_extra, field = get_extra_cr_3bit(etype, regmode, field) - # now sanity-check (and shrink afterwards) - if etype == 'EXTRA2': - if regmode == 'scalar': - # range is CR0-CR15 in increments of 1 - assert (sv_extra >> 1) == 0, \ - "scalar CR %s cannot fit into EXTRA2 %s" % \ - (rname, str(extras[extra_idx])) - # all good: encode as scalar - sv_extra = sv_extra & 0b01 - else: - # range is CR0-CR127 in increments of 16 - assert sv_extra & 0b111 == 0, \ - "vector CR %s cannot fit into EXTRA2 %s" % \ - (rname, str(extras[extra_idx])) - # all good: encode as vector (bit 2 set) - sv_extra = 0b10 | (sv_extra >> 3) - else: - if regmode == 'scalar': - # range is CR0-CR31 in increments of 1 - assert (sv_extra >> 2) == 0, \ - "scalar CR %s cannot fit into EXTRA2 %s" % \ - (rname, str(extras[extra_idx])) - # all good: encode as scalar - sv_extra = sv_extra & 0b11 - else: - # range is CR0-CR127 in increments of 8 - assert sv_extra & 0b11 == 0, \ - "vector CR %s cannot fit into EXTRA2 %s" % \ - (rname, str(extras[extra_idx])) - # all good: encode as vector (bit 3 set) - sv_extra = 0b100 | (sv_extra >> 2) - - # reconstruct the actual 5-bit CR field - field = (field << 2) | cr_subfield - - # capture the extra field info - print ("=>", "%5s" % bin(sv_extra), field) - extras[extra_idx] = sv_extra - - # append altered field value to v3.0b, differs for LDST - if ldst_imm: - v30b_newfields.append(("%s(%s)" % (immed, str(field)))) - else: - v30b_newfields.append(str(field)) - - print ("new v3.0B fields", v30b_op, v30b_newfields) - print ("extras", extras) - - # rright. now we have all the info. start creating SVP64 RM - svp64_rm = SVP64RMFields() - - # begin with EXTRA fields - for idx, sv_extra in extras.items(): - if idx is None: continue - if etype == 'EXTRA2': - svp64_rm.extra2[idx].eq( - SelectableInt(sv_extra, SVP64RM_EXTRA2_SPEC_SIZE)) - else: - svp64_rm.extra3[idx].eq( - SelectableInt(sv_extra, SVP64RM_EXTRA3_SPEC_SIZE)) - - # parts of svp64_rm - mmode = 0 # bit 0 - pmask = 0 # bits 1-3 - destwid = 0 # bits 4-5 - srcwid = 0 # bits 6-7 - subvl = 0 # bits 8-9 - smask = 0 # bits 16-18 but only for twin-predication - mode = 0 # bits 19-23 - - mask_m_specified = False - has_pmask = False - has_smask = False - - saturation = None - src_zero = 0 - dst_zero = 0 - sv_mode = None - - mapreduce = False - mapreduce_crm = False - mapreduce_svm = False - - predresult = False - failfirst = False - - # ok let's start identifying opcode augmentation fields - for encmode in opmodes: - # predicate mask (src and dest) - if encmode.startswith("m="): - pme = encmode - pmmode, pmask = decode_predicate(encmode[2:]) - smmode, smask = pmmode, pmask - mmode = pmmode - mask_m_specified = True - # predicate mask (dest) - elif encmode.startswith("dm="): - pme = encmode - pmmode, pmask = decode_predicate(encmode[3:]) - mmode = pmmode - has_pmask = True - # predicate mask (src, twin-pred) - elif encmode.startswith("sm="): - sme = encmode - smmode, smask = decode_predicate(encmode[3:]) - mmode = smmode - has_smask = True - # vec2/3/4 - elif encmode.startswith("vec"): - subvl = decode_subvl(encmode[3:]) - # elwidth - elif encmode.startswith("ew="): - destwid = decode_elwidth(encmode[3:]) - elif encmode.startswith("sw="): - srcwid = decode_elwidth(encmode[3:]) - # saturation - elif encmode == 'sats': - assert sv_mode is None - saturation = 1 - sv_mode = 0b10 - elif encmode == 'satu': - assert sv_mode is None - sv_mode = 0b10 - saturation = 0 - # predicate zeroing - elif encmode == 'sz': - src_zero = 1 - elif encmode == 'dz': - dst_zero = 1 - # failfirst - elif encmode.startswith("ff="): - assert sv_mode is None - sv_mode = 0b01 - failfirst = decode_ffirst(encmode[3:]) - # predicate-result, interestingly same as fail-first - elif encmode.startswith("pr="): - assert sv_mode is None - sv_mode = 0b11 - predresult = decode_ffirst(encmode[3:]) - # map-reduce mode - elif encmode == 'mr': - assert sv_mode is None - sv_mode = 0b00 - mapreduce = True - elif encmode == 'crm': # CR on map-reduce - assert sv_mode is None - sv_mode = 0b00 - mapreduce_crm = True - elif encmode == 'svm': # sub-vector mode - mapreduce_svm = True - else: - raise AssertionError("unknown encmode %s" % encmode) - - if ptype == '2P': - # since m=xx takes precedence (overrides) sm=xx and dm=xx, - # treat them as mutually exclusive - if mask_m_specified: - assert not has_smask,\ - "cannot have both source-mask and predicate mask" - assert not has_pmask,\ - "cannot have both dest-mask and predicate mask" - # since the default is INT predication (ALWAYS), if you - # specify one CR mask, you must specify both, to avoid - # mixing INT and CR reg types - if has_pmask and pmmode == 1: - assert has_smask, \ - "need explicit source-mask in CR twin predication" - if has_smask and smmode == 1: - assert has_pmask, \ - "need explicit dest-mask in CR twin predication" - # sanity-check that 2Pred mask is same mode - if has_pmask and has_smask: - assert smmode == pmmode, \ - "predicate masks %s and %s must be same reg type" % \ - (pme, sme) - - # sanity-check that twin-predication mask only specified in 2P mode - if ptype == '1P': - assert not has_smask, \ - "source-mask can only be specified on Twin-predicate ops" - assert not has_pmask, \ - "dest-mask can only be specified on Twin-predicate ops" - - # construct the mode field, doing sanity-checking along the way - - if mapreduce_svm: - assert sv_mode == 0b00, "sub-vector mode in mapreduce only" - assert subvl != 0, "sub-vector mode not possible on SUBVL=1" - - if src_zero: - assert has_smask or mask_m_specified, \ - "src zeroing requires a source predicate" - if dst_zero: - assert has_pmask or mask_m_specified, \ - "dest zeroing requires a dest predicate" - - # "normal" mode - if sv_mode is None: - mode |= src_zero << SVP64MODE.SZ # predicate zeroing - mode |= dst_zero << SVP64MODE.DZ # predicate zeroing - sv_mode = 0b00 - - # "mapreduce" modes - elif sv_mode == 0b00: - mode |= (0b1<