3 This stage is intended to do most of the work of executing branch
4 instructions. This is OP_B, OP_B, OP_BCREG
6 Note: it is PARTICULARLY important to pay attention to PowerDecode2
7 more specifically DecodeRA etc. as these work closely in conjunction
8 with the Branch pipeline, here.
10 The Branch pipeline itself does not and cannot read registers: it can
11 only process data and produce results. Therefore, something else needs
12 to know that BC needs CTR, and that one of the outputs from here is to
13 go into LR, and so on. Encoding of which registers are read and written
14 is the responsibility of PowerDecode2 and because some of those decisions
15 are conditional (based on BO2 for example) PowerDecode2 has to duplicate
16 some of that bitlevel operand field decoding.
18 It us therefore quite critical to read this code in conjunction side by
19 side with power_decode2.py
22 * https://bugs.libre-soc.org/show_bug.cgi?id=313
23 * https://bugs.libre-soc.org/show_bug.cgi?id=335
24 * https://libre-soc.org/openpower/isa/branch/
27 from nmigen
import (Module
, Signal
, Cat
, Mux
, Const
, Array
)
28 from nmutil
.pipemodbase
import PipeModBase
29 from nmutil
.extend
import exts
30 from soc
.fu
.branch
.pipe_data
import BranchInputData
, BranchOutputData
31 from soc
.decoder
.power_enums
import MicrOp
33 from soc
.decoder
.power_fields
import DecodeFields
34 from soc
.decoder
.power_fieldsn
import SignalBitRange
38 """computes sign-extended NIA (assumes word-alignment)
40 return Cat(Const(0, 2), exts(bd
, bd
.shape().width
, 64 - 2))
47 0000z Decrement the CTR, then branch if decremented CTR[M:63]!=0 and CR[BI]=0
48 0001z Decrement the CTR, then branch if decremented CTR[M:63]=0 and CR[BI]=0
49 001at Branch if CR[BI]=0
50 0100z Decrement the CTR, then branch if decremented CTR[M:63]!=0 and CR[BI]=1
51 0101z Decrement the CTR, then branch if decremented CTR[M:63]=0 and CR[BI]=1
52 011at Branch if CR[BI]=1
53 1a00t Decrement the CTR, then branch if decremented CTR[M:63]!=0
54 1a01t Decrement the CTR, then branch if decremented CTR[M:63]=0
58 class BranchMainStage(PipeModBase
):
59 def __init__(self
, pspec
):
60 super().__init
__(pspec
, "main")
61 self
.fields
= DecodeFields(SignalBitRange
, [self
.i
.ctx
.op
.insn
])
62 self
.fields
.create_specs()
65 return BranchInputData(self
.pspec
)
68 return BranchOutputData(self
.pspec
) # TODO: ALUIntermediateData
70 def elaborate(self
, platform
):
74 lk
= op
.lk
# see PowerDecode2 as to why this is done
75 cr
, cia
, ctr
, fast1
= self
.i
.cr
, self
.i
.cia
, self
.i
.ctr
, self
.i
.fast1
77 nia_o
, lr_o
, ctr_o
= self
.o
.nia
, self
.o
.lr
, self
.o
.ctr
79 # obtain relevant instruction field AA, "Absolute Address" mode
80 i_fields
= self
.fields
.FormI
81 AA
= i_fields
.AA
[0:-1]
83 br_imm_addr
= Signal(64, reset_less
=True)
84 br_addr
= Signal(64, reset_less
=True)
85 br_taken
= Signal(reset_less
=True)
87 # Handle absolute or relative branches
88 with m
.If(AA |
(op
.insn_type
== MicrOp
.OP_BCREG
)):
89 comb
+= br_addr
.eq(br_imm_addr
)
91 comb
+= br_addr
.eq(br_imm_addr
+ cia
)
93 # fields for conditional branches (BO and BI are same for BC and BCREG)
94 b_fields
= self
.fields
.FormB
95 BO
= b_fields
.BO
[0:-1]
96 BI
= b_fields
.BI
[0:-1][0:2] # CR0-7 selected already in PowerDecode2.
98 cr_bits
= Array([cr
[3-i
] for i
in range(4)]) # invert. Because POWER.
100 # The bit of CR selected by BI
101 bi
= Signal(2, reset_less
=True)
102 cr_bit
= Signal(reset_less
=True)
103 comb
+= bi
.eq(BI
) # reduces gate-count due to pmux
104 comb
+= cr_bit
.eq(cr_bits
[bi
])
106 # Whether ctr is written to on a conditional branch
107 ctr_write
= Signal(reset_less
=True)
108 comb
+= ctr_write
.eq(0)
110 # Whether the conditional branch should be taken
111 bc_taken
= Signal(reset_less
=True)
113 comb
+= bc_taken
.eq((cr_bit
== BO
[3]) | BO
[4])
115 # decrement the counter and place into output
116 ctr_n
= Signal(64, reset_less
=True)
117 comb
+= ctr_n
.eq(ctr
- 1)
118 comb
+= ctr_o
.data
.eq(ctr_n
)
119 comb
+= ctr_write
.eq(1)
120 # take either all 64 bits or only 32 of post-incremented counter
121 ctr_m
= Signal(64, reset_less
=True)
122 with m
.If(op
.is_32bit
):
123 comb
+= ctr_m
.eq(ctr
[:32])
125 comb
+= ctr_m
.eq(ctr
)
126 # check CTR zero/non-zero against BO[1]
127 ctr_zero_bo1
= Signal(reset_less
=True) # BO[1] == (ctr==0)
128 comb
+= ctr_zero_bo1
.eq(BO
[1] ^ ctr_m
.any())
129 with m
.If(BO
[3:5] == 0b00):
130 comb
+= bc_taken
.eq(ctr_zero_bo1
& ~cr_bit
)
131 with m
.Elif(BO
[3:5] == 0b01):
132 comb
+= bc_taken
.eq(ctr_zero_bo1
& cr_bit
)
133 with m
.Elif(BO
[4] == 1):
134 comb
+= bc_taken
.eq(ctr_zero_bo1
)
136 ### Main Switch Statement ###
137 with m
.Switch(op
.insn_type
):
139 with m
.Case(MicrOp
.OP_B
):
140 LI
= i_fields
.LI
[0:-1]
141 comb
+= br_imm_addr
.eq(br_ext(LI
))
142 comb
+= br_taken
.eq(1)
143 #### branch conditional ####
144 with m
.Case(MicrOp
.OP_BC
):
145 BD
= b_fields
.BD
[0:-1]
146 comb
+= br_imm_addr
.eq(br_ext(BD
))
147 comb
+= br_taken
.eq(bc_taken
)
148 comb
+= ctr_o
.ok
.eq(ctr_write
)
149 #### branch conditional reg ####
150 with m
.Case(MicrOp
.OP_BCREG
):
151 xo
= self
.fields
.FormXL
.XO
[0:-1]
152 with m
.If(xo
[9] & ~xo
[5]):
153 comb
+= br_imm_addr
.eq(Cat(Const(0, 2), fast1
[2:]))
155 comb
+= br_imm_addr
.eq(Cat(Const(0, 2), fast2
[2:]))
156 comb
+= br_taken
.eq(bc_taken
)
157 comb
+= ctr_o
.ok
.eq(ctr_write
)
159 # output next instruction address
160 comb
+= nia_o
.data
.eq(br_addr
)
161 comb
+= nia_o
.ok
.eq(br_taken
)
163 # link register - only activate on operations marked as "lk"
165 # ctx.op.lk is the AND of the insn LK field *and* whether the
166 # op is to "listen" to the link field
167 comb
+= lr_o
.data
.eq(cia
+ 4)
168 comb
+= lr_o
.ok
.eq(1)
171 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)