3 This stage is intended to do most of the work of executing branch
4 instructions. This is OP_B, OP_B, OP_BCREG
7 * https://bugs.libre-soc.org/show_bug.cgi?id=313
8 * https://bugs.libre-soc.org/show_bug.cgi?id=335
9 * https://libre-soc.org/openpower/isa/branch/
12 from nmigen
import (Module
, Signal
, Cat
, Mux
, Const
, Array
)
13 from nmutil
.pipemodbase
import PipeModBase
14 from nmutil
.extend
import exts
15 from soc
.fu
.branch
.pipe_data
import BranchInputData
, BranchOutputData
16 from soc
.decoder
.power_enums
import InternalOp
18 from soc
.decoder
.power_fields
import DecodeFields
19 from soc
.decoder
.power_fieldsn
import SignalBitRange
23 """computes sign-extended NIA (assumes word-alignment)
25 return Cat(Const(0, 2), exts(bd
, bd
.shape().width
, 64 - 2))
32 0000z Decrement the CTR, then branch if decremented CTR[M:63]!=0 and CR[BI]=0
33 0001z Decrement the CTR, then branch if decremented CTR[M:63]=0 and CR[BI]=0
34 001at Branch if CR[BI]=0
35 0100z Decrement the CTR, then branch if decremented CTR[M:63]!=0 and CR[BI]=1
36 0101z Decrement the CTR, then branch if decremented CTR[M:63]=0 and CR[BI]=1
37 011at Branch if CR[BI]=1
38 1a00t Decrement the CTR, then branch if decremented CTR[M:63]!=0
39 1a01t Decrement the CTR, then branch if decremented CTR[M:63]=0
43 class BranchMainStage(PipeModBase
):
44 def __init__(self
, pspec
):
45 super().__init
__(pspec
, "main")
46 self
.fields
= DecodeFields(SignalBitRange
, [self
.i
.ctx
.op
.insn
])
47 self
.fields
.create_specs()
50 return BranchInputData(self
.pspec
)
53 return BranchOutputData(self
.pspec
) # TODO: ALUIntermediateData
55 def elaborate(self
, platform
):
59 lk
= op
.lk
# see PowerDecode2 as to why this is done
60 cr
, cia
, ctr
, spr1
= self
.i
.cr
, self
.i
.cia
, self
.i
.ctr
, self
.i
.spr1
61 nia_o
, lr_o
, ctr_o
= self
.o
.nia
, self
.o
.lr
, self
.o
.ctr
63 # obtain relevant instruction field AA, "Absolute Address" mode
64 i_fields
= self
.fields
.FormI
65 AA
= i_fields
.AA
[0:-1]
67 br_imm_addr
= Signal(64, reset_less
=True)
68 br_addr
= Signal(64, reset_less
=True)
69 br_taken
= Signal(reset_less
=True)
71 # Handle absolute or relative branches
72 with m
.If(AA |
(op
.insn_type
== InternalOp
.OP_BCREG
)):
73 comb
+= br_addr
.eq(br_imm_addr
)
75 comb
+= br_addr
.eq(br_imm_addr
+ cia
)
77 # fields for conditional branches (BO and BI are same for BC and BCREG)
78 # NOTE: here, BO and BI we would like be treated as CR regfile
79 # selectors (similar to RA, RB, RS, RT). see comment here:
80 # https://bugs.libre-soc.org/show_bug.cgi?id=313#c2
81 b_fields
= self
.fields
.FormB
82 BO
= b_fields
.BO
[0:-1]
83 BI
= b_fields
.BI
[0:-1][0:2]
85 cr_bits
= Array([cr
[3-i
] for i
in range(4)])
87 # The bit of CR selected by BI
88 cr_bit
= Signal(reset_less
=True)
89 comb
+= cr_bit
.eq(cr_bits
[BI
])
91 # Whether the conditional branch should be taken
92 bc_taken
= Signal(reset_less
=True)
94 comb
+= bc_taken
.eq((cr_bit
== BO
[3]) | BO
[4])
96 # decrement the counter and place into output
97 ctr_n
= Signal(64, reset_less
=True)
98 comb
+= ctr_n
.eq(ctr
- 1)
99 comb
+= ctr_o
.data
.eq(ctr_n
)
100 comb
+= ctr_o
.ok
.eq(1)
101 # take either all 64 bits or only 32 of post-incremented counter
102 ctr_m
= Signal(64, reset_less
=True)
103 with m
.If(op
.is_32bit
):
104 comb
+= ctr_m
.eq(ctr
[:32])
106 comb
+= ctr_m
.eq(ctr
)
107 # check CTR zero/non-zero against BO[1]
108 ctr_zero_bo1
= Signal(reset_less
=True) # BO[1] == (ctr==0)
109 comb
+= ctr_zero_bo1
.eq(BO
[1] ^ ctr_m
.any())
110 with m
.If(BO
[3:5] == 0b00):
111 comb
+= bc_taken
.eq(ctr_zero_bo1
& ~cr_bit
)
112 with m
.Elif(BO
[3:5] == 0b01):
113 comb
+= bc_taken
.eq(ctr_zero_bo1
& cr_bit
)
114 with m
.Elif(BO
[4] == 1):
115 comb
+= bc_taken
.eq(ctr_zero_bo1
)
117 ### Main Switch Statement ###
118 with m
.Switch(op
.insn_type
):
120 with m
.Case(InternalOp
.OP_B
):
121 LI
= i_fields
.LI
[0:-1]
122 comb
+= br_imm_addr
.eq(br_ext(LI
))
123 comb
+= br_taken
.eq(1)
124 #### branch conditional ####
125 with m
.Case(InternalOp
.OP_BC
):
126 BD
= b_fields
.BD
[0:-1]
127 comb
+= br_imm_addr
.eq(br_ext(BD
))
128 comb
+= br_taken
.eq(bc_taken
)
129 #### branch conditional reg ####
130 with m
.Case(InternalOp
.OP_BCREG
):
131 comb
+= br_imm_addr
.eq(spr1
) # SPR1 is set by decode unit
132 comb
+= br_taken
.eq(bc_taken
)
134 # output next instruction address
135 comb
+= nia_o
.data
.eq(br_addr
)
136 comb
+= nia_o
.ok
.eq(br_taken
)
138 # link register - only activate on operations marked as "lk"
140 # ctx.op.lk is the AND of the insn LK field *and* whether the
141 # op is to "listen" to the link field
142 comb
+= lr_o
.data
.eq(cia
+ 4)
143 comb
+= lr_o
.ok
.eq(1)
146 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)