d4eecf37f80d3ec1ed93007d11d0aec5d9c828f3
1 # This stage is intended to do most of the work of executing Logical
2 # instructions. This is OR, AND, XOR, POPCNT, PRTY, CMPB, BPERMD, CNTLZ
3 # however input and output stages also perform bit-negation on input(s)
4 # and output, as well as carry and overflow generation.
5 # This module however should not gate the carry or overflow, that's up
8 from nmigen
import (Module
, Signal
, Cat
, Mux
, Const
, Array
)
9 from nmutil
.pipemodbase
import PipeModBase
10 from nmutil
.extend
import exts
11 from soc
.fu
.branch
.pipe_data
import BranchInputData
, BranchOutputData
12 from soc
.decoder
.power_enums
import InternalOp
14 from soc
.decoder
.power_fields
import DecodeFields
15 from soc
.decoder
.power_fieldsn
import SignalBitRange
18 """computes sign-extended NIA (assumes word-alignment)
20 return Cat(Const(0, 2), exts(bd
, bd
.shape().width
, 64 - 2))
27 0000z Decrement the CTR, then branch if decremented CTR[M:63]!=0 and CR[BI]=0
28 0001z Decrement the CTR, then branch if decremented CTR[M:63]=0 and CR[BI]=0
29 001at Branch if CR[BI]=0
30 0100z Decrement the CTR, then branch if decremented CTR[M:63]!=0 and CR[BI]=1
31 0101z Decrement the CTR, then branch if decremented CTR[M:63]=0 and CR[BI]=1
32 011at Branch if CR[BI]=1
33 1a00t Decrement the CTR, then branch if decremented CTR[M:63]!=0
34 1a01t Decrement the CTR, then branch if decremented CTR[M:63]=0
38 class BranchMainStage(PipeModBase
):
39 def __init__(self
, pspec
):
40 super().__init
__(pspec
, "main")
41 self
.fields
= DecodeFields(SignalBitRange
, [self
.i
.ctx
.op
.insn
])
42 self
.fields
.create_specs()
45 return BranchInputData(self
.pspec
)
48 return BranchOutputData(self
.pspec
) # TODO: ALUIntermediateData
50 def elaborate(self
, platform
):
54 lk
= op
.lk
# see PowerDecode2 as to why this is done
55 cr
, cia
, ctr
, spr1
= self
.i
.cr
, self
.i
.cia
, self
.i
.ctr
, self
.i
.spr1
56 nia_o
, lr_o
, ctr_o
= self
.o
.nia
, self
.o
.lr
, self
.o
.ctr
58 # obtain relevant instruction field AA, "Absolute Address" mode
59 i_fields
= self
.fields
.FormI
60 AA
= i_fields
.AA
[0:-1]
62 br_imm_addr
= Signal(64, reset_less
=True)
63 br_addr
= Signal(64, reset_less
=True)
64 br_taken
= Signal(reset_less
=True)
66 # Handle absolute or relative branches
67 with m
.If(AA |
(op
.insn_type
== InternalOp
.OP_BCREG
)):
68 comb
+= br_addr
.eq(br_imm_addr
)
70 comb
+= br_addr
.eq(br_imm_addr
+ cia
)
72 # fields for conditional branches (BO and BI are same for BC and BCREG)
73 # NOTE: here, BO and BI we would like be treated as CR regfile
74 # selectors (similar to RA, RB, RS, RT). see comment here:
75 # https://bugs.libre-soc.org/show_bug.cgi?id=313#c2
76 b_fields
= self
.fields
.FormB
77 BO
= b_fields
.BO
[0:-1]
78 BI
= b_fields
.BI
[0:-1][0:2]
80 cr_bits
= Array([cr
[3-i
] for i
in range(4)])
82 # The bit of CR selected by BI
83 cr_bit
= Signal(reset_less
=True)
84 comb
+= cr_bit
.eq(cr_bits
[BI
])
86 # Whether the conditional branch should be taken
87 bc_taken
= Signal(reset_less
=True)
89 comb
+= bc_taken
.eq((cr_bit
== BO
[3]) | BO
[4])
91 # decrement the counter and place into output
92 ctr_n
= Signal(64, reset_less
=True)
93 comb
+= ctr_n
.eq(ctr
- 1)
94 comb
+= ctr_o
.data
.eq(ctr_n
)
95 comb
+= ctr_o
.ok
.eq(1)
96 # take either all 64 bits or only 32 of post-incremented counter
97 ctr_m
= Signal(64, reset_less
=True)
98 with m
.If(op
.is_32bit
):
99 comb
+= ctr_m
.eq(ctr
[:32])
101 comb
+= ctr_m
.eq(ctr
)
102 # check CTR zero/non-zero against BO[1]
103 ctr_zero_bo1
= Signal(reset_less
=True) # BO[1] == (ctr==0)
104 comb
+= ctr_zero_bo1
.eq(BO
[1] ^ ctr_m
.any())
105 with m
.If(BO
[3:5] == 0b00):
106 comb
+= bc_taken
.eq(ctr_zero_bo1
& ~cr_bit
)
107 with m
.Elif(BO
[3:5] == 0b01):
108 comb
+= bc_taken
.eq(ctr_zero_bo1
& cr_bit
)
109 with m
.Elif(BO
[4] == 1):
110 comb
+= bc_taken
.eq(ctr_zero_bo1
)
112 ### Main Switch Statement ###
113 with m
.Switch(op
.insn_type
):
115 with m
.Case(InternalOp
.OP_B
):
116 LI
= i_fields
.LI
[0:-1]
117 comb
+= br_imm_addr
.eq(br_ext(LI
))
118 comb
+= br_taken
.eq(1)
119 #### branch conditional ####
120 with m
.Case(InternalOp
.OP_BC
):
121 BD
= b_fields
.BD
[0:-1]
122 comb
+= br_imm_addr
.eq(br_ext(BD
))
123 comb
+= br_taken
.eq(bc_taken
)
124 #### branch conditional reg ####
125 with m
.Case(InternalOp
.OP_BCREG
):
126 comb
+= br_imm_addr
.eq(spr1
) # SPR1 is set by decode unit
127 comb
+= br_taken
.eq(bc_taken
)
129 # output next instruction address
130 comb
+= nia_o
.data
.eq(br_addr
)
131 comb
+= nia_o
.ok
.eq(br_taken
)
133 # link register - only activate on operations marked as "lk"
135 # ctx.op.lk is the AND of the insn LK field *and* whether the
136 # op is to "listen" to the link field
137 comb
+= lr_o
.data
.eq(cia
+ 4)
138 comb
+= lr_o
.ok
.eq(1)
141 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)