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 soc
.decoder
.power_enums
import MicrOp
37 from soc
.decoder
.power_fields
import DecodeFields
38 from soc
.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
99 BO
= b_fields
.BO
[0:-1]
100 BI
= b_fields
.BI
[0:-1][0:2] # CR0-7 selected already in PowerDecode2.
102 cr_bits
= Array([cr
[3-i
] for i
in range(4)]) # invert. Because POWER.
104 # The bit of CR selected by BI
105 bi
= Signal(2, reset_less
=True)
106 cr_bit
= Signal(reset_less
=True)
107 comb
+= bi
.eq(BI
) # reduces gate-count due to pmux
108 comb
+= cr_bit
.eq(cr_bits
[bi
])
110 # Whether ctr is written to on a conditional branch
111 ctr_write
= Signal(reset_less
=True)
112 comb
+= ctr_write
.eq(0)
114 # Whether the conditional branch should be taken
115 bc_taken
= Signal(reset_less
=True)
117 comb
+= bc_taken
.eq((cr_bit
== BO
[3]) | BO
[4])
119 # decrement the counter and place into output
120 ctr_n
= Signal(64, reset_less
=True)
121 comb
+= ctr_n
.eq(ctr
- 1)
122 comb
+= ctr_o
.data
.eq(ctr_n
)
123 comb
+= ctr_write
.eq(1)
124 # take either all 64 bits or only 32 of post-incremented counter
125 ctr_m
= Signal(64, reset_less
=True)
126 with m
.If(op
.is_32bit
):
127 comb
+= ctr_m
.eq(ctr
[:32])
129 comb
+= ctr_m
.eq(ctr
)
130 # check CTR zero/non-zero against BO[1]
131 ctr_zero_bo1
= Signal(reset_less
=True) # BO[1] == (ctr==0)
132 comb
+= ctr_zero_bo1
.eq(BO
[1] ^ ctr_m
.any())
133 with m
.If(BO
[3:5] == 0b00):
134 comb
+= bc_taken
.eq(ctr_zero_bo1
& ~cr_bit
)
135 with m
.Elif(BO
[3:5] == 0b01):
136 comb
+= bc_taken
.eq(ctr_zero_bo1
& cr_bit
)
137 with m
.Elif(BO
[4] == 1):
138 comb
+= bc_taken
.eq(ctr_zero_bo1
)
140 ### Main Switch Statement ###
141 with m
.Switch(op
.insn_type
):
143 with m
.Case(MicrOp
.OP_B
):
144 LI
= i_fields
.LI
[0:-1]
145 comb
+= br_imm_addr
.eq(br_ext(LI
))
146 comb
+= br_taken
.eq(1)
147 #### branch conditional ####
148 with m
.Case(MicrOp
.OP_BC
):
149 BD
= b_fields
.BD
[0:-1]
150 comb
+= br_imm_addr
.eq(br_ext(BD
))
151 comb
+= br_taken
.eq(bc_taken
)
152 comb
+= ctr_o
.ok
.eq(ctr_write
)
153 #### branch conditional reg ####
154 with m
.Case(MicrOp
.OP_BCREG
):
155 xo
= self
.fields
.FormXL
.XO
[0:-1]
156 with m
.If(xo
[9] & ~xo
[5]):
157 comb
+= br_imm_addr
.eq(Cat(Const(0, 2), fast1
[2:]))
159 comb
+= br_imm_addr
.eq(Cat(Const(0, 2), fast2
[2:]))
160 comb
+= br_taken
.eq(bc_taken
)
161 comb
+= ctr_o
.ok
.eq(ctr_write
)
163 # output next instruction address
164 comb
+= nia_o
.data
.eq(br_addr
)
165 comb
+= nia_o
.ok
.eq(br_taken
)
167 # link register - only activate on operations marked as "lk"
169 # ctx.op.lk is the AND of the insn LK field *and* whether the
170 # op is to "listen" to the link field
171 comb
+= lr_o
.data
.eq(cia
+ 4)
172 comb
+= lr_o
.ok
.eq(1)
175 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)