Merge branch 'master' of ssh://git.libre-riscv.org:922/soc
authorTobias Platen <tplaten@posteo.de>
Wed, 3 Jun 2020 12:19:48 +0000 (14:19 +0200)
committerTobias Platen <tplaten@posteo.de>
Wed, 3 Jun 2020 12:19:48 +0000 (14:19 +0200)
24 files changed:
libreriscv
src/soc/decoder/power_decoder2.py
src/soc/decoder/power_regspec_map.py
src/soc/experiment/compalu_multi.py
src/soc/experiment/test/test_compalu_multi.py
src/soc/fu/alu/pipe_data.py
src/soc/fu/alu/test/test_pipe_caller.py
src/soc/fu/branch/main_stage.py
src/soc/fu/branch/pipe_data.py
src/soc/fu/branch/test/test_pipe_caller.py
src/soc/fu/compunits/compunits.py
src/soc/fu/compunits/test/test_alu_compunit.py
src/soc/fu/compunits/test/test_branch_compunit.py
src/soc/fu/compunits/test/test_compunit.py
src/soc/fu/compunits/test/test_logical_compunit.py
src/soc/fu/compunits/test/test_shiftrot_compunit.py
src/soc/fu/cr/pipe_data.py
src/soc/fu/logical/pipe_data.py
src/soc/fu/logical/test/test_pipe_caller.py
src/soc/fu/regspec.py
src/soc/fu/shift_rot/pipe_data.py
src/soc/fu/spr/pipe_data.py
src/soc/fu/trap/main_stage.py
src/soc/regfile/util.py [new file with mode: 0644]

index 71d70e4c753d1171c1fb83e1b9f9d78c9372f8d1..1970241a6db97d4ace1e053e72f2a3d9462e98b2 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 71d70e4c753d1171c1fb83e1b9f9d78c9372f8d1
+Subproject commit 1970241a6db97d4ace1e053e72f2a3d9462e98b2
index e50d1ca5d35d45e1297a7d24e8ebe06d38b5b95e..33e346ae7b0c42fd88629581f187d4ed2cf58da4 100644 (file)
@@ -60,10 +60,14 @@ class DecodeA(Elaboratable):
         # decode Fast-SPR based on instruction type
         op = self.dec.op
         # BC or BCREG: potential implicit register (CTR) NOTE: same in DecodeOut
-        with m.If((op.internal_op == InternalOp.OP_BC) |
-                  (op.internal_op == InternalOp.OP_BCREG)):
-            with m.If(~self.dec.BO[2] |        # 3.0B p38 BO2=0, use CTR reg
-                       self.dec.FormXL.XO[9]): # 3.0B p38 top bit of XO
+        with m.If(op.internal_op == InternalOp.OP_BC):
+            with m.If(~self.dec.BO[2]): # 3.0B p38 BO2=0, use CTR reg
+                comb += self.fast_out.data.eq(FastRegs.CTR) # constant: CTR
+                comb += self.fast_out.ok.eq(1)
+        with m.Elif(op.internal_op == InternalOp.OP_BCREG):
+            xo9 = self.dec.FormXL.XO[9] # 3.0B p38 top bit of XO
+            xo5 = self.dec.FormXL.XO[5] # 3.0B p38
+            with m.If(xo9 & ~xo5):
                 comb += self.fast_out.data.eq(FastRegs.CTR) # constant: CTR
                 comb += self.fast_out.ok.eq(1)
 
@@ -157,13 +161,17 @@ class DecodeB(Elaboratable):
 
         # decode SPR2 based on instruction type
         op = self.dec.op
-        # BCREG implicitly uses LR or TAR for 2nd reg (TODO: TAR)
+        # BCREG implicitly uses LR or TAR for 2nd reg
         # CTR however is already in fast_spr1 *not* 2.
-        with m.If((op.internal_op == InternalOp.OP_BC) |
-                 (op.internal_op == InternalOp.OP_BCREG)):
-            with m.If(~self.dec.FormXL.XO[9]): # 3.0B p38 top bit of XO
+        with m.If(op.internal_op == InternalOp.OP_BCREG):
+            xo9 = self.dec.FormXL.XO[9] # 3.0B p38 top bit of XO
+            xo5 = self.dec.FormXL.XO[5] # 3.0B p38
+            with m.If(~xo9):
                 comb += self.fast_out.data.eq(FastRegs.LR)
                 comb += self.fast_out.ok.eq(1)
+            with m.Elif(xo5):
+                comb += self.fast_out.data.eq(FastRegs.TAR)
+                comb += self.fast_out.ok.eq(1)
 
         return m
 
@@ -245,6 +253,7 @@ class DecodeOut2(Elaboratable):
     def __init__(self, dec):
         self.dec = dec
         self.sel_in = Signal(OutSel, reset_less=True)
+        self.lk = Signal(reset_less=True)
         self.insn_in = Signal(32, reset_less=True)
         self.reg_out = Data(5, "reg_o")
         self.fast_out = Data(3, "fast_o")
@@ -262,7 +271,7 @@ class DecodeOut2(Elaboratable):
         op = self.dec.op
         with m.If((op.internal_op == InternalOp.OP_BC) |
                   (op.internal_op == InternalOp.OP_BCREG)):
-            with m.If(self.dec.op.lk & self.dec.LK): # "link" mode
+            with m.If(self.lk): # "link" mode
                 comb += self.fast_out.data.eq(FastRegs.LR) # constant: LR
                 comb += self.fast_out.ok.eq(1)
 
@@ -516,6 +525,7 @@ class PowerDecode2(Elaboratable):
         comb += dec_c.sel_in.eq(self.dec.op.in3_sel)
         comb += dec_o.sel_in.eq(self.dec.op.out_sel)
         comb += dec_o2.sel_in.eq(self.dec.op.out_sel)
+        comb += dec_o2.lk.eq(self.e.lk)
         comb += dec_rc.sel_in.eq(self.dec.op.rc_sel)
         comb += dec_oe.sel_in.eq(self.dec.op.rc_sel) # XXX should be OE sel
         comb += dec_cr_in.sel_in.eq(self.dec.op.cr_in)
@@ -600,7 +610,16 @@ class PowerDecode2(Elaboratable):
         to Function Unit port regfiles (read-enable, read regnum, write regnum)
         regfile and regname arguments are fields 1 and 2 from a given regspec.
         """
-        return regspec_decode(self, regfile, regname)
+        return regspec_decode(self.e, regfile, regname)
+
+    def rdflags(self, cu):
+        rdl = []
+        for idx in range(cu.n_src):
+            regfile, regname, _ = cu.get_in_spec(idx)
+            rdflag, read, write = self.regspecmap(regfile, regname)
+            rdl.append(rdflag)
+        print ("rdflags", rdl)
+        return Cat(*rdl)
 
 
 if __name__ == '__main__':
index dec4b3cde7916aeadc56a7e7cc15ec047a7cea69..1bc486da2cc7014011dc6abaeb84876ecb6b25bd 100644 (file)
@@ -6,6 +6,7 @@ see https://libre-soc.org/3d_gpu/architecture/regfile/ section on regspecs
 """
 from nmigen import Const
 from soc.regfile.regfiles import XERRegs, FastRegs
+from soc.decoder.power_enums import CryIn
 
 
 def regspec_decode(e, regfile, name):
@@ -70,11 +71,11 @@ def regspec_decode(e, regfile, name):
         CA = 1<<XERRegs.CA
         OV = 1<<XERRegs.OV
         if name == 'xer_so':
-            return e.oe.oe & e.oe.oe_ok, SO, SO
+            return e.oe.oe[0] & e.oe.oe_ok, SO, SO
         if name == 'xer_ov':
-            return e.oe.oe & e.oe.oe_ok, OV, OV
+            return e.oe.oe[0] & e.oe.oe_ok, OV, OV
         if name == 'xer_ca':
-            return e.input_carry, CA, CA
+            return (e.input_carry == CryIn.CA.value), CA, CA
 
     if regfile == 'FAST':
         # FAST register numbering is *unary* encoded
@@ -91,8 +92,10 @@ def regspec_decode(e, regfile, name):
             return Const(1), MSR, MS # TODO: detect read-conditions
         # TODO: remap the SPR numbers to FAST regs
         if name == 'spr1':
-            return e.read_spr1.ok, 1<<e.read_spr1.data, 1<<e.write_fast1.data
+            return e.read_fast1.ok, 1<<e.read_fast1.data, 1<<e.write_fast1.data
         if name == 'spr2':
-            return e.read_spr2.ok, 1<<e.read_spr2.data, 1<<e.write_fast2.data
+            return e.read_fast2.ok, 1<<e.read_fast2.data, 1<<e.write_fast2.data
 
-    assert False, "regspec not found %s %d" % (repr(regspec), idx)
+    if regfile == 'SPR':
+        assert False, "regfile TODO %s %s %d" % (refgile, repr(regspec), idx)
+    assert False, "regspec not found %s %s %d" % (refgile, repr(regspec), idx)
index baebed0974d86b6af81df45cbdbec14a9db68bb9..4c1f019170159f6b5d57d40f0a06c67cf3e5375d 100644 (file)
@@ -204,6 +204,12 @@ class MultiCompUnit(RegSpecALUAPI, Elaboratable):
         m.d.comb += wr_any.eq(self.wr.go.bool())
         m.d.comb += req_done.eq(wr_any & ~self.alu.n.ready_i & \
                 ((req_l.q & self.wrmask) == 0))
+        # argh, complicated hack: if there are no regs to write,
+        # instead of waiting for regs that are never going to happen,
+        # we indicate "done" when the ALU is "done"
+        with m.If((self.wrmask == 0) & \
+                    self.alu.n.ready_i & self.alu.n.valid_o & self.busy_o):
+            m.d.comb += req_done.eq(1)
 
         # shadow/go_die
         reset = Signal(reset_less=True)
index e80f231724ec44261f8cf380d6f6855d76f7b14a..9399908d6d32e65d2440584f6ee2676e3597cb52 100644 (file)
@@ -137,9 +137,13 @@ class CompUnitParallelTest:
         self.op = 0
         self.inv_a = self.zero_a = 0
         self.imm = self.imm_ok = 0
+        self.imm_control = (0, 0)
         self.rdmaskn = (0, 0)
         # input data:
-        self.a = self.b = 0
+        self.operands = (0, 0)
+
+        # Indicates completion of the sub-processes
+        self.rd_complete = [False, False]
 
     def driver(self):
         print("Begin parallel test.")
@@ -149,18 +153,25 @@ class CompUnitParallelTest:
     def operation(self, a, b, op, inv_a=0, imm=0, imm_ok=0, zero_a=0,
                   rdmaskn=(0, 0)):
         # store data for the operation
-        self.a = a
-        self.b = b
+        self.operands = (a, b)
         self.op = op
         self.inv_a = inv_a
         self.imm = imm
         self.imm_ok = imm_ok
         self.zero_a = zero_a
+        self.imm_control = (zero_a, imm_ok)
         self.rdmaskn = rdmaskn
 
+        # Initialize completion flags
+        self.rd_complete = [False, False]
+
         # trigger operation cycle
         yield from self.issue()
 
+        # check that the sub-processes completed, before the busy_o cycle ended
+        for completion in self.rd_complete:
+            assert completion
+
     def issue(self):
         # issue_i starts inactive
         yield self.dut.issue_i.eq(0)
@@ -246,9 +257,8 @@ class CompUnitParallelTest:
         # likewise, if the read mask is active
         # TODO: don't exit the process, monitor rd instead to ensure it
         #       doesn't rise on its own
-        if self.rdmaskn[rd_idx] \
-                or (rd_idx == 0 and self.zero_a) \
-                or (rd_idx == 1 and self.imm_ok):
+        if self.rdmaskn[rd_idx] or self.imm_control[rd_idx]:
+            self.rd_complete[rd_idx] = True
             return
 
         # issue_i has risen. rel must rise on the next cycle
@@ -268,8 +278,14 @@ class CompUnitParallelTest:
         rel = yield self.dut.rd.rel[rd_idx]
         assert rel
 
-        # assert go for one cycle
+        # assert go for one cycle, passing along the operand value
         yield self.dut.rd.go[rd_idx].eq(1)
+        yield self.dut.src_i[rd_idx].eq(self.operands[rd_idx])
+        # check that the operand was sent to the alu
+        # TODO: Properly check the alu protocol
+        yield Settle()
+        alu_input = yield self.dut.get_in(rd_idx)
+        assert alu_input == self.operands[rd_idx]
         yield
 
         # rel must keep high, since go was inactive in the last cycle
@@ -278,6 +294,7 @@ class CompUnitParallelTest:
 
         # finish the go one-clock pulse
         yield self.dut.rd.go[rd_idx].eq(0)
+        yield self.dut.src_i[rd_idx].eq(0)
         yield
 
         # rel must have gone low in response to go being high
@@ -285,8 +302,10 @@ class CompUnitParallelTest:
         rel = yield self.dut.rd.rel[rd_idx]
         assert not rel
 
-        # TODO: also when dut.rd.go is set, put the expected value into
-        # the src_i.  use dut.get_in[rd_idx] to do so
+        self.rd_complete[rd_idx] = True
+
+        # TODO: check that rel doesn't rise again until the end of the
+        #       busy_o cycle
 
     def wr(self, wr_idx):
         # monitor self.dut.wr.req[rd_idx] and sets dut.wr.go[idx] for one cycle
index b9423944877d54a8bb4113f4dce8a44dc5e6e9a1..5b9766e295397fb74c94ecf4a086e6868605599c 100644 (file)
@@ -68,7 +68,3 @@ class ALUOutputData(IntegerData):
 class ALUPipeSpec(CommonPipeSpec):
     regspec = (ALUInputData.regspec, ALUOutputData.regspec)
     opsubsetkls = CompALUOpSubset
-    def rdflags(self, e): # in order of regspec
-        reg1_ok = e.read_reg1.ok # RA
-        reg2_ok = e.read_reg2.ok # RB
-        return Cat(reg1_ok, reg2_ok, 1, 1) # RA RB CA SO
index 8517dc741312b8fbd0c7f588ae17423f5b4af7e0..50e8e9b11c01153f6f3f7ebbe36b5658db67a66f 100644 (file)
@@ -6,7 +6,7 @@ import unittest
 from soc.decoder.isa.caller import ISACaller, special_sprs
 from soc.decoder.power_decoder import (create_pdecode)
 from soc.decoder.power_decoder2 import (PowerDecode2)
-from soc.decoder.power_enums import (XER_bits, Function, InternalOp)
+from soc.decoder.power_enums import (XER_bits, Function, InternalOp, CryIn)
 from soc.decoder.selectable_int import SelectableInt
 from soc.simulator.program import Program
 from soc.decoder.isa.all import ISA
@@ -24,41 +24,64 @@ class TestCase:
         self.name = name
 
 
-def set_alu_inputs(alu, dec2, sim):
-    # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
-    # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
-    # and place it into data_i.b
+def get_cu_inputs(dec2, sim):
+    """naming (res) must conform to ALUFunctionUnit input regspec
+    """
+    res = {}
 
+    # RA (or RC)
     reg1_ok = yield dec2.e.read_reg1.ok
     if reg1_ok:
         data1 = yield dec2.e.read_reg1.data
-        data1 = sim.gpr(data1).value
-    else:
-        data1 = 0
+        res['ra'] = sim.gpr(data1).value
+
+    # RB (or immediate)
+    reg2_ok = yield dec2.e.read_reg2.ok
+    if reg2_ok:
+        data2 = yield dec2.e.read_reg2.data
+        res['rb'] = sim.gpr(data2).value
+
+    # XER.ca
+    cry_in = yield dec2.e.input_carry
+    if cry_in == CryIn.CA.value:
+        carry = 1 if sim.spr['XER'][XER_bits['CA']] else 0
+        carry32 = 1 if sim.spr['XER'][XER_bits['CA32']] else 0
+        res['xer_ca'] = carry | (carry32<<1)
+
+    # XER.so
+    oe = yield dec2.e.oe.data[0] & dec2.e.oe.ok
+    if oe:
+        so = 1 if sim.spr['XER'][XER_bits['SO']] else 0
+        res['xer_so'] = so
+
+    return res
+
 
-    yield alu.p.data_i.a.eq(data1)
+
+def set_alu_inputs(alu, dec2, sim):
+    # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
+    # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
+    # and place it into data_i.b
+
+    inp = yield from get_cu_inputs(dec2, sim)
+    if 'ra' in inp:
+        yield alu.p.data_i.a.eq(inp['ra'])
+    if 'rb' in inp:
+        yield alu.p.data_i.b.eq(inp['rb'])
 
     # If there's an immediate, set the B operand to that
-    reg2_ok = yield dec2.e.read_reg2.ok
     imm_ok = yield dec2.e.imm_data.imm_ok
     if imm_ok:
         data2 = yield dec2.e.imm_data.imm
-    elif reg2_ok:
-        data2 = yield dec2.e.read_reg2.data
-        data2 = sim.gpr(data2).value
-    else:
-        data2 = 0
-    yield alu.p.data_i.b.eq(data2)
-
-
+        yield alu.p.data_i.b.eq(data2)
 
-def set_extra_alu_inputs(alu, dec2, sim):
-    carry = 1 if sim.spr['XER'][XER_bits['CA']] else 0
-    carry32 = 1 if sim.spr['XER'][XER_bits['CA32']] else 0
-    yield alu.p.data_i.xer_ca[0].eq(carry)
-    yield alu.p.data_i.xer_ca[1].eq(carry32)
-    so = 1 if sim.spr['XER'][XER_bits['SO']] else 0
-    yield alu.p.data_i.xer_so.eq(so)
+    if 'xer_ca' in inp:
+        yield alu.p.data_i.xer_ca.eq(inp['xer_ca'])
+        print ("extra inputs: CA/32", bin(inp['xer_ca']))
+    if 'xer_so' in inp:
+        so = inp['xer_so']
+        print ("extra inputs: so", so)
+        yield alu.p.data_i.xer_so.eq(so)
 
 
 # This test bench is a bit different than is usual. Initially when I
@@ -204,7 +227,6 @@ class TestRunner(FHDLTestCase):
                     fn_unit = yield pdecode2.e.fn_unit
                     self.assertEqual(fn_unit, Function.ALU.value)
                     yield from set_alu_inputs(alu, pdecode2, simulator)
-                    yield from set_extra_alu_inputs(alu, pdecode2, simulator)
                     yield
                     opname = code.split(' ')[0]
                     yield from simulator.call(opname)
index f145a63254cf9918a94955d812b6b5337a2e57fe..27076a56e763e9ec6ad2f58bab941d7aeda79e5a 100644 (file)
@@ -76,18 +76,17 @@ class BranchMainStage(PipeModBase):
             comb += br_addr.eq(br_imm_addr + cia)
 
         # fields for conditional branches (BO and BI are same for BC and BCREG)
-        # NOTE: here, BO and BI we would like be treated as CR regfile
-        # selectors (similar to RA, RB, RS, RT).  see comment here:
-        # https://bugs.libre-soc.org/show_bug.cgi?id=313#c2
         b_fields = self.fields.FormB
         BO = b_fields.BO[0:-1]
-        BI = b_fields.BI[0:-1][0:2]
+        BI = b_fields.BI[0:-1][0:2] # CR0-7 selected already in PowerDecode2.
 
-        cr_bits = Array([cr[3-i] for i in range(4)])
+        cr_bits = Array([cr[3-i] for i in range(4)]) # invert. Because POWER.
 
         # The bit of CR selected by BI
+        bi = Signal(2, reset_less=True)
         cr_bit = Signal(reset_less=True)
-        comb += cr_bit.eq(cr_bits[BI])
+        comb += bi.eq(BI)                 # reduces gate-count due to pmux
+        comb += cr_bit.eq(cr_bits[bi])
 
         # Whether ctr is written to on a conditional branch
         ctr_write = Signal(reset_less=True)
@@ -134,7 +133,11 @@ class BranchMainStage(PipeModBase):
                 comb += ctr_o.ok.eq(ctr_write)
             #### branch conditional reg ####
             with m.Case(InternalOp.OP_BCREG):
-                comb += br_imm_addr.eq(Cat(Const(0, 2), spr2[2:]))
+                xo = self.fields.FormXL.XO[0:-1]
+                with m.If(xo[9] & ~xo[5]):
+                    comb += br_imm_addr.eq(Cat(Const(0, 2), spr1[2:]))
+                with m.Else():
+                    comb += br_imm_addr.eq(Cat(Const(0, 2), spr2[2:]))
                 comb += br_taken.eq(bc_taken)
                 comb += ctr_o.ok.eq(ctr_write)
 
index f8481db397841a7071a07e933348b3deadf7d83e..78c4f0f972807094f19159df3b8be80e4f65da6f 100644 (file)
@@ -93,8 +93,3 @@ class BranchOutputData(IntegerData):
 class BranchPipeSpec(CommonPipeSpec):
     regspec = (BranchInputData.regspec, BranchOutputData.regspec)
     opsubsetkls = CompBROpSubset
-    def rdflags(self, e): # in order of regspec
-        cr1_en = e.read_cr1.ok # CR A
-        fast1_ok = e.read_fast1.ok # SPR1
-        fast2_ok = e.read_fast2.ok # SPR2
-        return Cat(fast1_ok, fast2_ok, cr1_en, 1) # SPR1 SPR2 CR CIA
index ffbb373e97756a7b2b58137d406f7d0f1dc9ef5a..0403199aee1e53f632638a44325cfa5370be64ac 100644 (file)
@@ -16,6 +16,7 @@ from soc.fu.branch.pipeline import BranchBasePipe
 from soc.fu.branch.pipe_data import BranchPipeSpec
 import random
 
+from soc.regfile.util import fast_reg_to_spr # HACK!
 
 class TestCase:
     def __init__(self, program, regs, sprs, cr, name):
@@ -55,6 +56,38 @@ def get_rec_width(rec):
 test_data = []
 
 
+def get_cu_inputs(dec2, sim):
+    """naming (res) must conform to BranchFunctionUnit input regspec
+    """
+    res = {}
+
+    # CIA (PC)
+    res['cia'] = sim.pc.CIA.value
+
+    fast1_en = yield dec2.e.read_fast1.ok
+    if fast1_en:
+        fast1_sel = yield dec2.e.read_fast1.data
+        spr1_sel = fast_reg_to_spr(fast1_sel)
+        spr1_data = sim.spr[spr1_sel].value
+        res['spr1'] = spr1_data
+
+    fast2_en = yield dec2.e.read_fast2.ok
+    if fast2_en:
+        fast2_sel = yield dec2.e.read_fast2.data
+        spr2_sel = fast_reg_to_spr(fast2_sel)
+        spr2_data = sim.spr[spr2_sel].value
+        res['spr2'] = spr2_data
+
+    cr_en = yield dec2.e.read_cr1.ok
+    if cr_en:
+        cr_sel = yield dec2.e.read_cr1.data
+        cr = sim.crl[cr_sel].get_range().value
+        res['cr_a'] = cr
+
+    print ("get inputs", res)
+    return res
+
+
 class BranchTestCase(FHDLTestCase):
     def __init__(self, name):
         super().__init__(name)
@@ -117,7 +150,7 @@ class BranchTestCase(FHDLTestCase):
                                      initial_sprs=initial_sprs,
                                      initial_cr=cr)
 
-        
+
 
     def test_ilang(self):
         pspec = BranchPipeSpec(id_wid=2)
@@ -173,7 +206,6 @@ class TestRunner(FHDLTestCase):
                     # ask the decoder to decode this binary data (endian'd)
                     yield pdecode2.dec.bigendian.eq(0)  # little / big?
                     yield instruction.eq(ins)          # raw binary instr.
-                    yield branch.p.data_i.cia.eq(simulator.pc.CIA.value)
                     # note, here, the op will need further decoding in order
                     # to set the correct SPRs on SPR1/2/3.  op_bc* require
                     # spr1 to be set to CTR, op_bctar require spr2 to be
@@ -208,6 +240,9 @@ class TestRunner(FHDLTestCase):
             print(f"real: {branch_addr:x}, sim: {sim.pc.CIA.value:x}")
             self.assertEqual(branch_addr, sim.pc.CIA.value, code)
 
+        # TODO: check write_fast1 as well (should contain CTR)
+
+        # TODO: this should be checking write_fast2
         lk = yield dec2.e.lk
         branch_lk = yield branch.n.data_o.lr.ok
         self.assertEqual(lk, branch_lk, code)
@@ -216,27 +251,18 @@ class TestRunner(FHDLTestCase):
             self.assertEqual(sim.spr['LR'], branch_lr, code)
 
     def set_inputs(self, branch, dec2, sim):
-        yield branch.p.data_i.spr1.eq(sim.spr['CTR'].value)
         print(f"cr0: {sim.crl[0].get_range()}")
 
-        insn_type = yield dec2.e.insn_type
-        if insn_type == InternalOp.OP_BCREG.value:
-            xo9 = yield dec2.dec.FormXL.XO[9]
-            xo5 = yield dec2.dec.FormXL.XO[5]
-            if xo9 == 0:
-                yield branch.p.data_i.spr2.eq(sim.spr['LR'].value)
-            elif xo5 == 1:
-                yield branch.p.data_i.spr2.eq(sim.spr['TAR'].value)
-            else:
-                yield branch.p.data_i.spr2.eq(sim.spr['CTR'].value)
-
-        cr_en = yield dec2.e.read_cr1.ok
-        if cr_en:
-            cr_sel = yield dec2.e.read_cr1.data
-            cr = sim.crl[cr_sel].get_range().value
-            yield branch.p.data_i.cr.eq(cr)
-            full_cr = sim.cr.get_range().value
-            print(f"full cr: {full_cr:x}, sel: {cr_sel}, cr: {cr:x}")
+        inp = yield from get_cu_inputs(dec2, sim)
+
+        if 'cia' in inp:
+            yield branch.p.data_i.cia.eq(inp['cia'])
+        if 'spr1' in inp:
+            yield branch.p.data_i.spr1.eq(inp['spr1'])
+        if 'spr2' in inp:
+            yield branch.p.data_i.spr2.eq(inp['spr2'])
+        if 'cr_a' in inp:
+            yield branch.p.data_i.cr.eq(inp['cr_a'])
 
 
 if __name__ == "__main__":
index 203055ad1cf3e3f1eabf0e80d93ad3157fe0c6c6..7eaecdb3a949498a70b7e52fa61c9c93a375a07b 100644 (file)
@@ -40,6 +40,8 @@ see:
 
 """
 
+# imports
+
 from nmigen import Cat
 from nmigen.cli import rtlil
 from soc.experiment.compalu_multi import MultiCompUnit
@@ -91,10 +93,6 @@ class FunctionUnitBaseSingle(MultiCompUnit):
         alu = pipekls(pspec)                     # create actual NNNBasePipe
         super().__init__(regspec, alu, opsubset) # pass to MultiCompUnit
 
-    def rdflags(self, e):
-        print (dir(self.alu))
-        return self.alu.pspec.rdflags(e)
-
 
 ##############################################################
 # TODO: ReservationStations-based (FunctionUnitBaseConcurrent)
index 124752501b21db14d1f9879c09bbaa26a39d357d..7de152ab7efeafe13cbab01abb39b7a72ea39748 100644 (file)
@@ -2,6 +2,7 @@ import unittest
 from soc.decoder.power_enums import (XER_bits, Function)
 
 # XXX bad practice: use of global variables
+from soc.fu.alu.test.test_pipe_caller import get_cu_inputs
 from soc.fu.alu.test.test_pipe_caller import ALUTestCase # creates the tests
 from soc.fu.alu.test.test_pipe_caller import test_data # imports the data
 
@@ -17,29 +18,7 @@ class ALUTestRunner(TestRunner):
     def get_cu_inputs(self, dec2, sim):
         """naming (res) must conform to ALUFunctionUnit input regspec
         """
-        res = {}
-
-        # RA (or RC)
-        reg1_ok = yield dec2.e.read_reg1.ok
-        if reg1_ok:
-            data1 = yield dec2.e.read_reg1.data
-            res['ra'] = sim.gpr(data1).value
-
-        # RB (or immediate)
-        reg2_ok = yield dec2.e.read_reg2.ok
-        if reg2_ok:
-            data2 = yield dec2.e.read_reg2.data
-            res['rb'] = sim.gpr(data2).value
-
-        # XER.ca
-        carry = 1 if sim.spr['XER'][XER_bits['CA']] else 0
-        carry32 = 1 if sim.spr['XER'][XER_bits['CA32']] else 0
-        res['xer_ca'] = carry | (carry32<<1)
-
-        # XER.so
-        so = 1 if sim.spr['XER'][XER_bits['SO']] else 0
-        res['xer_so'] = so
-
+        res = yield from get_cu_inputs(dec2, sim)
         return res
 
     def check_cu_outputs(self, res, dec2, sim, code):
index 312d3348b69787870a068a90bac9750d3a52ec31..9d4503ced6f44f89b3cbef5fa115b57ddefef2cc 100644 (file)
@@ -2,26 +2,18 @@ import unittest
 from soc.decoder.power_enums import (XER_bits, Function, spr_dict, SPR)
 
 # XXX bad practice: use of global variables
-from soc.fu.branch.test.test_pipe_caller import BranchTestCase
+from soc.fu.branch.test.test_pipe_caller import BranchTestCase, get_cu_inputs
 from soc.fu.branch.test.test_pipe_caller import test_data
 
 from soc.fu.compunits.compunits import BranchFunctionUnit
 from soc.fu.compunits.test.test_compunit import TestRunner
 
-from soc.regfile.regfiles import FastRegs
+from soc.regfile.util import fast_reg_to_spr # HACK!
 
 """
     def assert_outputs(self, branch, dec2, sim, prev_nia, code):
 """
 
-def fast_reg_to_spr(spr_num):
-    if spr_num == FastRegs.CTR:
-        return SPR.CTR.value
-    elif spr_num == FastRegs.LR:
-        return SPR.LR.value
-    elif spr_num == FastRegs.TAR:
-        return SPR.TAR.value
-
 
 class BranchTestRunner(TestRunner):
     def __init__(self, test_data):
@@ -31,35 +23,7 @@ class BranchTestRunner(TestRunner):
     def get_cu_inputs(self, dec2, sim):
         """naming (res) must conform to BranchFunctionUnit input regspec
         """
-        res = {}
-        full_reg = yield dec2.e.read_cr_whole
-
-        # CIA (PC)
-        res['cia'] = sim.pc.CIA.value
-
-        # CR A
-        cr1_en = yield dec2.e.read_cr1.ok
-        if cr1_en:
-            cr1_sel = yield dec2.e.read_cr1.data
-            res['cr_a'] = sim.crl[cr1_sel].get_range().value
-
-        # Fast1
-        spr_ok = yield dec2.e.read_fast1.ok
-        spr_num = yield dec2.e.read_fast1.data
-        # HACK
-        spr_num = fast_reg_to_spr(spr_num)
-        if spr_ok:
-            res['spr1'] = sim.spr[spr_dict[spr_num].SPR].value
-
-        # SPR2
-        spr_ok = yield dec2.e.read_fast2.ok
-        spr_num = yield dec2.e.read_fast2.data
-        # HACK
-        spr_num = fast_reg_to_spr(spr_num)
-        if spr_ok:
-            res['spr2'] = sim.spr[spr_dict[spr_num].SPR].value
-
-        print ("get inputs", res)
+        res = yield from get_cu_inputs(dec2, sim)
         return res
 
     def check_cu_outputs(self, res, dec2, sim, code):
index 605b9127c1b1cf069d6b15a1c9d5c6536d9ac8d2..ff884201371dab8e96b020119912f3e25014a7bc 100644 (file)
@@ -153,7 +153,9 @@ class TestRunner(FHDLTestCase):
                     inp = get_inp_indexed(cu, iname)
 
                     # reset read-operand mask
-                    rdmask = cu.rdflags(pdecode2.e)
+                    rdmask = pdecode2.rdflags(cu)
+                    #print ("hardcoded rdmask", cu.rdflags(pdecode2.e))
+                    #print ("decoder rdmask", rdmask)
                     yield cu.rdmaskn.eq(~rdmask)
 
                     # reset write-operand mask
@@ -162,16 +164,17 @@ class TestRunner(FHDLTestCase):
                         fname = find_ok(wrok.fields)
                         yield getattr(wrok, fname).eq(0)
 
-                    # first set inputs to zero
-                    for idx in range(cu.n_src):
-                        cu_in = cu.get_in(idx)
-                        yield cu_in.eq(0)
+                    yield Settle()
 
                     # set inputs into CU
                     rd_rel_o = yield cu.rd.rel
                     wr_rel_o = yield cu.wr.rel
                     print ("before inputs, rd_rel, wr_rel: ",
                             bin(rd_rel_o), bin(wr_rel_o))
+                    assert wr_rel_o == 0, "wr.rel %s must be zero. "\
+                                "previous instr not written all regs\n"\
+                                "respec %s" % \
+                                (bin(wr_rel_o), cu.rwid[1])
                     yield from set_cu_inputs(cu, inp)
                     yield
                     rd_rel_o = yield cu.rd.rel
@@ -185,6 +188,7 @@ class TestRunner(FHDLTestCase):
                     yield from sim.call(opname)
                     index = sim.pc.CIA.value//4
 
+                    yield Settle()
                     # get all outputs (one by one, just "because")
                     res = yield from get_cu_outputs(cu, code)
 
index 8745b0b1e7810ed2ea3d3e343b4b27e7da347144..2591bcd41820740c13ba476306e901d18370f3da 100644 (file)
@@ -2,7 +2,7 @@ import unittest
 from soc.decoder.power_enums import (XER_bits, Function)
 
 # XXX bad practice: use of global variables
-from soc.fu.logical.test.test_pipe_caller import LogicalTestCase
+from soc.fu.logical.test.test_pipe_caller import LogicalTestCase, get_cu_inputs
 from soc.fu.logical.test.test_pipe_caller import test_data
 
 from soc.fu.compunits.compunits import LogicalFunctionUnit
@@ -17,20 +17,7 @@ class LogicalTestRunner(TestRunner):
     def get_cu_inputs(self, dec2, sim):
         """naming (res) must conform to LogicalFunctionUnit input regspec
         """
-        res = {}
-
-        # RA (or RC)
-        reg1_ok = yield dec2.e.read_reg1.ok
-        if reg1_ok:
-            data1 = yield dec2.e.read_reg1.data
-            res['ra'] = sim.gpr(data1).value
-
-        # RB (or immediate)
-        reg2_ok = yield dec2.e.read_reg2.ok
-        if reg2_ok:
-            data2 = yield dec2.e.read_reg2.data
-            res['rb'] = sim.gpr(data2).value
-
+        res = yield from get_cu_inputs(dec2, sim)
         return res
 
     def check_cu_outputs(self, res, dec2, sim, code):
index aeb7de8baf2941db79bff34c5355f49f685c4e3b..e802f7ed4ea5eb4becf7d820db4c1b03935b15de 100644 (file)
@@ -8,6 +8,8 @@ from soc.fu.shift_rot.test.test_pipe_caller import test_data
 from soc.fu.compunits.compunits import ShiftRotFunctionUnit
 from soc.fu.compunits.test.test_compunit import TestRunner
 
+from soc.decoder.power_enums import CryIn
+
 
 class ShiftRotTestRunner(TestRunner):
     def __init__(self, test_data):
@@ -38,9 +40,11 @@ class ShiftRotTestRunner(TestRunner):
             res['rc'] = sim.gpr(data3).value
 
         # XER.ca
-        carry = 1 if sim.spr['XER'][XER_bits['CA']] else 0
-        carry32 = 1 if sim.spr['XER'][XER_bits['CA32']] else 0
-        res['xer_ca'] = carry | (carry32<<1)
+        cry_in = yield dec2.e.input_carry
+        if cry_in == CryIn.CA.value:
+            carry = 1 if sim.spr['XER'][XER_bits['CA']] else 0
+            carry32 = 1 if sim.spr['XER'][XER_bits['CA32']] else 0
+            res['xer_ca'] = carry | (carry32<<1)
 
         print ("inputs", res)
 
index a7291c6c3d4e1d6cec184193fff7bf6f86b7be4d..24402270c9ed0472d4a38689a3a1c6d6a807851d 100644 (file)
@@ -74,11 +74,3 @@ class CROutputData(IntegerData):
 class CRPipeSpec(CommonPipeSpec):
     regspec = (CRInputData.regspec, CROutputData.regspec)
     opsubsetkls = CompCROpSubset
-    def rdflags(self, e): # in order of regspec
-        reg1_ok = e.read_reg1.ok # RA/RC
-        reg2_ok = e.read_reg2.ok # RB
-        full_reg = e.read_cr_whole # full CR
-        cr1_en = e.read_cr1.ok # CR A
-        cr2_en = e.read_cr2.ok # CR B
-        cr3_en = e.read_cr3.ok # CR C
-        return Cat(reg1_ok, reg2_ok, full_reg, cr1_en, cr2_en, cr3_en)
index 6512324d67e144954d5465aad268a2a0a7200e49..37e86d5aec1834aaf7ce5c78708b10619f424e8f 100644 (file)
@@ -58,7 +58,3 @@ class LogicalOutputData(IntegerData):
 class LogicalPipeSpec(CommonPipeSpec):
     regspec = (LogicalInputData.regspec, LogicalOutputData.regspec)
     opsubsetkls = CompLogicalOpSubset
-    def rdflags(self, e): # in order of regspec
-        reg1_ok = e.read_reg1.ok # RA
-        reg2_ok = e.read_reg2.ok # RB
-        return Cat(reg1_ok, reg2_ok) # RA RB
index c8f1ebc278002e348cd23782886b19799f61e530..480603ab3429d74f7f74739d9b97f286750b79b3 100644 (file)
@@ -23,32 +23,45 @@ class TestCase:
         self.sprs = sprs
         self.name = name
 
+def get_cu_inputs(dec2, sim):
+    """naming (res) must conform to LogicalFunctionUnit input regspec
+    """
+    res = {}
 
-def set_alu_inputs(alu, dec2, sim):
-    # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
-    # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
-    # and place it into data_i.b
-
+    # RA (or RC)
     reg1_ok = yield dec2.e.read_reg1.ok
     if reg1_ok:
         data1 = yield dec2.e.read_reg1.data
-        data1 = sim.gpr(data1).value
-    else:
-        data1 = 0
+        res['ra'] = sim.gpr(data1).value
 
-    yield alu.p.data_i.a.eq(data1)
-
-    # If there's an immediate, set the B operand to that
+    # RB (or immediate)
     reg2_ok = yield dec2.e.read_reg2.ok
+    #imm_ok = yield dec2.e.imm_data.imm_ok
+    if reg2_ok:
+        data2 = yield dec2.e.read_reg2.data
+        data2 = sim.gpr(data2).value
+        res['rb'] = data2
+    #elif imm_ok:
+    #    data2 = yield dec2.e.imm_data.imm
+    #    res['rb'] = data2
+
+    return res
+
+
+def set_alu_inputs(alu, dec2, sim):
+    # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
+    # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
+    # and place it into data_i.b
+
+    inp = yield from get_cu_inputs(dec2, sim)
+    if 'ra' in inp:
+        yield alu.p.data_i.a.eq(inp['ra'])
+    if 'rb' in inp:
+        yield alu.p.data_i.b.eq(inp['rb'])
     imm_ok = yield dec2.e.imm_data.imm_ok
     if imm_ok:
         data2 = yield dec2.e.imm_data.imm
-    elif reg2_ok:
-        data2 = yield dec2.e.read_reg2.data
-        data2 = sim.gpr(data2).value
-    else:
-        data2 = 0
-    yield alu.p.data_i.b.eq(data2)
+        yield alu.p.data_i.b.eq(data2)
 
 
 # This test bench is a bit different than is usual. Initially when I
index 1eedc303aa03a1a985542dabbc65666f16cf62b7..18b16f38c4dd7de455b6fb9f692656c1dd279294 100644 (file)
@@ -66,11 +66,17 @@ class RegSpecALUAPI:
         self.rwid = rwid
         self.alu = alu # actual ALU - set as a "submodule" of the CU
 
+    def get_in_spec(self, i):
+        return self.rwid[0][i]
+
+    def get_out_spec(self, i):
+        return self.rwid[1][i]
+
     def get_in_name(self, i):
-        return self.rwid[0][i][1]
+        return self.get_in_spec(i)[1]
 
     def get_out_name(self, i):
-        return self.rwid[1][i][1]
+        return self.get_out_spec(i)[1]
 
     def get_out(self, i):
         if isinstance(self.rwid, int): # old - testing - API (rwid is int)
index 46d383a0300421a18b75f5c6d748f601d1c586af..044857526534a8382383b085feb5b8a62311beea 100644 (file)
@@ -38,8 +38,3 @@ class ShiftRotInputData(IntegerData):
 class ShiftRotPipeSpec(CommonPipeSpec):
     regspec = (ShiftRotInputData.regspec, LogicalOutputData.regspec)
     opsubsetkls = CompSROpSubset
-    def rdflags(self, e): # in order of regspec input
-        reg1_ok = e.read_reg1.ok # RA
-        reg2_ok = e.read_reg2.ok # RB
-        reg3_ok = e.read_reg3.ok # RS
-        return Cat(reg1_ok, reg2_ok, reg3_ok, 1) # RA RB RC CA
index 6871aa98531d43ea26cc155fab601ce1ec770173..eed1071116366292706a53e55255e42b63278ce2 100644 (file)
@@ -17,7 +17,7 @@ from soc.fu.spr.spr_input_record import CompSPROpSubset
 
 
 class SPRInputData(IntegerData):
-    regspec = [('INT', 'a', '0:63'),
+    regspec = [('INT', 'ra', '0:63'),
                ('SPR', 'spr1', '0:63'),
                ('FAST', 'spr2', '0:63'),
                ('XER', 'xer_so', '32'),
@@ -25,16 +25,18 @@ class SPRInputData(IntegerData):
                ('XER', 'xer_ca', '34,45')]
     def __init__(self, pspec):
         super().__init__(pspec)
-        self.a = Signal(64, reset_less=True) # RA
+        self.ra = Signal(64, reset_less=True) # RA
         self.spr1 = Signal(64, reset_less=True) # SPR (slow)
         self.spr2 = Signal(64, reset_less=True) # SPR (fast: MSR, LR, CTR etc)
         self.xer_so = Signal(reset_less=True) # XER bit 32: SO
         self.xer_ca = Signal(2, reset_less=True) # XER bit 34/45: CA/CA32
         self.xer_ov = Signal(2, reset_less=True) # bit0: ov, bit1: ov32
+        # convenience
+        self.a = self.ra
 
     def __iter__(self):
         yield from super().__iter__()
-        yield self.a
+        yield self.ra
         yield self.spr1
         yield self.spr2
         yield self.xer_ca
@@ -43,7 +45,7 @@ class SPRInputData(IntegerData):
 
     def eq(self, i):
         lst = super().eq(i)
-        return lst + [self.a.eq(i.a), self.reg.eq(i.reg),
+        return lst + [self.ra.eq(i.ra), self.reg.eq(i.reg),
                       self.spr1.eq(i.spr1), self.spr2.eq(i.spr2),
                       self.xer_ca.eq(i.xer_ca),
                       self.xer_ov.eq(i.xer_ov),
index bbd00b64c9919bfc6519a9cf22c1d904ae2ded12..8352895799d41697f650ca3259af1291cd4ffab2 100644 (file)
@@ -9,19 +9,27 @@ from nmigen import (Module, Signal, Cat, Mux, Const, signed)
 from nmutil.pipemodbase import PipeModBase
 from nmutil.extend import exts
 from soc.fu.trap.pipe_data import TrapInputData, TrapOutputData
+from soc.fu.branch.main_stage import br_ext
 from soc.decoder.power_enums import InternalOp
 
 from soc.decoder.power_fields import DecodeFields
 from soc.decoder.power_fieldsn import SignalBitRange
 
 # TODO at some point move these to their own module (for use elsewhere)
+# TODO: turn these into python constants (just "MSR_SF = 63-0 # comment" etc.)
 """
+    Listed in V3.0B Book III Chap 4.2.1
     -- MSR bit numbers
     constant MSR_SF  : integer := (63 - 0);     -- Sixty-Four bit mode
+    constant MSR_HV  : integer := (63 - 3);     -- Hypervisor state
+    constant MSR_S   : integer := (63 - 41);    -- Secure state
     constant MSR_EE  : integer := (63 - 48);    -- External interrupt Enable
     constant MSR_PR  : integer := (63 - 49);    -- PRoblem state
+    constant MSR_FP  : integer := (63 - 50);    -- FP available
+    constant MSR_ME  : integer := (63 - 51);    -- Machine Check int enable
     constant MSR_IR  : integer := (63 - 58);    -- Instruction Relocation
     constant MSR_DR  : integer := (63 - 59);    -- Data Relocation
+    constant MSR_PMM : integer := (63 - 60);    -- Performance Monitor Mark
     constant MSR_RI  : integer := (63 - 62);    -- Recoverable Interrupt
     constant MSR_LE  : integer := (63 - 63);    -- Little Endian
 """
@@ -117,7 +125,7 @@ class TrapMainStage(PipeModBase):
             with m.Case(InternalOp.OP_MTMSR):
                 # TODO: some of the bits need zeroing?
                 """
-                if e_in.insn(16) = '1' then
+                if e_in.insn(16) = '1' then  <-- this is X-form field "L".
                     -- just update EE and RI
                     ctrl_tmp.msr(MSR_EE) <= c_in(MSR_EE);
                     ctrl_tmp.msr(MSR_RI) <= c_in(MSR_RI);
@@ -132,7 +140,18 @@ class TrapMainStage(PipeModBase):
                         ctrl_tmp.msr(MSR_IR) <= '1';
                         ctrl_tmp.msr(MSR_DR) <= '1';
                 """
-                comb += self.o.msr.data.eq(a)
+                L = self.fields.FormX.L[0:-1]
+                with m.If(L):
+                    comb += self.o.msr[MSR_EE].eq(self.i.msr[MSR_EE])
+                    comb += self.o.msr[MSR_RI].eq(self.i.msr[MSR_RI])
+
+                with m.Else():
+                    for stt, end in [(1,12), (13, 60), (61, 64)]:
+                        comb += self.o.msr.data[stt:end].eq(a[stt:end])
+                    with m.If(a[MSR_PR]):
+                            self.o.msr[MSR_EE].eq(1)
+                            self.o.msr[MSR_IR].eq(1)
+                            self.o.msr[MSR_DR].eq(1)
                 comb += self.o.msr.ok.eq(1)
 
             # move from SPR
@@ -146,7 +165,6 @@ class TrapMainStage(PipeModBase):
                 comb += self.o.o.data.eq(self.i.msr)
                 comb += self.o.o.ok.eq(1)
 
-            # TODO
             with m.Case(InternalOp.OP_RFID):
                 """
                 # XXX f_out.virt_mode <= b_in(MSR_IR) or b_in(MSR_PR);
@@ -163,9 +181,16 @@ class TrapMainStage(PipeModBase):
                     ctrl_tmp.msr(MSR_DR) <= '1';
                 end if;
                 """
-                pass
+                comb += self.o.nia.data.eq(br_ext(a[63:1] & 0))
+                comb += self.o.nia.ok.eq(1)
+                for stt, end in [(0,16), (22, 27), (31, 64)]:
+                    comb += self.o.msr.data[stt:end].eq(a[stt:end])
+                with m.If(a[MSR_PR]):
+                        self.o.msr[MSR_EE].eq(1)
+                        self.o.msr[MSR_IR].eq(1)
+                        self.o.msr[MSR_DR].eq(1)
+                comb += self.o.msr.ok.eq(1)
 
-            # TODO
             with m.Case(InternalOp.OP_SC):
                 """
                 # TODO: scv must generate illegal instruction.  this is
@@ -173,8 +198,12 @@ class TrapMainStage(PipeModBase):
                 ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#C00#, 64));
                 ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
                 """
-                pass
+                comb += self.o.nia.eq(0xC00) # trap address
+                comb += self.o.nia.ok.eq(1)
+                comb += self.o.srr1.data.eq(self.i.msr)
+                comb += self.o.srr1.ok.eq(1)
 
+            # TODO (later)
             #with m.Case(InternalOp.OP_ADDPCIS):
             #    pass
 
diff --git a/src/soc/regfile/util.py b/src/soc/regfile/util.py
new file mode 100644 (file)
index 0000000..f27d711
--- /dev/null
@@ -0,0 +1,10 @@
+from soc.regfile.regfiles import FastRegs
+from soc.decoder.power_enums import SPR
+
+def fast_reg_to_spr(spr_num):
+    if spr_num == FastRegs.CTR:
+        return SPR.CTR.value
+    elif spr_num == FastRegs.LR:
+        return SPR.LR.value
+    elif spr_num == FastRegs.TAR:
+        return SPR.TAR.value