move over to openpower-isa repo
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 23 Apr 2021 14:26:03 +0000 (15:26 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 23 Apr 2021 14:26:03 +0000 (15:26 +0100)
src/soc/decoder/decode2execute1.py
src/soc/decoder/power_decoder.py
src/soc/decoder/power_fields.py
src/soc/decoder/power_fieldsn.py
src/soc/decoder/selectable_int.py

index 6333dcdf87641405b68fc438761cf222e7755d34..9f670097ad7d07211afcfecceaf23ee082723b0f 100644 (file)
@@ -1,130 +1,5 @@
-"""Decode2ToExecute1Type
+# moved to openpower-isa
+# https://git.libre-soc.org/?p=openpower-isa.git;a=summary
+# wildcard imports here ONLY to support migration
 
 
-based on Anton Blanchard microwatt decode2.vhdl
-
-"""
-from nmigen import Signal, Record
-from nmutil.iocontrol import RecordObject
-from soc.decoder.power_enums import (MicrOp, CryIn, Function,
-                                     SPRfull, SPRreduced, LDSTMode)
-from soc.consts import TT
-from soc.experiment.mem_types import LDSTException
-
-
-class Data(Record):
-
-    def __init__(self, width, name):
-        name_ok = "%s_ok" % name
-        layout = ((name, width), (name_ok, 1))
-        Record.__init__(self, layout)
-        self.data = getattr(self, name) # convenience
-        self.ok = getattr(self, name_ok) # convenience
-        self.data.reset_less = True # grrr
-        self.reset_less = True # grrr
-
-    def ports(self):
-        return [self.data, self.ok]
-
-
-class IssuerDecode2ToOperand(RecordObject):
-    """IssuerDecode2ToOperand
-
-    contains the subset of fields needed for Issuer to decode the instruction
-    and get register rdflags signals set up.  it also doubles up as the
-    "Trap" temporary store, because part of the Decoder's job is to
-    identify whether a trap / interrupt / exception should occur.
-    """
-
-    def __init__(self, name=None):
-
-        RecordObject.__init__(self, name=name)
-
-        # current "state" (TODO: this in its own Record)
-        self.msr = Signal(64, reset_less=True)
-        self.cia = Signal(64, reset_less=True)
-
-        # instruction, type and decoded information
-        self.insn = Signal(32, reset_less=True) # original instruction
-        self.insn_type = Signal(MicrOp, reset_less=True)
-        self.fn_unit = Signal(Function, reset_less=True)
-        self.lk = Signal(reset_less=True)
-        self.rc = Data(1, "rc")
-        self.oe = Data(1, "oe")
-        self.input_carry = Signal(CryIn, reset_less=True)
-        self.traptype  = Signal(TT.size, reset_less=True) # trap main_stage.py
-        self.ldst_exc  = LDSTException("exc")
-        self.trapaddr  = Signal(13, reset_less=True)
-        self.read_cr_whole = Data(8, "cr_rd") # CR full read mask
-        self.write_cr_whole = Data(8, "cr_wr") # CR full write mask
-        self.is_32bit = Signal(reset_less=True)
-
-
-class Decode2ToOperand(IssuerDecode2ToOperand):
-
-    def __init__(self, name=None):
-
-        IssuerDecode2ToOperand.__init__(self, name=name)
-
-        # instruction, type and decoded information
-        self.imm_data = Data(64, name="imm")
-        self.invert_in = Signal(reset_less=True)
-        self.zero_a = Signal(reset_less=True)
-        self.output_carry = Signal(reset_less=True)
-        self.input_cr = Signal(reset_less=True)  # instr. has a CR as input
-        self.output_cr = Signal(reset_less=True) # instr. has a CR as output
-        self.invert_out = Signal(reset_less=True)
-        self.is_32bit = Signal(reset_less=True)
-        self.is_signed = Signal(reset_less=True)
-        self.data_len = Signal(4, reset_less=True) # bytes
-        self.byte_reverse  = Signal(reset_less=True)
-        self.sign_extend  = Signal(reset_less=True)# do we need this?
-        self.ldst_mode  = Signal(LDSTMode, reset_less=True) # LD/ST mode
-        self.write_cr0 = Signal(reset_less=True)
-
-
-class Decode2ToExecute1Type(RecordObject):
-
-    def __init__(self, name=None, asmcode=True, opkls=None, do=None,
-                       regreduce_en=False):
-
-        if regreduce_en:
-            SPR = SPRreduced
-        else:
-            SPR = SPRfull
-
-        if do is None and opkls is None:
-            opkls = Decode2ToOperand
-
-        RecordObject.__init__(self, name=name)
-
-        if asmcode:
-            self.asmcode = Signal(8, reset_less=True) # only for simulator
-        self.write_reg = Data(7, name="rego")
-        self.write_ea = Data(7, name="ea") # for LD/ST in update mode
-        self.read_reg1 = Data(7, name="reg1")
-        self.read_reg2 = Data(7, name="reg2")
-        self.read_reg3 = Data(7, name="reg3")
-        self.write_spr = Data(SPR, name="spro")
-        self.read_spr1 = Data(SPR, name="spr1")
-        #self.read_spr2 = Data(SPR, name="spr2") # only one needed
-
-        self.xer_in = Signal(3, reset_less=True)   # xer might be read
-        self.xer_out = Signal(reset_less=True)  # xer might be written
-
-        self.read_fast1 = Data(3, name="fast1")
-        self.read_fast2 = Data(3, name="fast2")
-        self.write_fast1 = Data(3, name="fasto1")
-        self.write_fast2 = Data(3, name="fasto2")
-
-        self.read_cr1 = Data(7, name="cr_in1")
-        self.read_cr2 = Data(7, name="cr_in2")
-        self.read_cr3 = Data(7, name="cr_in2")
-        self.write_cr = Data(7, name="cr_out")
-
-        # decode operand data
-        print ("decode2execute init", name, opkls, do)
-        #assert name is not None, str(opkls)
-        if do is not None:
-            self.do = do
-        else:
-            self.do = opkls(name)
+from openpower.decoder.decode2execute1 import *
index eb6df3cf18cdd95bad47dc4918d4055780ec57cf..1ca6af06407dfbf8b26b7cea52e84878ae3a3dc7 100644 (file)
@@ -1,607 +1,5 @@
-"""Cascading Power ISA Decoder
+# moved to openpower-isa
+# https://git.libre-soc.org/?p=openpower-isa.git;a=summary
+# wildcard imports here ONLY to support migration
 
 
-License: LGPLv3+
-
-# Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
-# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
-
-This module uses CSV tables in a hierarchical/peer cascading fashion,
-to create a multi-level instruction decoder by recognising appropriate
-patterns.  The output is a wide, flattened (1-level) series of bitfields,
-suitable for a simple RISC engine.
-
-This is based on Anton Blanchard's excellent microwatt work:
-https://github.com/antonblanchard/microwatt/blob/master/decode1.vhdl
-
-The basic principle is that the python code does the heavy lifting
-(reading the CSV files, constructing the hierarchy), creating the HDL
-AST with for-loops generating switch-case statements.
-
-Where "normal" HDL would do this, in laborious excruciating detail:
-
-    switch (opcode & major_mask_bits):
-        case opcode_2: decode_opcode_2()
-        case opcode_19:
-                switch (opcode & minor_19_mask_bits)
-                    case minor_opcode_19_operation_X:
-                    case minor_opcode_19_operation_y:
-
-we take *full* advantage of the decoupling between python and the
-nmigen AST data structure, to do this:
-
-    with m.Switch(opcode & self.mask):
-        for case_bitmask in subcases:
-            with m.If(opcode & case_bitmask): {do_something}
-
-this includes specifying the information sufficient to perform subdecoding.
-
-create_pdecode()
-
-    the full hierarchical tree for decoding POWER9 is specified here
-    subsetting is possible by specifying col_subset (row_subset TODO)
-
-PowerDecoder
-
-    takes a *list* of CSV files with an associated bit-range that it
-    is requested to match against the "opcode" row of the CSV file.
-    This pattern can be either an integer, a binary number, *or* a
-    wildcard nmigen Case pattern of the form "001--1-100".
-
-Subdecoders
-
-    these are *additional* cases with further decoding.  The "pattern"
-    argument is specified as one of the Case statements (a peer of the
-    opcode row in the CSV file), and thus further fields of the opcode
-    may be decoded giving increasing levels of detail.
-
-Top Level:
-
-    [ (extra.csv: bit-fields entire 32-bit range
-        opcode                           -> matches
-        000000---------------01000000000 -> ILLEGAL instruction
-        01100000000000000000000000000000 -> SIM_CONFIG instruction
-        ................................ ->
-      ),
-      (major.csv: first 6 bits ONLY
-        opcode                           -> matches
-        001100                           -> ALU,OP_ADD (add)
-        001101                           -> ALU,OP_ADD (another type of add)
-        ......                           -> ...
-        ......                           -> ...
-        subdecoders:
-        001011 this must match *MAJOR*.CSV
-            [ (minor_19.csv: bits 21 through 30 inclusive:
-                opcode                  -> matches
-                0b0000000000            -> ALU,OP_MCRF
-                ............            -> ....
-              ),
-              (minor_19_00000.csv: bits 21 through 25 inclusive:
-                opcode                  -> matches
-                0b00010                 -> ALU,add_pcis
-              )
-            ]
-      ),
-    ]
-
-
-"""
-
-import gc
-from collections import namedtuple
-from nmigen import Module, Elaboratable, Signal, Cat, Mux
-from nmigen.cli import rtlil
-from soc.decoder.power_enums import (Function, Form, MicrOp,
-                                     In1Sel, In2Sel, In3Sel, OutSel,
-                                     SVEXTRA, SVEtype, SVPtype,  # Simple-V
-                                     RC, LdstLen, LDSTMode, CryIn,
-                                     single_bit_flags, CRInSel,
-                                     CROutSel, get_signal_name,
-                                     default_values, insns, asmidx)
-from soc.decoder.power_fields import DecodeFields
-from soc.decoder.power_fieldsn import SigDecode, SignalBitRange
-from soc.decoder.power_svp64 import SVP64RM
-
-# key data structure in which the POWER decoder is specified,
-# in a hierarchical fashion
-Subdecoder = namedtuple(  # fix autoformatter
-    "Subdecoder",
-    ["pattern",    # the major pattern to search for (e.g. major opcode)
-     "opcodes",    # a dictionary of minor patterns to find
-     "opint",      # true => the pattern must not be in "10----11" format
-     # the bits (as a range) against which "pattern" matches
-     "bitsel",
-     "suffix",     # shift the opcode down before decoding
-     "subdecoders"  # list of further subdecoders for *additional* matches,
-     # *ONLY* after "pattern" has *ALSO* been matched against.
-     ])
-
-power_op_types = {'function_unit': Function,
-                  'internal_op': MicrOp,
-                  'form': Form,
-                  'asmcode': 8,
-                  'SV_Etype': SVEtype,
-                  'SV_Ptype': SVPtype,
-                  'in1_sel': In1Sel,
-                  'in2_sel': In2Sel,
-                  'in3_sel': In3Sel,
-                  'out_sel': OutSel,
-                  'cr_in': CRInSel,
-                  'cr_out': CROutSel,
-                  'sv_in1': SVEXTRA,
-                  'sv_in2': SVEXTRA,
-                  'sv_in3': SVEXTRA,
-                  'sv_out': SVEXTRA,
-                  'sv_out2': SVEXTRA,
-                  'sv_cr_in': SVEXTRA,
-                  'sv_cr_out': SVEXTRA,
-                  'ldst_len': LdstLen,
-                  'upd': LDSTMode,
-                  'rc_sel': RC,
-                  'cry_in': CryIn
-                  }
-
-power_op_csvmap = {'function_unit': 'unit',
-                   'form': 'form',
-                   'internal_op': 'internal op',
-                   'in1_sel': 'in1',
-                   'in2_sel': 'in2',
-                   'in3_sel': 'in3',
-                   'out_sel': 'out',
-                   'sv_in1': 'sv_in1',
-                   'sv_in2': 'sv_in2',
-                   'sv_in3': 'sv_in3',
-                   'sv_out': 'sv_out',
-                   'sv_out2': 'sv_out2',
-                   'sv_cr_in': 'sv_cr_in',
-                   'sv_cr_out': 'sv_cr_out',
-                   'SV_Etype': 'SV_Etype',
-                   'SV_Ptype': 'SV_Ptype',
-                   'cr_in': 'CR in',
-                   'cr_out': 'CR out',
-                   'ldst_len': 'ldst len',
-                   'upd': 'upd',
-                   'rc_sel': 'rc',
-                   'cry_in': 'cry in',
-                   }
-
-
-def get_pname(field, pname):
-    if pname is None:
-        return field
-    return "%s_%s" % (pname, field)
-
-
-class PowerOp:
-    """PowerOp - a dynamic class that stores (subsets of) CSV rows of data
-    about a PowerISA instruction.  this is a "micro-code" expanded format
-    which generates an awful lot of wires, hence the subsetting
-    """
-
-    def __init__(self, incl_asm=True, name=None, subset=None):
-        self.subset = subset
-        debug_report = set()
-        fields = set()
-        for field, ptype in power_op_types.items():
-            fields.add(field)
-            if subset and field not in subset:
-                continue
-            fname = get_pname(field, name)
-            setattr(self, field, Signal(ptype, reset_less=True, name=fname))
-            debug_report.add(field)
-        for bit in single_bit_flags:
-            field = get_signal_name(bit)
-            fields.add(field)
-            if subset and field not in subset:
-                continue
-            debug_report.add(field)
-            fname = get_pname(field, name)
-            setattr(self, field, Signal(reset_less=True, name=fname))
-        print("PowerOp debug", name, debug_report)
-        print("        fields", fields)
-
-    def _eq(self, row=None):
-        if row is None:
-            row = default_values
-        # TODO: this conversion process from a dict to an object
-        # should really be done using e.g. namedtuple and then
-        # call eq not _eq
-        if False:  # debugging
-            if row['CR in'] == '1':
-                import pdb
-                pdb.set_trace()
-                print(row)
-            if row['CR out'] == '0':
-                import pdb
-                pdb.set_trace()
-                print(row)
-            print(row)
-        ldst_mode = row['upd']
-        if ldst_mode.isdigit():
-            row['upd'] = int(ldst_mode)
-        res = []
-        for field, ptype in power_op_types.items():
-            if not hasattr(self, field):
-                continue
-            if field not in power_op_csvmap:
-                continue
-            csvname = power_op_csvmap[field]
-            print(field, ptype, csvname, row)
-            val = row[csvname]
-            if csvname == 'upd' and isinstance(val, int):  # LDSTMode different
-                val = ptype(val)
-            else:
-                val = ptype[val]
-            res.append(getattr(self, field).eq(val))
-        if False:
-            print(row.keys())
-        asmcode = row['comment']
-        if hasattr(self, "asmcode") and asmcode in asmidx:
-            res.append(self.asmcode.eq(asmidx[asmcode]))
-        for bit in single_bit_flags:
-            field = get_signal_name(bit)
-            if not hasattr(self, field):
-                continue
-            sig = getattr(self, field)
-            res.append(sig.eq(int(row.get(bit, 0))))
-        return res
-
-    def _get_eq(self, res, field, otherop):
-        copyfrom = getattr(otherop, field, None)
-        copyto = getattr(self, field, None)
-        if copyfrom is not None and copyto is not None:
-            res.append(copyto.eq(copyfrom))
-
-    def eq(self, otherop):
-        res = []
-        for field in power_op_types.keys():
-            self._get_eq(res, field, otherop)
-        for bit in single_bit_flags:
-            self._get_eq(res, get_signal_name(bit), otherop)
-        return res
-
-    def ports(self):
-        res = []
-        for field in power_op_types.keys():
-            if hasattr(self, field):
-                res.append(getattr(self, field))
-        if hasattr(self, "asmcode"):
-            res.append(self.asmcode)
-        for field in single_bit_flags:
-            field = get_signal_name(field)
-            if hasattr(self, field):
-                res.append(getattr(self, field))
-        return res
-
-
-class PowerDecoder(Elaboratable):
-    """PowerDecoder - decodes an incoming opcode into the type of operation
-
-    this is a recursive algorithm, creating Switch statements that can
-    have further match-and-decode on other parts of the opcode field before
-    finally landing at a "this CSV entry details gets returned" thing.
-
-    the complicating factor is the row and col subsetting.  column subsetting
-    dynamically chooses only the CSV columns requested, whilst row subsetting
-    allows a function to be called on the row to determine if the Case
-    statement is to be generated for that row.  this not only generates
-    completely different Decoders, it also means that some sub-decoders
-    will turn up blank (empty switch statements).  if that happens we do
-    not want the parent to include a Mux for an entirely blank switch statement
-    so we have to store the switch/case statements in a tree, and
-    post-analyse it.
-
-    the reason for the tree is because elaborate can only be called *after*
-    the constructor is called.  all quite messy.
-    """
-
-    def __init__(self, width, dec, name=None, col_subset=None, row_subset=None):
-        self.actually_does_something = False
-        self.pname = name
-        self.col_subset = col_subset
-        self.row_subsetfn = row_subset
-        if not isinstance(dec, list):
-            dec = [dec]
-        self.dec = dec
-        self.opcode_in = Signal(width, reset_less=True)
-
-        self.op = PowerOp(name=name, subset=col_subset)
-        for d in dec:
-            if d.suffix is not None and d.suffix >= width:
-                d.suffix = None
-        self.width = width
-
-    def suffix_mask(self, d):
-        return ((1 << d.suffix) - 1)
-
-    def divide_opcodes(self, d):
-        divided = {}
-        mask = self.suffix_mask(d)
-        print("mask", hex(mask))
-        for row in d.opcodes:
-            opcode = row['opcode']
-            if d.opint and '-' not in opcode:
-                opcode = int(opcode, 0)
-            key = opcode & mask
-            opcode = opcode >> d.suffix
-            if key not in divided:
-                divided[key] = []
-            r = row.copy()
-            r['opcode'] = opcode
-            divided[key].append(r)
-        return divided
-
-    def tree_analyse(self):
-        self.decs = decs = []
-        self.submodules = submodules = {}
-        self.eqs = eqs = []
-
-        # go through the list of CSV decoders first
-        for d in self.dec:
-            cases = []
-            opcode_switch = Signal(d.bitsel[1] - d.bitsel[0],
-                                   reset_less=True)
-            eq = []
-            case_does_something = False
-            eq.append(opcode_switch.eq(
-                self.opcode_in[d.bitsel[0]:d.bitsel[1]]))
-            if d.suffix:
-                opcodes = self.divide_opcodes(d)
-                opc_in = Signal(d.suffix, reset_less=True)
-                eq.append(opc_in.eq(opcode_switch[:d.suffix]))
-                # begin the dynamic Switch statement here
-                switch_case = {}
-                cases.append([opc_in, switch_case])
-                sub_eqs = []
-                for key, row in opcodes.items():
-                    bitsel = (d.suffix+d.bitsel[0], d.bitsel[1])
-                    sd = Subdecoder(pattern=None, opcodes=row,
-                                    bitsel=bitsel, suffix=None,
-                                    opint=False, subdecoders=[])
-                    mname = get_pname("dec_sub%d" % key, self.pname)
-                    subdecoder = PowerDecoder(width=32, dec=sd,
-                                              name=mname,
-                                              col_subset=self.col_subset,
-                                              row_subset=self.row_subsetfn)
-                    if not subdecoder.tree_analyse():
-                        del subdecoder
-                        continue
-                    submodules[mname] = subdecoder
-                    sub_eqs.append(subdecoder.opcode_in.eq(self.opcode_in))
-                    # add in the dynamic Case statement here
-                    switch_case[key] = self.op.eq(subdecoder.op)
-                    self.actually_does_something = True
-                    case_does_something = True
-                if case_does_something:
-                    eq += sub_eqs
-            else:
-                # TODO: arguments, here (all of them) need to be a list.
-                # a for-loop around the *list* of decoder args.
-                switch_case = {}
-                cases.append([opcode_switch, switch_case])
-                seqs = self.handle_subdecoders(switch_case, submodules, d)
-                if seqs:
-                    case_does_something = True
-                eq += seqs
-                for row in d.opcodes:
-                    opcode = row['opcode']
-                    if d.opint and '-' not in opcode:
-                        opcode = int(opcode, 0)
-                    if not row['unit']:
-                        continue
-                    if self.row_subsetfn:
-                        if not self.row_subsetfn(opcode, row):
-                            continue
-                    # add in the dynamic Case statement here
-                    switch_case[opcode] = self.op._eq(row)
-                    self.actually_does_something = True
-                    case_does_something = True
-
-            if cases:
-                decs.append(cases)
-            if case_does_something:
-                eqs += eq
-                print("submodule eqs", self.pname, eq)
-
-        print("submodules", self.pname, submodules)
-
-        gc.collect()
-        return self.actually_does_something
-
-    def handle_subdecoders(self, switch_case, submodules, d):
-        eqs = []
-        for dec in d.subdecoders:
-            if isinstance(dec, list):  # XXX HACK: take first pattern
-                dec = dec[0]
-            print("subdec", dec.pattern, self.pname)
-            mname = get_pname("dec%d" % dec.pattern, self.pname)
-            subdecoder = PowerDecoder(self.width, dec,
-                                      name=mname,
-                                      col_subset=self.col_subset,
-                                      row_subset=self.row_subsetfn)
-            if not subdecoder.tree_analyse():  # doesn't do anything
-                del subdecoder
-                continue                      # skip
-            submodules[mname] = subdecoder
-            eqs.append(subdecoder.opcode_in.eq(self.opcode_in))
-            switch_case[dec.pattern] = self.op.eq(subdecoder.op)
-            self.actually_does_something = True
-
-        return eqs
-
-    def elaborate(self, platform):
-        print("decoder elaborate", self.pname, self.submodules)
-        m = Module()
-        comb = m.d.comb
-
-        comb += self.eqs
-
-        for mname, subdecoder in self.submodules.items():
-            setattr(m.submodules, mname, subdecoder)
-
-        for switch_case in self.decs:
-            for (switch, cases) in switch_case:
-                with m.Switch(switch):
-                    for key, eqs in cases.items():
-                        with m.Case(key):
-                            comb += eqs
-        return m
-
-    def ports(self):
-        return [self.opcode_in] + self.op.ports()
-
-
-class TopPowerDecoder(PowerDecoder):
-    """TopPowerDecoder
-
-    top-level hierarchical decoder for POWER ISA
-    bigendian dynamically switches between big and little endian decoding
-    (reverses byte order).  See V3.0B p44 1.11.2
-    """
-
-    def __init__(self, width, dec, name=None, col_subset=None, row_subset=None):
-        PowerDecoder.__init__(self, width, dec, name, col_subset, row_subset)
-        self.fields = df = DecodeFields(SignalBitRange, [self.opcode_in])
-        self.fields.create_specs()
-        self.raw_opcode_in = Signal.like(self.opcode_in, reset_less=True)
-        self.bigendian = Signal(reset_less=True)
-
-        for fname, value in self.fields.common_fields.items():
-            signame = get_pname(fname, name)
-            sig = Signal(value[0:-1].shape(), reset_less=True, name=signame)
-            setattr(self, fname, sig)
-
-        # create signals for all field forms
-        forms = self.form_names
-        self.sigforms = {}
-        for form in forms:
-            fields = self.fields.instrs[form]
-            fk = fields.keys()
-            Fields = namedtuple("Fields", fk)
-            sf = {}
-            for k, value in fields.items():
-                fname = "%s_%s" % (form, k)
-                sig = Signal(value[0:-1].shape(), reset_less=True, name=fname)
-                sf[k] = sig
-            instr = Fields(**sf)
-            setattr(self, "Form%s" % form, instr)
-            self.sigforms[form] = instr
-
-        self.tree_analyse()
-
-    @property
-    def form_names(self):
-        return self.fields.instrs.keys()
-
-    def elaborate(self, platform):
-        m = PowerDecoder.elaborate(self, platform)
-        comb = m.d.comb
-        # sigh duplicated in SVP64PowerDecoder
-        # raw opcode in assumed to be in LE order: byte-reverse it to get BE
-        raw_le = self.raw_opcode_in
-        l = []
-        for i in range(0, self.width, 8):
-            l.append(raw_le[i:i+8])
-        l.reverse()
-        raw_be = Cat(*l)
-        comb += self.opcode_in.eq(Mux(self.bigendian, raw_be, raw_le))
-
-        # add all signal from commonly-used fields
-        for fname, value in self.fields.common_fields.items():
-            sig = getattr(self, fname)
-            comb += sig.eq(value[0:-1])
-
-        # link signals for all field forms
-        forms = self.form_names
-        for form in forms:
-            sf = self.sigforms[form]
-            fields = self.fields.instrs[form]
-            for k, value in fields.items():
-                sig = getattr(sf, k)
-                comb += sig.eq(value[0:-1])
-
-        return m
-
-    def ports(self):
-        return [self.raw_opcode_in, self.bigendian] + PowerDecoder.ports(self)
-
-
-####################################################
-# PRIMARY FUNCTION SPECIFYING THE FULL POWER DECODER
-
-def create_pdecode(name=None, col_subset=None, row_subset=None):
-    """create_pdecode - creates a cascading hierarchical POWER ISA decoder
-
-    subsetting of the PowerOp decoding is possible by setting col_subset
-    """
-
-    # some alteration to the CSV files is required for SV so we use
-    # a class to do it
-    isa = SVP64RM()
-    get_csv = isa.get_svp64_csv
-
-    # minor 19 has extra patterns
-    m19 = []
-    m19.append(Subdecoder(pattern=19, opcodes=get_csv("minor_19.csv"),
-                          opint=True, bitsel=(1, 11), suffix=None,
-                          subdecoders=[]))
-    m19.append(Subdecoder(pattern=19, opcodes=get_csv("minor_19_00000.csv"),
-                          opint=True, bitsel=(1, 6), suffix=None,
-                          subdecoders=[]))
-
-    # minor opcodes.
-    pminor = [
-        m19,
-        Subdecoder(pattern=30, opcodes=get_csv("minor_30.csv"),
-                   opint=True, bitsel=(1, 5), suffix=None, subdecoders=[]),
-        Subdecoder(pattern=31, opcodes=get_csv("minor_31.csv"),
-                   opint=True, bitsel=(1, 11), suffix=0b00101, subdecoders=[]),
-        Subdecoder(pattern=58, opcodes=get_csv("minor_58.csv"),
-                   opint=True, bitsel=(0, 2), suffix=None, subdecoders=[]),
-        Subdecoder(pattern=62, opcodes=get_csv("minor_62.csv"),
-                   opint=True, bitsel=(0, 2), suffix=None, subdecoders=[]),
-        Subdecoder(pattern=22, opcodes=get_csv("minor_22.csv"),
-                   opint=True, bitsel=(1, 5), suffix=None, subdecoders=[]),
-    ]
-
-    # top level: extra merged with major
-    dec = []
-    opcodes = get_csv("major.csv")
-    dec.append(Subdecoder(pattern=None, opint=True, opcodes=opcodes,
-                          bitsel=(26, 32), suffix=None, subdecoders=pminor))
-    opcodes = get_csv("extra.csv")
-    dec.append(Subdecoder(pattern=None, opint=False, opcodes=opcodes,
-                          bitsel=(0, 32), suffix=None, subdecoders=[]))
-
-    return TopPowerDecoder(32, dec, name=name, col_subset=col_subset,
-                           row_subset=row_subset)
-
-
-if __name__ == '__main__':
-
-    if True:
-        # row subset
-
-        def rowsubsetfn(opcode, row):
-            print("row_subset", opcode, row)
-            return row['unit'] == 'ALU'
-
-        pdecode = create_pdecode(name="rowsub",
-                                 col_subset={'function_unit', 'in1_sel'},
-                                 row_subset=rowsubsetfn)
-        vl = rtlil.convert(pdecode, ports=pdecode.ports())
-        with open("row_subset_decoder.il", "w") as f:
-            f.write(vl)
-
-        # col subset
-
-        pdecode = create_pdecode(name="fusubset", col_subset={'function_unit'})
-        vl = rtlil.convert(pdecode, ports=pdecode.ports())
-        with open("col_subset_decoder.il", "w") as f:
-            f.write(vl)
-
-    # full decoder
-
-    pdecode = create_pdecode()
-    vl = rtlil.convert(pdecode, ports=pdecode.ports())
-    with open("decoder.il", "w") as f:
-        f.write(vl)
+from openpower.decoder.power_decoder import *
index d0fe85cbce4a83f5f12d424b6e1ed78872e97f2c..6a0f70c7019ef52d4de560f47b2e980b737ae381 100644 (file)
@@ -1,255 +1,5 @@
-from collections import OrderedDict, namedtuple
-from soc.decoder.power_enums import find_wiki_file
+# moved to openpower-isa
+# https://git.libre-soc.org/?p=openpower-isa.git;a=summary
+# wildcard imports here ONLY to support migration
 
 
-
-class BitRange(OrderedDict):
-    """BitRange: remaps from straight indices (0,1,2..) to bit numbers
-    """
-
-    def __getitem__(self, subscript):
-        if isinstance(subscript, slice):
-            return list(self.values())[subscript]
-        else:
-            return OrderedDict.__getitem__(self, subscript)
-
-
-def decode_instructions(form):
-    res = {}
-    accum = []
-    for l in form:
-        if l.strip().startswith("Formats"):
-            l = l.strip().split(":")[-1]
-            l = l.replace(" ", "")
-            l = l.split(",")
-            for fmt in l:
-                if fmt not in res:
-                    res[fmt] = [accum[0]]
-                else:
-                    res[fmt].append(accum[0])
-            accum = []
-        else:
-            accum.append(l.strip())
-    return res
-
-
-def decode_form_header(hdr):
-    res = {}
-    count = 0
-    hdr = hdr.strip()
-    for f in hdr.split("|"):
-        if not f:
-            continue
-        if f[0].isdigit():
-            idx = int(f.strip().split(' ')[0])
-            res[count] = idx
-        count += len(f) + 1
-    return res
-
-
-def find_unique(d, key):
-    if key not in d:
-        return key
-    idx = 1
-    while "%s_%d" % (key, idx) in d:
-        idx += 1
-    return "%s_%d" % (key, idx)
-
-
-def decode_line(header, line):
-    line = line.strip()
-    res = {}
-    count = 0
-    prev_fieldname = None
-    for f in line.split("|"):
-        if not f:
-            continue
-        end = count + len(f) + 1
-        fieldname = f.strip()
-        if not fieldname or fieldname.startswith('/'):
-            if prev_fieldname is not None:
-                res[prev_fieldname] = (res[prev_fieldname], header[count])
-                prev_fieldname = None
-            count = end
-            continue
-        bitstart = header[count]
-        if prev_fieldname is not None:
-            res[prev_fieldname] = (res[prev_fieldname], bitstart)
-        res[fieldname] = bitstart
-        count = end
-        prev_fieldname = fieldname
-    res[prev_fieldname] = (bitstart, 32)
-    return res
-
-
-def decode_form(form):
-    header = decode_form_header(form[0])
-    res = []
-    for line in form[1:]:
-        dec = decode_line(header, line)
-        if dec:
-            res.append(dec)
-    fields = {}
-    falternate = {}
-    for l in res:
-        for k, (start, end) in l.items():
-            if k in fields:
-                if (start, end) == fields[k]:
-                    continue  # already in and matching for this Form
-                if k in falternate:
-                    alternate = "%s_%d" % (k, falternate[k])
-                    if (start, end) == fields[alternate]:
-                        continue
-                falternate[k] = fidx = falternate.get(k, 0) + 1
-                fields["%s_%d" % (k, fidx)] = (start, end)
-            else:
-                fields[k] = (start, end)
-    return fields
-
-
-class DecodeFields:
-
-    def __init__(self, bitkls=BitRange, bitargs=(), fname=None,
-                 name_on_wiki=None):
-        self.bitkls = bitkls
-        self.bitargs = bitargs
-        if fname is None:
-            assert name_on_wiki is None
-            fname = "fields.txt"
-            name_on_wiki = "fields.text"
-        self.fname = find_wiki_file(name_on_wiki)
-
-    @property
-    def form_names(self):
-        return self.instrs.keys()
-
-    def create_specs(self):
-        self.forms, self.instrs = self.decode_fields()
-        forms = self.form_names
-        #print ("specs", self.forms, forms)
-        for form in forms:
-            fields = self.instrs[form]
-            fk = fields.keys()
-            Fields = namedtuple("Fields", fk)
-            instr = Fields(**fields)
-            setattr(self, "Form%s" % form, instr)
-        # now add in some commonly-used fields (should be done automatically)
-        # note that these should only be ones which are the same on all Forms
-        # note: these are from microwatt insn_helpers.vhdl
-        self.common_fields = {
-            "PO": self.Formall.PO,
-            "RS": self.FormX.RS,
-            "RT": self.FormX.RT,
-            "RA": self.FormX.RA,
-            "RB": self.FormX.RB,
-            "SI": self.FormD.SI,
-            "UI": self.FormD.UI,
-            "L": self.FormD.L,
-            "SH32": self.FormM.SH,
-            "sh": self.FormMD.sh,
-            "MB32": self.FormM.MB,
-            "ME32": self.FormM.ME,
-            "LI": self.FormI.LI,
-            "LK": self.FormI.LK,
-            "AA": self.FormB.AA,
-            "Rc": self.FormX.Rc,
-            "OE": self.FormXO.OE,
-            "BD": self.FormB.BD,
-            "BF": self.FormX.BF,
-            "CR": self.FormXL.XO,
-            "BB": self.FormXL.BB,
-            "BA": self.FormXL.BA,
-            "BT": self.FormXL.BT,
-            "FXM": self.FormXFX.FXM,
-            "BO": self.FormXL.BO,
-            "BI": self.FormXL.BI,
-            "BH": self.FormXL.BH,
-            "D": self.FormD.D,
-            "DS": self.FormDS.DS,
-            "TO": self.FormX.TO,
-            "BC": self.FormA.BC,
-            "SH": self.FormX.SH,
-            "ME": self.FormM.ME,
-            "MB": self.FormM.MB,
-            "SPR": self.FormXFX.SPR}
-        for k, v in self.common_fields.items():
-            setattr(self, k, v)
-
-    def decode_fields(self):
-        with open(self.fname) as f:
-            txt = f.readlines()
-        #print ("decode", txt)
-        forms = {}
-        reading_data = False
-        for l in txt:
-            l = l.strip()
-            if len(l) == 0:
-                continue
-            if reading_data:
-                if l[0] == '#':
-                    reading_data = False
-                else:
-                    forms[heading].append(l)
-            if not reading_data:
-                assert l[0] == '#'
-                heading = l[1:].strip()
-                # if heading.startswith('1.6.28'): # skip instr fields for now
-                #     break
-                heading = heading.split(' ')[-1]
-                reading_data = True
-                forms[heading] = []
-
-        res = {}
-        inst = {}
-
-        for hdr, form in forms.items():
-            if heading == 'Fields':
-                i = decode_instructions(form)
-                for form, field in i.items():
-                    inst[form] = self.decode_instruction_fields(field)
-            # else:
-            #     res[hdr] = decode_form(form)
-        return res, inst
-
-    def decode_instruction_fields(self, fields):
-        res = {}
-        for field in fields:
-            f, spec = field.strip().split(" ")
-            ss = spec[1:-1].split(",")
-            fs = f.split(",")
-            if len(fs) > 1:
-                individualfields = []
-                for f0, s0 in zip(fs, ss):
-                    txt = "%s (%s)" % (f0, s0)
-                    individualfields.append(txt)
-                if len(fs) > 1:
-                    res.update(self.decode_instruction_fields(
-                        individualfields))
-            d = self.bitkls(*self.bitargs)
-            idx = 0
-            for s in ss:
-                s = s.split(':')
-                if len(s) == 1:
-                    d[idx] = int(s[0])
-                    idx += 1
-                else:
-                    start = int(s[0])
-                    end = int(s[1])
-                    while start <= end:
-                        d[idx] = start
-                        idx += 1
-                        start += 1
-            f = f.replace(",", "_")
-            unique = find_unique(res, f)
-            res[unique] = d
-
-        return res
-
-
-if __name__ == '__main__':
-    dec = DecodeFields()
-    dec.create_specs()
-    forms, instrs = dec.forms, dec.instrs
-    for form, fields in instrs.items():
-        print("Form", form)
-        for field, bits in fields.items():
-            print("\tfield", field, bits)
+from openpower.decoder.power_fields import *
index 852dd15b079cc88a1b555f71d216107ce2d9c7a1..243bda894687eafea7d468f1ac00222e571da689 100644 (file)
@@ -1,79 +1,5 @@
-from collections import OrderedDict
-from soc.decoder.power_fields import DecodeFields, BitRange
-from nmigen import Module, Elaboratable, Signal, Cat
-from nmigen.cli import rtlil
-from copy import deepcopy
+# moved to openpower-isa
+# https://git.libre-soc.org/?p=openpower-isa.git;a=summary
+# wildcard imports here ONLY to support migration
 
 
-
-class SignalBitRange(BitRange):
-    def __init__(self, signal):
-        BitRange.__init__(self)
-        self.signal = signal
-
-    def __deepcopy__(self, memo):
-        signal = deepcopy(self.signal, memo)
-        retval = SignalBitRange(signal=signal)
-        for k, v in self.items():
-            k = deepcopy(k, memo)
-            v = deepcopy(v, memo)
-            retval[k] = v
-        return retval
-
-    def _rev(self, k):
-        width = self.signal.width
-        return width-1-k
-
-    def __getitem__(self, subs):
-        # *sigh* field numberings are bit-inverted.  PowerISA 3.0B section 1.3.2
-        if isinstance(subs, slice):
-            res = []
-            start, stop, step = subs.start, subs.stop, subs.step
-            if step is None:
-                step = 1
-            if start is None:
-                start = 0
-            if stop is None:
-                stop = -1
-            if start < 0:
-                start = len(self) + start + 1
-            if stop < 0:
-                stop = len(self) + stop + 1
-            for t in range(start, stop, step):
-                t = len(self) - 1 - t  # invert field back
-                k = OrderedDict.__getitem__(self, t)
-                res.append(self.signal[self._rev(k)])  # reverse-order here
-            return Cat(*res)
-        else:
-            if subs < 0:
-                subs = len(self) + subs
-            subs = len(self) - 1 - subs  # invert field back
-            k = OrderedDict.__getitem__(self, subs)
-            return self.signal[self._rev(k)]  # reverse-order here
-
-
-class SigDecode(Elaboratable):
-
-    def __init__(self, width):
-        self.opcode_in = Signal(width, reset_less=False)
-        self.df = DecodeFields(SignalBitRange, [self.opcode_in])
-        self.df.create_specs()
-
-    def elaborate(self, platform):
-        m = Module()
-        comb = m.d.comb
-        return m
-
-    def ports(self):
-        return [self.opcode_in]
-
-
-def create_sigdecode():
-    s = SigDecode(32)
-    return s
-
-
-if __name__ == '__main__':
-    sigdecode = create_sigdecode()
-    vl = rtlil.convert(sigdecode, ports=sigdecode.ports())
-    with open("decoder.il", "w") as f:
-        f.write(vl)
+from openpower.decoder.power_fieldsn import *
index 152764ca08758f3922e991da1b400cee6e47c853..99cf5f2cf636550160f7065faf6cff2cc469b51e 100644 (file)
@@ -1,560 +1,5 @@
-import unittest
-from copy import copy
-from soc.decoder.power_fields import BitRange
-from operator import (add, sub, mul, floordiv, truediv, mod, or_, and_, xor,
-                      neg, inv, lshift, rshift)
+# moved to openpower-isa
+# https://git.libre-soc.org/?p=openpower-isa.git;a=summary
+# wildcard imports here ONLY to support migration
 
 
-
-def check_extsign(a, b):
-    if isinstance(b, FieldSelectableInt):
-        b = b.get_range()
-    if isinstance(b, int):
-        return SelectableInt(b, a.bits)
-    if b.bits != 256:
-        return b
-    return SelectableInt(b.value, a.bits)
-
-
-class FieldSelectableInt:
-    """FieldSelectableInt: allows bit-range selection onto another target
-    """
-
-    def __init__(self, si, br):
-        self.si = si  # target selectable int
-        if isinstance(br, list) or isinstance(br, tuple):
-            _br = BitRange()
-            for i, v in enumerate(br):
-                _br[i] = v
-            br = _br
-        self.br = br  # map of indices.
-
-    def eq(self, b):
-        if isinstance(b, SelectableInt):
-            for i in range(b.bits):
-                self[i] = b[i]
-        else:
-            self.si = copy(b.si)
-            self.br = copy(b.br)
-
-    def _op(self, op, b):
-        vi = self.get_range()
-        vi = op(vi, b)
-        return self.merge(vi)
-
-    def _op1(self, op):
-        vi = self.get_range()
-        vi = op(vi)
-        return self.merge(vi)
-
-    def __getitem__(self, key):
-        print("getitem", key, self.br)
-        if isinstance(key, SelectableInt):
-            key = key.value
-        if isinstance(key, int):
-            key = self.br[key]  # don't do POWER 1.3.4 bit-inversion
-            return self.si[key]
-        if isinstance(key, slice):
-            key = self.br[key]
-            return selectconcat(*[self.si[x] for x in key])
-
-    def __setitem__(self, key, value):
-        if isinstance(key, SelectableInt):
-            key = key.value
-        key = self.br[key]  # don't do POWER 1.3.4 bit-inversion
-        if isinstance(key, int):
-            return self.si.__setitem__(key, value)
-        else:
-            if not isinstance(value, SelectableInt):
-                value = SelectableInt(value, bits=len(key))
-            for i, k in enumerate(key):
-                self.si[k] = value[i]
-
-    def __negate__(self):
-        return self._op1(negate)
-
-    def __invert__(self):
-        return self._op1(inv)
-
-    def __add__(self, b):
-        return self._op(add, b)
-
-    def __sub__(self, b):
-        return self._op(sub, b)
-
-    def __mul__(self, b):
-        return self._op(mul, b)
-
-    def __div__(self, b):
-        return self._op(truediv, b)
-
-    def __mod__(self, b):
-        return self._op(mod, b)
-
-    def __and__(self, b):
-        return self._op(and_, b)
-
-    def __or__(self, b):
-        return self._op(or_, b)
-
-    def __xor__(self, b):
-        return self._op(xor, b)
-
-    def get_range(self):
-        vi = SelectableInt(0, len(self.br))
-        for k, v in self.br.items():
-            vi[k] = self.si[v]
-        return vi
-
-    def merge(self, vi):
-        fi = copy(self)
-        for i, v in fi.br.items():
-            fi.si[v] = vi[i]
-        return fi
-
-    def __repr__(self):
-        return "FieldSelectableInt(si=%s, br=%s)" % (self.si, self.br)
-
-    def asint(self, msb0=False):
-        res = 0
-        brlen = len(self.br)
-        for i, key in self.br.items():
-            bit = self.si[key].value
-            #print("asint", i, key, bit)
-            res |= bit << ((brlen-i-1) if msb0 else i)
-        return res
-
-
-class FieldSelectableIntTestCase(unittest.TestCase):
-    def test_arith(self):
-        a = SelectableInt(0b10101, 5)
-        b = SelectableInt(0b011, 3)
-        br = BitRange()
-        br[0] = 0
-        br[1] = 2
-        br[2] = 3
-        fs = FieldSelectableInt(a, br)
-        c = fs + b
-        print(c)
-        #self.assertEqual(c.value, a.value + b.value)
-
-    def test_select(self):
-        a = SelectableInt(0b00001111, 8)
-        br = BitRange()
-        br[0] = 0
-        br[1] = 1
-        br[2] = 4
-        br[3] = 5
-        fs = FieldSelectableInt(a, br)
-
-        self.assertEqual(fs.get_range(), 0b0011)
-
-    def test_select_range(self):
-        a = SelectableInt(0b00001111, 8)
-        br = BitRange()
-        br[0] = 0
-        br[1] = 1
-        br[2] = 4
-        br[3] = 5
-        fs = FieldSelectableInt(a, br)
-
-        self.assertEqual(fs[2:4], 0b11)
-
-        fs[0:2] = 0b10
-        self.assertEqual(fs.get_range(), 0b1011)
-
-class SelectableInt:
-    """SelectableInt - a class that behaves exactly like python int
-
-    this class is designed to mirror precisely the behaviour of python int.
-    the only difference is that it must contain the context of the bitwidth
-    (number of bits) associated with that integer.
-
-    FieldSelectableInt can then operate on partial bits, and because there
-    is a bit width associated with SelectableInt, slices operate correctly
-    including negative start/end points.
-    """
-
-    def __init__(self, value, bits):
-        if isinstance(value, SelectableInt):
-            value = value.value
-        mask = (1 << bits) - 1
-        self.value = value & mask
-        self.bits = bits
-        self.overflow = (value & ~mask) != 0
-
-    def eq(self, b):
-        self.value = b.value
-        self.bits = b.bits
-
-    def to_signed_int(self):
-        print ("to signed?", self.value & (1<<(self.bits-1)), self.value)
-        if self.value & (1<<(self.bits-1)) != 0: # negative
-            res = self.value - (1<<self.bits)
-            print ("    val -ve:", self.bits, res)
-        else:
-            res = self.value
-            print ("    val +ve:", res)
-        return res
-
-    def _op(self, op, b):
-        if isinstance(b, int):
-            b = SelectableInt(b, self.bits)
-        b = check_extsign(self, b)
-        assert b.bits == self.bits
-        return SelectableInt(op(self.value, b.value), self.bits)
-
-    def __add__(self, b):
-        return self._op(add, b)
-
-    def __sub__(self, b):
-        return self._op(sub, b)
-
-    def __mul__(self, b):
-        # different case: mul result needs to fit the total bitsize
-        if isinstance(b, int):
-            b = SelectableInt(b, self.bits)
-        print("SelectableInt mul", hex(self.value), hex(b.value),
-              self.bits, b.bits)
-        return SelectableInt(self.value * b.value, self.bits + b.bits)
-
-    def __floordiv__(self, b):
-        return self._op(floordiv, b)
-
-    def __truediv__(self, b):
-        return self._op(truediv, b)
-
-    def __mod__(self, b):
-        return self._op(mod, b)
-
-    def __and__(self, b):
-        return self._op(and_, b)
-
-    def __or__(self, b):
-        return self._op(or_, b)
-
-    def __xor__(self, b):
-        return self._op(xor, b)
-
-    def __abs__(self):
-        print("abs", self.value & (1 << (self.bits-1)))
-        if self.value & (1 << (self.bits-1)) != 0:
-            return -self
-        return self
-
-    def __rsub__(self, b):
-        if isinstance(b, int):
-            b = SelectableInt(b, self.bits)
-        b = check_extsign(self, b)
-        assert b.bits == self.bits
-        return SelectableInt(b.value - self.value, self.bits)
-
-    def __radd__(self, b):
-        if isinstance(b, int):
-            b = SelectableInt(b, self.bits)
-        b = check_extsign(self, b)
-        assert b.bits == self.bits
-        return SelectableInt(b.value + self.value, self.bits)
-
-    def __rxor__(self, b):
-        b = check_extsign(self, b)
-        assert b.bits == self.bits
-        return SelectableInt(self.value ^ b.value, self.bits)
-
-    def __invert__(self):
-        return SelectableInt(~self.value, self.bits)
-
-    def __neg__(self):
-        res = SelectableInt((~self.value) + 1, self.bits)
-        print ("neg", hex(self.value), hex(res.value))
-        return res
-
-    def __lshift__(self, b):
-        b = check_extsign(self, b)
-        return SelectableInt(self.value << b.value, self.bits)
-
-    def __rshift__(self, b):
-        b = check_extsign(self, b)
-        return SelectableInt(self.value >> b.value, self.bits)
-
-    def __getitem__(self, key):
-        if isinstance(key, SelectableInt):
-            key = key.value
-        if isinstance(key, int):
-            assert key < self.bits, "key %d accessing %d" % (key, self.bits)
-            assert key >= 0
-            # NOTE: POWER 3.0B annotation order!  see p4 1.3.2
-            # MSB is indexed **LOWEST** (sigh)
-            key = self.bits - (key + 1)
-
-            value = (self.value >> key) & 1
-            print("getitem", key, self.bits, hex(self.value), value)
-            return SelectableInt(value, 1)
-        elif isinstance(key, slice):
-            assert key.step is None or key.step == 1
-            assert key.start < key.stop
-            assert key.start >= 0
-            assert key.stop <= self.bits
-
-            stop = self.bits - key.start
-            start = self.bits - key.stop
-
-            bits = stop - start
-            #print ("__getitem__ slice num bits", start, stop, bits)
-            mask = (1 << bits) - 1
-            value = (self.value >> start) & mask
-            print("getitem", stop, start, self.bits, hex(self.value), value)
-            return SelectableInt(value, bits)
-
-    def __setitem__(self, key, value):
-        if isinstance(key, SelectableInt):
-            key = key.value
-        print("setitem", key, self.bits, hex(self.value))
-        if isinstance(key, int):
-            assert key < self.bits
-            assert key >= 0
-            key = self.bits - (key + 1)
-            if isinstance(value, SelectableInt):
-                assert value.bits == 1
-                value = value.value
-
-            value = value << key
-            mask = 1 << key
-            self.value = (self.value & ~mask) | (value & mask)
-        elif isinstance(key, slice):
-            assert key.step is None or key.step == 1
-            assert key.start < key.stop
-            assert key.start >= 0
-            assert key.stop <= self.bits
-
-            stop = self.bits - key.start
-            start = self.bits - key.stop
-
-            bits = stop - start
-            #print ("__setitem__ slice num bits", bits)
-            if isinstance(value, SelectableInt):
-                assert value.bits == bits, "%d into %d" % (value.bits, bits)
-                value = value.value
-            mask = ((1 << bits) - 1) << start
-            value = value << start
-            self.value = (self.value & ~mask) | (value & mask)
-
-    def __ge__(self, other):
-        if isinstance(other, FieldSelectableInt):
-            other = other.get_range()
-        if isinstance(other, SelectableInt):
-            other = check_extsign(self, other)
-            assert other.bits == self.bits
-            other = other.to_signed_int()
-        if isinstance(other, int):
-            return onebit(self.to_signed_int() >= other)
-        assert False
-
-    def __le__(self, other):
-        if isinstance(other, FieldSelectableInt):
-            other = other.get_range()
-        if isinstance(other, SelectableInt):
-            other = check_extsign(self, other)
-            assert other.bits == self.bits
-            other = other.to_signed_int()
-        if isinstance(other, int):
-            return onebit(self.to_signed_int() <= other)
-        assert False
-
-    def __gt__(self, other):
-        if isinstance(other, FieldSelectableInt):
-            other = other.get_range()
-        if isinstance(other, SelectableInt):
-            other = check_extsign(self, other)
-            assert other.bits == self.bits
-            other = other.to_signed_int()
-        if isinstance(other, int):
-            return onebit(self.to_signed_int() > other)
-        assert False
-
-    def __lt__(self, other):
-        print ("SelectableInt lt", self, other)
-        if isinstance(other, FieldSelectableInt):
-            other = other.get_range()
-        if isinstance(other, SelectableInt):
-            other = check_extsign(self, other)
-            assert other.bits == self.bits
-            other = other.to_signed_int()
-        if isinstance(other, int):
-            a = self.to_signed_int()
-            res = onebit(a  < other)
-            print ("    a < b", a, other, res)
-            return res
-        assert False
-
-    def __eq__(self, other):
-        print("__eq__", self, other)
-        if isinstance(other, FieldSelectableInt):
-            other = other.get_range()
-        if isinstance(other, SelectableInt):
-            other = check_extsign(self, other)
-            assert other.bits == self.bits
-            other = other.value
-        print ("    eq", other, self.value, other == self.value)
-        if isinstance(other, int):
-            return onebit(other == self.value)
-        assert False
-
-    def narrow(self, bits):
-        assert bits <= self.bits
-        return SelectableInt(self.value, bits)
-
-    def __bool__(self):
-        return self.value != 0
-
-    def __repr__(self):
-        return "SelectableInt(value=0x{:x}, bits={})".format(self.value,
-                                                             self.bits)
-
-    def __len__(self):
-        return self.bits
-
-    def asint(self):
-        return self.value
-
-
-def onebit(bit):
-    return SelectableInt(1 if bit else 0, 1)
-
-
-def selectltu(lhs, rhs):
-    """ less-than (unsigned)
-    """
-    if isinstance(rhs, SelectableInt):
-        rhs = rhs.value
-    return onebit(lhs.value < rhs)
-
-
-def selectgtu(lhs, rhs):
-    """ greater-than (unsigned)
-    """
-    if isinstance(rhs, SelectableInt):
-        rhs = rhs.value
-    return onebit(lhs.value > rhs)
-
-
-# XXX this probably isn't needed...
-def selectassign(lhs, idx, rhs):
-    if isinstance(idx, tuple):
-        if len(idx) == 2:
-            lower, upper = idx
-            step = None
-        else:
-            lower, upper, step = idx
-        toidx = range(lower, upper, step)
-        fromidx = range(0, upper-lower, step)  # XXX eurgh...
-    else:
-        toidx = [idx]
-        fromidx = [0]
-    for t, f in zip(toidx, fromidx):
-        lhs[t] = rhs[f]
-
-
-def selectconcat(*args, repeat=1):
-    if repeat != 1 and len(args) == 1 and isinstance(args[0], int):
-        args = [SelectableInt(args[0], 1)]
-    if repeat != 1:  # multiplies the incoming arguments
-        tmp = []
-        for i in range(repeat):
-            tmp += args
-        args = tmp
-    res = copy(args[0])
-    for i in args[1:]:
-        if isinstance(i, FieldSelectableInt):
-            i = i.si
-        assert isinstance(i, SelectableInt), "can only concat SIs, sorry"
-        res.bits += i.bits
-        res.value = (res.value << i.bits) | i.value
-    print("concat", repeat, res)
-    return res
-
-
-class SelectableIntTestCase(unittest.TestCase):
-    def test_arith(self):
-        a = SelectableInt(5, 8)
-        b = SelectableInt(9, 8)
-        c = a + b
-        d = a - b
-        e = a * b
-        f = -a
-        g = abs(f)
-        h = abs(a)
-        self.assertEqual(c.value, a.value + b.value)
-        self.assertEqual(d.value, (a.value - b.value) & 0xFF)
-        self.assertEqual(e.value, (a.value * b.value) & 0xFF)
-        self.assertEqual(f.value, (-a.value) & 0xFF)
-        self.assertEqual(c.bits, a.bits)
-        self.assertEqual(d.bits, a.bits)
-        self.assertEqual(e.bits, a.bits)
-        self.assertEqual(a.bits, f.bits)
-        self.assertEqual(a.bits, h.bits)
-
-    def test_logic(self):
-        a = SelectableInt(0x0F, 8)
-        b = SelectableInt(0xA5, 8)
-        c = a & b
-        d = a | b
-        e = a ^ b
-        f = ~a
-        self.assertEqual(c.value, a.value & b.value)
-        self.assertEqual(d.value, a.value | b.value)
-        self.assertEqual(e.value, a.value ^ b.value)
-        self.assertEqual(f.value, 0xF0)
-
-    def test_get(self):
-        a = SelectableInt(0xa2, 8)
-        # These should be big endian
-        self.assertEqual(a[7], 0)
-        self.assertEqual(a[0:4], 10)
-        self.assertEqual(a[4:8], 2)
-
-    def test_set(self):
-        a = SelectableInt(0x5, 8)
-        a[7] = SelectableInt(0, 1)
-        self.assertEqual(a, 4)
-        a[4:8] = 9
-        self.assertEqual(a, 9)
-        a[0:4] = 3
-        self.assertEqual(a, 0x39)
-        a[0:4] = a[4:8]
-        self.assertEqual(a, 0x99)
-
-    def test_concat(self):
-        a = SelectableInt(0x1, 1)
-        c = selectconcat(a, repeat=8)
-        self.assertEqual(c, 0xff)
-        self.assertEqual(c.bits, 8)
-        a = SelectableInt(0x0, 1)
-        c = selectconcat(a, repeat=8)
-        self.assertEqual(c, 0x00)
-        self.assertEqual(c.bits, 8)
-
-    def test_repr(self):
-        for i in range(65536):
-            a = SelectableInt(i, 16)
-            b = eval(repr(a))
-            self.assertEqual(a, b)
-
-    def test_cmp(self):
-        a = SelectableInt(10, bits=8)
-        b = SelectableInt(5, bits=8)
-        self.assertTrue(a > b)
-        self.assertFalse(a < b)
-        self.assertTrue(a != b)
-        self.assertFalse(a == b)
-
-    def test_unsigned(self):
-        a = SelectableInt(0x80, bits=8)
-        b = SelectableInt(0x7f, bits=8)
-        self.assertTrue(a > b)
-        self.assertFalse(a < b)
-        self.assertTrue(a != b)
-        self.assertFalse(a == b)
-
-
-if __name__ == "__main__":
-    unittest.main()
+from openpower.decoder.selectable_int import *