comb = m.d.comb
op = self.i.ctx.op
xer_so_i, xer_ov_i = self.i.xer_so.data, self.i.xer_ov.data
+ xer_so_o, xer_ov_o = self.o.xer_so, self.o.xer_ov
# copy overflow and sticky-overflow. indicate to CompALU if they
# are actually required (oe enabled/set) otherwise the CompALU
comb += oe.eq(op.oe.oe & op.oe.oe_ok)
with m.If(oe):
# XXX see https://bugs.libre-soc.org/show_bug.cgi?id=319#c5
- comb += self.so.eq(xer_so_i[0] | xer_ov_i[0]) # SO
- comb += self.o.xer_so.data.eq(self.so)
- comb += self.o.xer_so.ok.eq(1)
- comb += self.o.xer_ov.data.eq(xer_ov_i)
- comb += self.o.xer_ov.ok.eq(1) # OV/32 is to be set
+ comb += xer_so_o.data.eq(xer_so_i[0] | xer_ov_i[0]) # SO
+ comb += xer_so_o.ok.eq(1)
+ comb += xer_ov_o.data.eq(xer_ov_i)
+ comb += xer_ov_o.ok.eq(1) # OV/32 is to be set
return m
##### sticky overflow and context (both pass-through) #####
if hasattr(self.o, "xer_so"): # hack (for now - for LogicalInputData)
- with m.If(op.oe.oe_ok):
- comb += self.o.xer_so.eq(self.i.xer_so)
+ comb += self.o.xer_so.eq(self.i.xer_so)
comb += self.o.ctx.eq(self.i.ctx)
return m
m = Module()
comb = m.d.comb
op = self.i.ctx.op
+ # ok so there are two different ways this goes:
+ # (1) something involving XER ov in which case so gets modified
+ # and that means we need the modified version of so in CR0
+ # (2) something that does *not* have XER ov, in which case so
+ # has been pass-through just to get it into CR0
+ # in case (1) we don't *have* an xer_so output so put xer_so *input*
+ # into CR0.
if hasattr(self.o, "xer_so"):
xer_so_o = self.o.xer_so.data[0]
else:
- xer_so_o = Const(0, 1)
+ xer_so_o = self.i.xer_so.data[0]
# op requests inversion of the output...
o = Signal.like(self.i.o)
msb_test = Signal(reset_less=True) # set equal to MSB, invert if OP=CMP
is_cmp = Signal(reset_less=True) # true if OP=CMP
is_cmpeqb = Signal(reset_less=True) # true if OP=CMPEQB
- self.so = Signal(1, reset_less=True)
cr0 = Signal(4, reset_less=True)
# TODO: if o[63] is XORed with "operand == OP_CMP"
with m.Default():
comb += o.ok.eq(0)
- ###### context, pass-through #####
+ ###### sticky overflow and context, both pass-through #####
+ comb += self.o.xer_so.data.eq(self.i.xer_so)
comb += self.o.ctx.eq(self.i.ctx)
return m
from nmigen import (Module, Signal, Cat, Repl)
from nmutil.pipemodbase import PipeModBase
from soc.fu.common_output_stage import CommonOutputStage
-from soc.fu.logical.pipe_data import LogicalInputData, LogicalOutputData
+from soc.fu.logical.pipe_data import (LogicalInputData, LogicalOutputData,
+ LogicalOutputDataFinal)
from ieee754.part.partsig import PartitionedSignal
from soc.decoder.power_enums import MicrOp
return LogicalOutputData(self.pspec)
def ospec(self):
- return LogicalOutputData(self.pspec)
+ return LogicalOutputDataFinal(self.pspec)
from soc.fu.logical.logical_input_record import CompLogicalOpSubset
+# input (and output) for logical initial stage (common input)
class LogicalInputData(IntegerData):
regspec = [('INT', 'ra', '0:63'), # RA
('INT', 'rb', '0:63'), # RB/immediate
+ ('XER', 'xer_so', '32'), # bit0: so
]
def __init__(self, pspec):
super().__init__(pspec, False)
self.a, self.b = self.ra, self.rb
+# input to logical final stage (common output)
class LogicalOutputData(IntegerData):
regspec = [('INT', 'o', '0:63'), # RT
('CR', 'cr_a', '0:3'),
- ('XER', 'xer_ca', '34,45'), # bit0: ca, bit1: ca32
+ ('XER', 'xer_so', '32'), # bit0: so
+ ]
+ def __init__(self, pspec):
+ super().__init__(pspec, True)
+ # convenience
+ self.cr0 = self.cr_a
+
+
+# output from logical final stage (common output) - note that XER.so
+# is *not* included (the only reason it's in the input is because of CR0)
+class LogicalOutputDataFinal(IntegerData):
+ regspec = [('INT', 'o', '0:63'), # RT
+ ('CR', 'cr_a', '0:3'),
]
def __init__(self, pspec):
super().__init__(pspec, True)
class LogicalPipeSpec(CommonPipeSpec):
- regspec = (LogicalInputData.regspec, LogicalOutputData.regspec)
+ regspec = (LogicalInputData.regspec, LogicalOutputDataFinal.regspec)
opsubsetkls = CompLogicalOpSubset
yield from ALUHelpers.get_sim_int_ra(res, sim, dec2) # RA
yield from ALUHelpers.get_sim_int_rb(res, sim, dec2) # RB
+ yield from ALUHelpers.get_sim_xer_so(res, sim, dec2) # XER.so
+
+ print("alu get_cu_inputs", res)
return res
# and place it into data_i.b
inp = yield from get_cu_inputs(dec2, sim)
+ print ("set alu inputs", inp)
yield from ALUHelpers.set_int_ra(alu, dec2, inp)
yield from ALUHelpers.set_int_rb(alu, dec2, inp)
+ yield from ALUHelpers.set_xer_so(alu, dec2, inp)
# This test bench is a bit different than is usual. Initially when I
initial_regs[2] = random.randint(0, (1 << 64)-1)
self.add_case(Program(lst, bigendian), initial_regs)
+ def case_rand_(self):
+ insns = ["and.", "or.", "xor.", "eqv.", "andc.",
+ "orc.", "nand.", "nor."]
+ for XER in [0, 0xe00c0000]:
+ for i in range(40):
+ choice = random.choice(insns)
+ lst = [f"{choice} 3, 1, 2"]
+ initial_regs = [0] * 32
+ initial_regs[1] = random.randint(0, (1 << 64)-1)
+ initial_regs[2] = random.randint(0, (1 << 64)-1)
+ self.add_case(Program(lst, bigendian), initial_regs,
+ initial_sprs = {'XER': XER})
+
+ def case_rand_imm_so(self):
+ insns = ["andi.", "andis."]
+ for i in range(1):
+ choice = random.choice(insns)
+ imm = random.randint(0, (1 << 16)-1)
+ lst = [f"{choice} 3, 1, {imm}"]
+ print(lst)
+ initial_regs = [0] * 32
+ initial_regs[1] = random.randint(0, (1 << 64)-1)
+ initial_sprs = {'XER': 0xe00c0000}
+
+ self.add_case(Program(lst, bigendian), initial_regs,
+ initial_sprs=initial_sprs)
+
def case_rand_imm_logical(self):
insns = ["andi.", "andis.", "ori", "oris", "xori", "xoris"]
for i in range(10):
yield from ALUHelpers.get_wr_sim_cr_a(sim_o, sim, dec2)
ALUHelpers.check_cr_a(self, res, sim_o, "CR%d %s" % (cridx, code))
+ ALUHelpers.check_xer_ca(self, res, sim_o, code)
ALUHelpers.check_int_o(self, res, sim_o, code)
res['xer_ov'] = expected_ov | (expected_ov32 << 1)
def get_sim_xer_so(res, sim, dec2):
- oe = yield dec2.e.do.oe.oe
- oe_ok = yield dec2.e.do.oe.ok
- xer_in = yield dec2.e.xer_in
- if xer_in or (oe and oe_ok):
- res['xer_so'] = 1 if sim.spr['XER'][XER_bits['SO']] else 0
+ yield
+ #oe = yield dec2.e.do.oe.oe
+ #oe_ok = yield dec2.e.do.oe.ok
+ #xer_in = yield dec2.e.xer_in
+ #if xer_in or (oe and oe_ok):
+ res['xer_so'] = 1 if sim.spr['XER'][XER_bits['SO']] else 0
def check_slow_spr1(dut, res, sim_o, msg):
if 'spr1' in res: