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