"""
from nmigen import (Elaboratable, Module, Signal, ClockSignal, ResetSignal,
- ClockDomain, DomainRenamer, Mux, Const)
+ ClockDomain, DomainRenamer, Mux, Const, Repl)
from nmigen.cli import rtlil
from nmigen.cli import main
import sys
from soc.simple.core import NonProductionCore
from soc.config.test.test_loadstore import TestMemPspec
from soc.config.ifetch import ConfigFetchUnit
-from soc.decoder.power_enums import MicrOp, SVP64PredInt, SVP64PredCR
+from soc.decoder.power_enums import (MicrOp, SVP64PredInt, SVP64PredCR,
+ SVP64PredMode)
from soc.debug.dmi import CoreDebug, DMIInterface
from soc.debug.jtag import JTAG
from soc.config.pinouts import get_pinspecs
comb += res.eq(regfile.data_o)
return res
-def get_predint(m, mask):
+def get_predint(m, mask, name):
"""decode SVP64 predicate integer mask field to reg number and invert
this is identical to the equivalent function in ISACaller except that
it doesn't read the INT directly, it just decodes "what needs to be done"
i.e. which INT reg, whether it is shifted and whether it is bit-inverted.
+
+ * all1s is set to indicate that no mask is to be applied.
+ * regread indicates the GPR register number to be read
+ * invert is set to indicate that the register value is to be inverted
+ * unary indicates that the contents of the register is to be shifted 1<<r3
"""
comb = m.d.comb
- regread = Signal(5)
- invert = Signal()
- unary = Signal()
+ regread = Signal(5, name=name+"regread")
+ invert = Signal(name=name+"invert")
+ unary = Signal(name=name+"unary")
+ all1s = Signal(name=name+"all1s")
with m.Switch(mask):
- with m.Case(SVP64PredInt.ALWAYS):
- comb += regread.eq(0)
- comb += invert.eq(1)
- with m.Case(SVP64PredInt.R3_UNARY):
+ with m.Case(SVP64PredInt.ALWAYS.value):
+ comb += all1s.eq(1) # use 0b1111 (all ones)
+ with m.Case(SVP64PredInt.R3_UNARY.value):
comb += regread.eq(3)
- comb += unary.eq(1)
- with m.Case(SVP64PredInt.R3):
+ comb += unary.eq(1) # 1<<r3 - shift r3 (single bit)
+ with m.Case(SVP64PredInt.R3.value):
comb += regread.eq(3)
- with m.Case(SVP64PredInt.R3_N):
+ with m.Case(SVP64PredInt.R3_N.value):
comb += regread.eq(3)
comb += invert.eq(1)
- with m.Case(SVP64PredInt.R10):
+ with m.Case(SVP64PredInt.R10.value):
comb += regread.eq(10)
- with m.Case(SVP64PredInt.R10_N):
+ with m.Case(SVP64PredInt.R10_N.value):
comb += regread.eq(10)
comb += invert.eq(1)
- with m.Case(SVP64PredInt.R30):
+ with m.Case(SVP64PredInt.R30.value):
comb += regread.eq(30)
- with m.Case(SVP64PredInt.R30_N):
+ with m.Case(SVP64PredInt.R30_N.value):
comb += regread.eq(30)
comb += invert.eq(1)
- return regread, invert, unary
+ return regread, invert, unary, all1s
-def get_predcr(m, mask):
+def get_predcr(m, mask, name):
"""decode SVP64 predicate CR to reg number field and invert status
this is identical to _get_predcr in ISACaller
"""
comb = m.d.comb
- idx = Signal(2)
- invert = Signal()
+ idx = Signal(2, name=name+"idx")
+ invert = Signal(name=name+"crinvert")
with m.Switch(mask):
- with m.Case(SVP64PredCR.LT):
+ with m.Case(SVP64PredCR.LT.value):
comb += idx.eq(0)
comb += invert.eq(1)
- with m.Case(SVP64PredCR.GE):
+ with m.Case(SVP64PredCR.GE.value):
comb += idx.eq(0)
comb += invert.eq(0)
- with m.Case(SVP64PredCR.GT):
+ with m.Case(SVP64PredCR.GT.value):
comb += idx.eq(1)
comb += invert.eq(1)
- with m.Case(SVP64PredCR.LE):
+ with m.Case(SVP64PredCR.LE.value):
comb += idx.eq(1)
comb += invert.eq(0)
- with m.Case(SVP64PredCR.EQ):
+ with m.Case(SVP64PredCR.EQ.value):
comb += idx.eq(2)
comb += invert.eq(1)
- with m.Case(SVP64PredCR.NE):
+ with m.Case(SVP64PredCR.NE.value):
comb += idx.eq(1)
comb += invert.eq(0)
- with m.Case(SVP64PredCR.SO):
+ with m.Case(SVP64PredCR.SO.value):
comb += idx.eq(3)
comb += invert.eq(1)
- with m.Case(SVP64PredCR.NS):
+ with m.Case(SVP64PredCR.NS.value):
comb += idx.eq(3)
comb += invert.eq(0)
return idx, invert
# here or maybe even in INSN_READ state, if svp64_mode
# detected, in order to trigger - and wait for - the
# predicate reading.
- pmode = pdecode2.rm_dec.predmode
+ if self.svp64_en:
+ pmode = pdecode2.rm_dec.predmode
"""
if pmode != SVP64PredMode.ALWAYS.value:
fire predicate loading FSM and wait before
predmode = rm_dec.predmode
srcpred, dstpred = rm_dec.srcpred, rm_dec.dstpred
cr_pred, int_pred = self.cr_pred, self.int_pred # read regfiles
- # if predmode == INT:
- # INT-src sregread, sinvert, sunary = get_predint(m, srcpred)
- # INT-dst dregread, dinvert, dunary = get_predint(m, dstpred)
- # TODO read INT-src and INT-dst into self.srcmask+dstmask
- # has to cope with first one then the other
- # FSM-triggered-int-read
- # comb += int_pred.addr.eq(d_reg.addr)
- # comb += int_pred.ren.eq(1)
- # FSM-1-clock-later
- # comb += d_reg.data.eq(self.int_r.data_o)
+
# elif predmode == CR:
# CR-src sidx, sinvert = get_predcr(m, srcpred)
# CR-dst didx, dinvert = get_predcr(m, dstpred)
# comb += cr_bit.eq(cr_field.bit_select(idx)))
# # just like in branch BO tests
# comd += self.srcmask[cr_idx].eq(inv ^ cr_bit)
- # else
- # sync += self.srcmask.eq(-1) # set to all 1s
- # sync += self.dstmask.eq(-1) # set to all 1s
+
+ # decode predicates
+ sregread, sinvert, sunary, sall1s = get_predint(m, srcpred, 's')
+ dregread, dinvert, dunary, dall1s = get_predint(m, dstpred, 'd')
+ sidx, scrinvert = get_predcr(m, srcpred, 's')
+ didx, dcrinvert = get_predcr(m, dstpred, 'd')
+
with m.FSM(name="fetch_predicate"):
with m.State("FETCH_PRED_IDLE"):
comb += pred_insn_ready_o.eq(1)
with m.If(pred_insn_valid_i):
+ with m.If(predmode == SVP64PredMode.INT):
+ # skip fetching destination mask register, when zero
+ with m.If(dall1s):
+ sync += self.dstmask.eq(-1)
+ # directly go to fetch source mask register
+ # guaranteed not to be zero (otherwise predmode
+ # would be SVP64PredMode.ALWAYS, not INT)
+ comb += int_pred.addr.eq(sregread)
+ comb += int_pred.ren.eq(1)
+ m.next = "INT_SRC_READ"
+ # fetch destination predicate register
+ with m.Else():
+ comb += int_pred.addr.eq(dregread)
+ comb += int_pred.ren.eq(1)
+ m.next = "INT_DST_READ"
+ with m.Else():
+ sync += self.srcmask.eq(-1)
+ sync += self.dstmask.eq(-1)
+ m.next = "FETCH_PRED_DONE"
+
+ with m.State("INT_DST_READ"):
+ # store destination mask
+ inv = Repl(dinvert, 64)
+ sync += self.dstmask.eq(self.int_pred.data_o ^ inv)
+ # skip fetching source mask register, when zero
+ with m.If(sall1s):
sync += self.srcmask.eq(-1)
- sync += self.dstmask.eq(-1)
m.next = "FETCH_PRED_DONE"
+ # fetch source predicate register
+ with m.Else():
+ comb += int_pred.addr.eq(sregread)
+ comb += int_pred.ren.eq(1)
+ m.next = "INT_SRC_READ"
+
+ with m.State("INT_SRC_READ"):
+ # store source mask
+ inv = Repl(sinvert, 64)
+ sync += self.srcmask.eq(self.int_pred.data_o ^ inv)
+ m.next = "FETCH_PRED_DONE"
with m.State("FETCH_PRED_DONE"):
comb += pred_mask_valid_o.eq(1)
comb += self.insn_done.eq(1)
m.next = "ISSUE_START"
with m.Else():
- m.next = "PRED_START" # start fetching the predicate
+ if self.svp64_en:
+ m.next = "PRED_START" # start fetching predicate
+ else:
+ m.next = "INSN_EXECUTE" # skip predication
with m.State("PRED_START"):
comb += pred_insn_valid_i.eq(1) # tell fetch_pred to start
with m.If(is_svp64_mode):
- pred_src_zero = pdecode2.rm_dec.pred_sz
- pred_dst_zero = pdecode2.rm_dec.pred_dz
+ if self.svp64_en:
+ pred_src_zero = pdecode2.rm_dec.pred_sz
+ pred_dst_zero = pdecode2.rm_dec.pred_dz
"""
if not pred_src_zero:
exec_insn_valid_i, exec_insn_ready_o,
exec_pc_valid_o, exec_pc_ready_i)
- self.fetch_predicate_fsm(m,
- pred_insn_valid_i, pred_insn_ready_o,
- pred_mask_valid_o, pred_mask_ready_i)
+ if self.svp64_en:
+ self.fetch_predicate_fsm(m,
+ pred_insn_valid_i, pred_insn_ready_o,
+ pred_mask_valid_o, pred_mask_ready_i)
self.execute_fsm(m, core, pc_changed, sv_changed,
exec_insn_valid_i, exec_insn_ready_o,