from nmigen import Module, Elaboratable, Signal, Mux, Const, Cat, Repl, Record
from nmigen.cli import rtlil
+from nmutil.util import sel
+
from soc.regfile.regfiles import XERRegs
from nmutil.picker import PriorityPicker
from soc.decoder.decode2execute1 import (Decode2ToExecute1Type, Data,
Decode2ToOperand)
from soc.sv.svp64 import SVP64Rec
-from soc.consts import (MSR, sel, SPEC, EXTRA2, EXTRA3, SVP64P, field,
- SPEC_SIZE, SPECb, SPEC_AUG_SIZE)
+from soc.consts import (MSR, SPEC, EXTRA2, EXTRA3, SVP64P, field,
+ SPEC_SIZE, SPECb, SPEC_AUG_SIZE, SVP64CROffs)
from soc.regfile.regfiles import FastRegs
from soc.consts import TT
with m.Case(SVEtype.EXTRA3):
with m.Switch(self.idx):
with m.Case(SVEXTRA.Idx0): # 1st 3 bits [0:2]
- comb += spec.eq(sel(extra, EXTRA3.IDX0))
+ extra3_idx0 = sel(m, extra, EXTRA3.IDX0)
+ comb += spec.eq(extra3_idx0)
with m.Case(SVEXTRA.Idx1): # 2nd 3 bits [3:5]
- comb += spec.eq(sel(extra, EXTRA3.IDX1))
+ extra3_idx1 = sel(m, extra, EXTRA3.IDX1)
+ comb += spec.eq(extra3_idx1)
with m.Case(SVEXTRA.Idx2): # 3rd 3 bits [6:8]
- comb += spec.eq(sel(extra, EXTRA3.IDX2))
+ extra3_idx2 = sel(m, extra, EXTRA3.IDX2)
+ comb += spec.eq(extra3_idx2)
# cannot fit more than 9 bits so there is no 4th thing
return m
comb += self.whole_reg.ok.eq(0)
comb += self.sv_override.eq(0)
+ # please note these MUST match (setting of cr_bitfield.ok) exactly
+ # with write_cr0 below in PowerDecoder2. the reason it's separated
+ # is to avoid having duplicate copies of DecodeCROut in multiple
+ # PowerDecoderSubsets. register decoding should be a one-off in
+ # PowerDecoder2. see https://bugs.libre-soc.org/show_bug.cgi?id=606
+
with m.Switch(self.sel_in):
with m.Case(CROutSel.NONE):
pass # No bitfield activated
state = self.state
op, do = self.dec.op, self.do
msr, cia = state.msr, state.pc
-
# fill in for a normal instruction (not an exception)
# copy over if non-exception, non-privileged etc. is detected
if not self.final:
# set up submodule decoders
m.submodules.dec = self.dec
- m.submodules.dec_rc = dec_rc = DecodeRC(self.dec)
+ m.submodules.dec_rc = self.dec_rc = dec_rc = DecodeRC(self.dec)
m.submodules.dec_oe = dec_oe = DecodeOE(self.dec)
- m.submodules.dec_cr_in = self.dec_cr_in = DecodeCRIn(self.dec)
- m.submodules.dec_cr_out = self.dec_cr_out = DecodeCROut(self.dec)
# copy instruction through...
- for i in [do.insn,
- dec_rc.insn_in, dec_oe.insn_in,
- self.dec_cr_in.insn_in, self.dec_cr_out.insn_in]:
+ for i in [do.insn, dec_rc.insn_in, dec_oe.insn_in, ]:
comb += i.eq(self.dec.opcode_in)
# ...and subdecoders' input fields
comb += dec_rc.sel_in.eq(op.rc_sel)
comb += dec_oe.sel_in.eq(op.rc_sel) # XXX should be OE sel
- comb += self.dec_cr_in.sel_in.eq(op.cr_in)
- comb += self.dec_cr_out.sel_in.eq(op.cr_out)
- comb += self.dec_cr_out.rc_in.eq(dec_rc.rc_out.data)
# copy "state" over
comb += self.do_copy("msr", msr)
# set up instruction type
# no op: defaults to OP_ILLEGAL
- if self.fn_name=="MMU":
- # mmu is special case: needs SPR opcode as well
- mmu0 = self.mmu0_spr_dec
- with m.If(((mmu0.dec.op.internal_op == MicrOp.OP_MTSPR) |
- (mmu0.dec.op.internal_op == MicrOp.OP_MFSPR))):
- comb += self.do_copy("insn_type", mmu0.op_get("internal_op"))
- with m.Else():
- comb += self.do_copy("insn_type", self.op_get("internal_op"))
- else:
- comb += self.do_copy("insn_type", self.op_get("internal_op"))
+ # FIX https://bugs.libre-soc.org/show_bug.cgi?id=607
+ comb += self.do_copy("insn_type", self.op_get("internal_op"))
# function unit for decoded instruction: requires minor redirect
# for SPR set/get
spr = Signal(10, reset_less=True)
comb += spr.eq(decode_spr_num(self.dec.SPR)) # from XFX
- # XXX BUG - don't use hardcoded magic constants.
- # also use ".value" otherwise the test fails. bit of a pain
- # https://bugs.libre-soc.org/show_bug.cgi?id=603
-
- SPR_PID = 48 # TODO read docs for POWER9
# Microwatt doesn't implement the partition table
- # instead has PRTBL register (SPR) to point to process table
- SPR_PRTBL = 720 # see common.vhdl in microwatt, not in POWER9
+ # instead has PRTBL(SVSRR0) register (SPR) to point to process table
with m.If(((self.dec.op.internal_op == MicrOp.OP_MTSPR) |
(self.dec.op.internal_op == MicrOp.OP_MFSPR)) &
- ((spr == SPR.DSISR) | (spr == SPR.DAR)
- | (spr==SPR_PRTBL) | (spr==SPR_PID))):
+ ((spr == SPR.DSISR.value) | (spr == SPR.DAR.value) |
+ (spr==SPR.SVSRR0.value) | (spr==SPR.PIDR.value))):
comb += self.do_copy("fn_unit", Function.MMU)
with m.Else():
comb += self.do_copy("fn_unit",fn)
comb += self.do_copy("rc", dec_rc.rc_out)
comb += self.do_copy("oe", dec_oe.oe_out)
- # CR in/out
- comb += self.do_copy("read_cr_whole", self.dec_cr_in.whole_reg)
- comb += self.do_copy("write_cr_whole", self.dec_cr_out.whole_reg)
- comb += self.do_copy("write_cr0", self.dec_cr_out.cr_bitfield.ok)
+ # CR in/out - note: these MUST match with what happens in
+ # DecodeCROut!
+ rc_out = self.dec_rc.rc_out.data
+ with m.Switch(op.cr_out):
+ with m.Case(CROutSel.CR0, CROutSel.CR1):
+ comb += self.do_copy("write_cr0", rc_out) # only when RC=1
+ with m.Case(CROutSel.BF, CROutSel.BT):
+ comb += self.do_copy("write_cr0", 1)
comb += self.do_copy("input_cr", self.op_get("cr_in")) # CR in
comb += self.do_copy("output_cr", self.op_get("cr_out")) # CR out
state = self.state
e_out, op, do_out = self.e, self.dec.op, self.e.do
dec_spr, msr, cia, ext_irq = state.dec, state.msr, state.pc, state.eint
+ rc_out = self.dec_rc.rc_out.data
e = self.e_tmp
do = e.do
m.submodules.dec_c = dec_c = DecodeC(self.dec)
m.submodules.dec_o = dec_o = DecodeOut(self.dec)
m.submodules.dec_o2 = dec_o2 = DecodeOut2(self.dec)
+ m.submodules.dec_cr_in = self.dec_cr_in = DecodeCRIn(self.dec)
+ m.submodules.dec_cr_out = self.dec_cr_out = DecodeCROut(self.dec)
# and SVP64 Extra decoders
m.submodules.crout_svdec = crout_svdec = SVP64CRExtra()
# copy instruction through...
for i in [do.insn, dec_a.insn_in, dec_b.insn_in,
+ self.dec_cr_in.insn_in, self.dec_cr_out.insn_in,
dec_c.insn_in, dec_o.insn_in, dec_o2.insn_in]:
comb += i.eq(self.dec.opcode_in)
+ # CR setup
+ comb += self.dec_cr_in.sel_in.eq(op.cr_in)
+ comb += self.dec_cr_out.sel_in.eq(op.cr_out)
+ comb += self.dec_cr_out.rc_in.eq(rc_out)
+
+ # CR register info
+ comb += self.do_copy("read_cr_whole", self.dec_cr_in.whole_reg)
+ comb += self.do_copy("write_cr_whole", self.dec_cr_out.whole_reg)
+
# now do the SVP64 munging. op.SV_Etype and op.sv_in1 comes from
# PowerDecoder which in turn comes from LDST-RM*.csv and RM-*.csv
# which in turn were auto-generated by sv_analysis.py
comb += self.o_isvec.eq(o_svdec.isvec)
comb += self.o2_isvec.eq(o2_svdec.isvec)
# TODO: include SPRs and CRs here! must be True when *all* are scalar
- comb += self.no_out_vec.eq((~o2_svdec.isvec) & (~o_svdec.isvec))
+ comb += self.no_out_vec.eq((~o2_svdec.isvec) & (~o_svdec.isvec) &
+ (~crout_svdec.isvec))
# SPRs out
comb += e.read_spr1.eq(dec_a.spr_out)
comb += svdec.cr_in.eq(fromreg.data) # 3-bit (CR0/BC/BFA)
with m.If(svdec.isvec):
# check if this is CR0 or CR1: treated differently
- # (does not "listen" to EXTRA2/3 spec
+ # (does not "listen" to EXTRA2/3 spec for a start)
+ # also: the CRs start from completely different locations
with m.If(cr.sv_override == 1): # CR0
- comb += to_reg.data.eq(srcstep+0) # XXX TODO CR0 offset
+ offs = SVP64CROffs.CR0
+ comb += to_reg.data.eq(srcstep+offs)
with m.Elif(cr.sv_override == 2): # CR1
- comb += to_reg.data.eq(srcstep+1) # XXX TODO CR1 offset
+ offs = SVP64CROffs.CR1
+ comb += to_reg.data.eq(srcstep+1)
with m.Else():
comb += to_reg.data.eq(srcstep+svdec.cr_out) # 7-bit output
with m.Else():
comb += opcode_in.eq(Mux(self.bigendian, raw_be, raw_le))
# start identifying if the incoming opcode is SVP64 prefix)
- major = Signal(6, reset_less=True)
- ident = Signal(2, reset_less=True)
-
- comb += major.eq(sel(opcode_in, SVP64P.OPC))
- comb += ident.eq(sel(opcode_in, SVP64P.SVP64_7_9))
+ major = sel(m, opcode_in, SVP64P.OPC)
+ ident = sel(m, opcode_in, SVP64P.SVP64_7_9)
comb += self.is_svp64_mode.eq(
(major == Const(1, 6)) & # EXT01
with m.If(self.is_svp64_mode):
# now grab the 24-bit ReMap context bits,
- comb += self.svp64_rm.eq(sel(opcode_in, SVP64P.RM))
+ rm = sel(m, opcode_in, SVP64P.RM)
+ comb += self.svp64_rm.eq(rm)
return m