from soc.regfile.regfiles import FastRegs
 from soc.consts import TT
+from soc.config.state import CoreState
 
 
 def decode_spr_num(spr):
         self.valid = Signal()  # sync signal
 
         # state information needed by the Decoder (TODO: this as a Record)
-        self.msr = Signal(64, reset_less=True)  # copy of MSR
-        self.cia = Signal(64, reset_less=True)  # copy of Program Counter
+        self.state = CoreState("dec2")
 
     def ports(self):
         return self.dec.ports() + self.e.ports()
     def elaborate(self, platform):
         m = Module()
         comb = m.d.comb
-        e, op, do, msr, cia = self.e, self.dec.op, self.e.do, self.msr, self.cia
+        e, op, do = self.e, self.dec.op, self.e.do
+        msr, cia = self.state.msr, self.state.pc
 
         # set up submodule decoders
         m.submodules.dec = self.dec
         comb += dec_cr_out.rc_in.eq(dec_rc.rc_out.data)
 
         # copy "state" over
-        comb += do.msr.eq(self.msr)
-        comb += do.cia.eq(self.cia)
+        comb += do.msr.eq(msr)
+        comb += do.cia.eq(cia)
 
         # set up instruction, pick fn unit
         # no op: defaults to OP_ILLEGAL
         comb += do.fn_unit.eq(Function.TRAP)
         comb += do.trapaddr.eq(trapaddr >> 4)  # cut bottom 4 bits
         comb += do.traptype.eq(traptype)  # request type
-        comb += do.msr.eq(self.msr)  # copy of MSR "state"
-        comb += do.cia.eq(self.cia)  # copy of PC "state"
+        comb += do.msr.eq(self.state.msr)  # copy of MSR "state"
+        comb += do.cia.eq(self.state.pc)  # copy of PC "state"
 
     def regspecmap_read(self, regfile, regname):
         """regspecmap_read: provides PowerDecode2 with an encoding relationship
 
 from soc.config.ifetch import ConfigFetchUnit
 from soc.decoder.power_enums import MicrOp
 from soc.debug.dmi import CoreDebug, DMIInterface
+from soc.config.state import CoreState
 
 
 class TestIssuer(Elaboratable):
         comb += self.busy_o.eq(core.busy_o)
         comb += core.bigendian_i.eq(self.core_bigendian_i)
 
+        # current state (MSR/PC at the moment
+        cur_state = CoreState("cur")
+
         # temporary hack: says "go" immediately for both address gen and ST
         l0 = core.l0
         ldst = core.fus.fus['ldst0']
 
         # PC and instruction from I-Memory
         current_insn = Signal(32) # current fetched instruction (note sync)
-        cur_pc = Signal(64) # current PC (note it is reset/sync)
         pc_changed = Signal() # note write to PC
-        comb += self.pc_o.eq(cur_pc)
+        comb += self.pc_o.eq(cur_state.pc)
         ilatch = Signal(32)
 
         # MSR (temp and latched)
-        cur_msr = Signal(64) # current MSR (note it is reset/sync)
         msr = Signal(64, reset_less=True)
 
         # next instruction (+4 on current)
         nia = Signal(64, reset_less=True)
-        comb += nia.eq(cur_pc + 4)
+        comb += nia.eq(cur_state.pc + 4)
 
         # connect up debug signals
         comb += core.core_stopped_i.eq(dbg.core_stop_o)
         # TODO comb += core.reset_i.eq(dbg.core_rst_o)
         # TODO comb += core.icache_rst_i.eq(dbg.icache_rst_o)
         comb += dbg.terminate_i.eq(core.core_terminate_o)
-        comb += dbg.state.pc.eq(cur_pc)
-        comb += dbg.state.msr.eq(cur_msr)
+        comb += dbg.state.eq(cur_state)
 
         # temporaries
         core_busy_o = core.busy_o         # core is busy
         core_opcode_i = core.raw_opcode_i # raw opcode
 
         insn_type = core.pdecode2.e.do.insn_type
-        insn_msr = core.pdecode2.msr
-        insn_cia = core.pdecode2.cia
+        insn_state = core.pdecode2.state
 
         # actually use a nmigen FSM for the first time (w00t)
         # this FSM is perhaps unusual in that it detects conditions
                     comb += self.imem.a_pc_i.eq(pc)
                     comb += self.imem.a_valid_i.eq(1)
                     comb += self.imem.f_valid_i.eq(1)
-                    sync += cur_pc.eq(pc)
+                    sync += cur_state.pc.eq(pc)
                     m.next = "INSN_READ" # move to "wait for bus" phase
 
             # waiting for instruction bus (stays there until not busy)
                     if f_instr_o.width == 32:
                         insn = f_instr_o
                     else:
-                        insn = f_instr_o.word_select(cur_pc[2], 32)
+                        insn = f_instr_o.word_select(cur_state.pc[2], 32)
                     comb += current_insn.eq(insn)
                     comb += core_ivalid_i.eq(1) # instruction is valid
                     comb += core_issue_i.eq(1)  # and issued
                     # read MSR, latch it, and put it in decode "state"
                     comb += self.fast_r_msr.ren.eq(1<<FastRegs.MSR)
                     comb += msr.eq(self.fast_r_msr.data_o)
-                    comb += insn_msr.eq(msr)
-                    sync += cur_msr.eq(msr) # latch current MSR
+                    comb += insn_state.msr.eq(msr)
+                    sync += cur_state.msr.eq(msr) # latch current MSR
 
                     # also drop PC into decode "state"
-                    comb += insn_cia.eq(cur_pc)
+                    comb += insn_state.pc.eq(cur_state.pc)
 
                     m.next = "INSN_ACTIVE" # move to "wait completion"
 
                 with m.If(insn_type != MicrOp.OP_NOP):
                     comb += core_ivalid_i.eq(1) # instruction is valid
                 comb += core_opcode_i.eq(ilatch) # actual opcode
-                comb += insn_msr.eq(cur_msr)     # and MSR
-                comb += insn_cia.eq(cur_pc)     # and PC
+                comb += insn_state.eq(cur_state)     # and MSR and PC
                 with m.If(self.fast_nia.wen):
                     sync += pc_changed.eq(1)
                 with m.If(~core_busy_o): # instruction done!