return f_instr_o.word_select(pc[2], 32)
# gets state input or reads from state regfile
-def state_get(m, state_i, name, regfile, regnum):
+def state_get(m, core_rst, state_i, name, regfile, regnum):
comb = m.d.comb
sync = m.d.sync
# read the PC
res = Signal(64, reset_less=True, name=name)
res_ok_delay = Signal(name="%s_ok_delay" % name)
- sync += res_ok_delay.eq(~state_i.ok)
- with m.If(state_i.ok):
- # incoming override (start from pc_i)
- comb += res.eq(state_i.data)
- with m.Else():
- # otherwise read StateRegs regfile for PC...
- comb += regfile.ren.eq(1<<regnum)
- # ... but on a 1-clock delay
- with m.If(res_ok_delay):
- comb += res.eq(regfile.data_o)
+ with m.If(~core_rst):
+ sync += res_ok_delay.eq(~state_i.ok)
+ with m.If(state_i.ok):
+ # incoming override (start from pc_i)
+ comb += res.eq(state_i.data)
+ with m.Else():
+ # otherwise read StateRegs regfile for PC...
+ comb += regfile.ren.eq(1<<regnum)
+ # ... but on a 1-clock delay
+ with m.If(res_ok_delay):
+ comb += res.eq(regfile.data_o)
return res
def get_predint(m, mask, name):
predmode = rm_dec.predmode
srcpred, dstpred = rm_dec.srcpred, rm_dec.dstpred
cr_pred, int_pred = self.cr_pred, self.int_pred # read regfiles
+ # get src/dst step, so we can skip already used mask bits
+ cur_state = self.cur_state
+ srcstep = cur_state.svstate.srcstep
+ dststep = cur_state.svstate.dststep
# elif predmode == CR:
# CR-src sidx, sinvert = get_predcr(m, srcpred)
with m.State("INT_DST_READ"):
# store destination mask
inv = Repl(dinvert, 64)
- sync += self.dstmask.eq(self.int_pred.data_o ^ inv)
+ new_dstmask = Signal(64)
+ with m.If(dunary):
+ # set selected mask bit for 1<<r3 mode
+ dst_shift = Signal(range(64))
+ comb += dst_shift.eq(self.int_pred.data_o & 0b111111)
+ comb += new_dstmask.bit_select(dst_shift, 1).eq(1)
+ with m.Else():
+ # invert mask if requested
+ comb += new_dstmask.eq(self.int_pred.data_o ^ inv)
+ # shift-out already used mask bits
+ sync += self.dstmask.eq(new_dstmask >> dststep)
# skip fetching source mask register, when zero
with m.If(sall1s):
sync += self.srcmask.eq(-1)
with m.State("INT_SRC_READ"):
# store source mask
inv = Repl(sinvert, 64)
- sync += self.srcmask.eq(self.int_pred.data_o ^ inv)
+ new_srcmask = Signal(64)
+ with m.If(sunary):
+ # set selected mask bit for 1<<r3 mode
+ src_shift = Signal(range(64))
+ comb += src_shift.eq(self.int_pred.data_o & 0b111111)
+ comb += new_srcmask.bit_select(src_shift, 1).eq(1)
+ with m.Else():
+ # invert mask if requested
+ comb += new_srcmask.eq(self.int_pred.data_o ^ inv)
+ # shift-out already used mask bits
+ sync += self.srcmask.eq(new_srcmask >> srcstep)
m.next = "FETCH_PRED_DONE"
with m.State("FETCH_PRED_DONE"):
# append guard bit, in case the mask is all zeros
pri_enc_src = PriorityEncoder(65)
m.submodules.pri_enc_src = pri_enc_src
- comb += pri_enc_src.i.eq(Cat(self.srcmask, 1))
+ comb += pri_enc_src.i.eq(Cat(self.srcmask,
+ Const(1, 1)))
comb += src_delta.eq(pri_enc_src.o)
# apply delta to srcstep
comb += skip_srcstep.eq(cur_srcstep + src_delta)
# shift-out all leading zeros from the mask
# plus the leading "one" bit
+ # TODO count leading zeros and shift-out the zero
+ # bits, in the same step, in hardware
sync += self.srcmask.eq(self.srcmask >> (src_delta+1))
# same as above, but for dststep
with m.If(~pred_dst_zero):
pri_enc_dst = PriorityEncoder(65)
m.submodules.pri_enc_dst = pri_enc_dst
- comb += pri_enc_dst.i.eq(Cat(self.dstmask, 1))
+ comb += pri_enc_dst.i.eq(Cat(self.dstmask,
+ Const(1, 1)))
comb += dst_delta.eq(pri_enc_dst.o)
comb += skip_dststep.eq(cur_dststep + dst_delta)
sync += self.dstmask.eq(self.dstmask >> (dst_delta+1))
# set up peripherals and core
core_rst = self.setup_peripherals(m)
+ # reset current state if core reset requested
+ with m.If(core_rst):
+ m.d.sync += self.cur_state.eq(0)
+
# PC and instruction from I-Memory
comb += self.pc_o.eq(cur_state.pc)
pc_changed = Signal() # note write to PC
# read state either from incoming override or from regfile
# TODO: really should be doing MSR in the same way
- pc = state_get(m, self.pc_i, "pc", # read PC
+ pc = state_get(m, core_rst, self.pc_i,
+ "pc", # read PC
self.state_r_pc, StateRegs.PC)
- svstate = state_get(m, self.svstate_i, "svstate", # read SVSTATE
+ svstate = state_get(m, core_rst, self.svstate_i,
+ "svstate", # read SVSTATE
self.state_r_sv, StateRegs.SVSTATE)
# don't write pc every cycle
# address of the next instruction, in the absence of a branch
# depends on the instruction size
- nia = Signal(64, reset_less=True)
+ nia = Signal(64)
# connect up debug signals
# TODO comb += core.icache_rst_i.eq(dbg.icache_rst_o)
exec_insn_valid_i, exec_insn_ready_o,
exec_pc_valid_o, exec_pc_ready_i)
+ # whatever was done above, over-ride it if core reset is held
+ with m.If(core_rst):
+ sync += nia.eq(0)
+
# this bit doesn't have to be in the FSM: connect up to read
# regfiles on demand from DMI
self.do_dmi(m, dbg)