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/
26 # Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
28 from nmigen
import (Module
, Signal
, Cat
, Mux
, Const
, Array
)
29 from nmutil
.pipemodbase
import PipeModBase
30 from nmutil
.extend
import exts
31 from soc
.fu
.branch
.pipe_data
import BranchInputData
, BranchOutputData
32 from soc
.decoder
.power_enums
import MicrOp
34 from soc
.decoder
.power_fields
import DecodeFields
35 from soc
.decoder
.power_fieldsn
import SignalBitRange
39 """computes sign-extended NIA (assumes word-alignment)
41 return Cat(Const(0, 2), exts(bd
, bd
.shape().width
, 64 - 2))
48 0000z Decrement the CTR, then branch if decremented CTR[M:63]!=0 and CR[BI]=0
49 0001z Decrement the CTR, then branch if decremented CTR[M:63]=0 and CR[BI]=0
50 001at Branch if CR[BI]=0
51 0100z Decrement the CTR, then branch if decremented CTR[M:63]!=0 and CR[BI]=1
52 0101z Decrement the CTR, then branch if decremented CTR[M:63]=0 and CR[BI]=1
53 011at Branch if CR[BI]=1
54 1a00t Decrement the CTR, then branch if decremented CTR[M:63]!=0
55 1a01t Decrement the CTR, then branch if decremented CTR[M:63]=0
59 class BranchMainStage(PipeModBase
):
60 def __init__(self
, pspec
):
61 super().__init
__(pspec
, "main")
62 self
.fields
= DecodeFields(SignalBitRange
, [self
.i
.ctx
.op
.insn
])
63 self
.fields
.create_specs()
66 return BranchInputData(self
.pspec
)
69 return BranchOutputData(self
.pspec
) # TODO: ALUIntermediateData
71 def elaborate(self
, platform
):
75 lk
= op
.lk
# see PowerDecode2 as to why this is done
76 cr
, cia
, ctr
, fast1
= self
.i
.cr
, op
.cia
, self
.i
.ctr
, self
.i
.fast1
78 nia_o
, lr_o
, ctr_o
= self
.o
.nia
, self
.o
.lr
, self
.o
.ctr
80 # obtain relevant instruction field AA, "Absolute Address" mode
81 i_fields
= self
.fields
.FormI
82 AA
= i_fields
.AA
[0:-1]
84 br_imm_addr
= Signal(64, reset_less
=True)
85 br_addr
= Signal(64, reset_less
=True)
86 br_taken
= Signal(reset_less
=True)
88 # Handle absolute or relative branches
89 with m
.If(AA |
(op
.insn_type
== MicrOp
.OP_BCREG
)):
90 comb
+= br_addr
.eq(br_imm_addr
)
92 comb
+= br_addr
.eq(br_imm_addr
+ cia
)
94 # fields for conditional branches (BO and BI are same for BC and BCREG)
95 b_fields
= self
.fields
.FormB
96 BO
= b_fields
.BO
[0:-1]
97 BI
= b_fields
.BI
[0:-1][0:2] # CR0-7 selected already in PowerDecode2.
99 cr_bits
= Array([cr
[3-i
] for i
in range(4)]) # invert. Because POWER.
101 # The bit of CR selected by BI
102 bi
= Signal(2, reset_less
=True)
103 cr_bit
= Signal(reset_less
=True)
104 comb
+= bi
.eq(BI
) # reduces gate-count due to pmux
105 comb
+= cr_bit
.eq(cr_bits
[bi
])
107 # Whether ctr is written to on a conditional branch
108 ctr_write
= Signal(reset_less
=True)
109 comb
+= ctr_write
.eq(0)
111 # Whether the conditional branch should be taken
112 bc_taken
= Signal(reset_less
=True)
114 comb
+= bc_taken
.eq((cr_bit
== BO
[3]) | BO
[4])
116 # decrement the counter and place into output
117 ctr_n
= Signal(64, reset_less
=True)
118 comb
+= ctr_n
.eq(ctr
- 1)
119 comb
+= ctr_o
.data
.eq(ctr_n
)
120 comb
+= ctr_write
.eq(1)
121 # take either all 64 bits or only 32 of post-incremented counter
122 ctr_m
= Signal(64, reset_less
=True)
123 with m
.If(op
.is_32bit
):
124 comb
+= ctr_m
.eq(ctr
[:32])
126 comb
+= ctr_m
.eq(ctr
)
127 # check CTR zero/non-zero against BO[1]
128 ctr_zero_bo1
= Signal(reset_less
=True) # BO[1] == (ctr==0)
129 comb
+= ctr_zero_bo1
.eq(BO
[1] ^ ctr_m
.any())
130 with m
.If(BO
[3:5] == 0b00):
131 comb
+= bc_taken
.eq(ctr_zero_bo1
& ~cr_bit
)
132 with m
.Elif(BO
[3:5] == 0b01):
133 comb
+= bc_taken
.eq(ctr_zero_bo1
& cr_bit
)
134 with m
.Elif(BO
[4] == 1):
135 comb
+= bc_taken
.eq(ctr_zero_bo1
)
137 ### Main Switch Statement ###
138 with m
.Switch(op
.insn_type
):
140 with m
.Case(MicrOp
.OP_B
):
141 LI
= i_fields
.LI
[0:-1]
142 comb
+= br_imm_addr
.eq(br_ext(LI
))
143 comb
+= br_taken
.eq(1)
144 #### branch conditional ####
145 with m
.Case(MicrOp
.OP_BC
):
146 BD
= b_fields
.BD
[0:-1]
147 comb
+= br_imm_addr
.eq(br_ext(BD
))
148 comb
+= br_taken
.eq(bc_taken
)
149 comb
+= ctr_o
.ok
.eq(ctr_write
)
150 #### branch conditional reg ####
151 with m
.Case(MicrOp
.OP_BCREG
):
152 xo
= self
.fields
.FormXL
.XO
[0:-1]
153 with m
.If(xo
[9] & ~xo
[5]):
154 comb
+= br_imm_addr
.eq(Cat(Const(0, 2), fast1
[2:]))
156 comb
+= br_imm_addr
.eq(Cat(Const(0, 2), fast2
[2:]))
157 comb
+= br_taken
.eq(bc_taken
)
158 comb
+= ctr_o
.ok
.eq(ctr_write
)
160 # output next instruction address
161 comb
+= nia_o
.data
.eq(br_addr
)
162 comb
+= nia_o
.ok
.eq(br_taken
)
164 # link register - only activate on operations marked as "lk"
166 # ctx.op.lk is the AND of the insn LK field *and* whether the
167 # op is to "listen" to the link field
168 comb
+= lr_o
.data
.eq(cia
+ 4)
169 comb
+= lr_o
.ok
.eq(1)
172 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)