7d21be6a0dcae2993c837a799fa0324fb8454c51
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
, Repl
, Mux
, Const
, Array
)
9 from nmutil
.pipemodbase
import PipeModBase
10 from soc
.branch
.pipe_data
import BranchInputData
, BranchOutputData
11 from soc
.decoder
.power_enums
import InternalOp
13 from soc
.decoder
.power_fields
import DecodeFields
14 from soc
.decoder
.power_fieldsn
import SignalBitRange
17 return Cat(Const(0, 2), bd
, Repl(bd
[-1], 64-(bd
.width
+ 2)))
20 class BranchMainStage(PipeModBase
):
21 def __init__(self
, pspec
):
22 super().__init
__(pspec
, "main")
23 self
.fields
= DecodeFields(SignalBitRange
, [self
.i
.ctx
.op
.insn
])
24 self
.fields
.create_specs()
27 return BranchInputData(self
.pspec
)
30 return BranchOutputData(self
.pspec
) # TODO: ALUIntermediateData
32 def elaborate(self
, platform
):
36 nia_out
, lr
= self
.o
.nia_out
, self
.o
.lr
38 # obtain relevant instruction fields
39 i_fields
= self
.fields
.instrs
['I']
40 lk
= Signal(i_fields
['LK'][0:-1].shape())
41 aa
= Signal(i_fields
['AA'][0:-1].shape())
42 comb
+= lk
.eq(i_fields
['LK'][0:-1])
43 comb
+= aa
.eq(i_fields
['AA'][0:-1])
45 br_imm_addr
= Signal(64, reset_less
=True)
46 br_addr
= Signal(64, reset_less
=True)
47 br_taken
= Signal(reset_less
=True)
49 # Handle absolute or relative branches
51 comb
+= br_addr
.eq(br_imm_addr
)
53 comb
+= br_addr
.eq(br_imm_addr
+ self
.i
.cia
)
55 # fields for conditional branches (BO and BI are same for BC and BCREG)
56 # NOTE: here, BO and BI we would like be treated as CR regfile
57 # selectors (similar to RA, RB, RS, RT). see comment here:
58 # https://bugs.libre-soc.org/show_bug.cgi?id=313#c2
59 b_fields
= self
.fields
.instrs
['B']
60 bo
= Signal(b_fields
['BO'][0:-1].shape())
61 bi
= Signal(b_fields
['BI'][0:-1].shape())
62 comb
+= bo
.eq(b_fields
['BO'][0:-1])
63 comb
+= bi
.eq(b_fields
['BI'][0:-1])
65 # The bit of CR selected by BI
66 cr_bit
= Signal(reset_less
=True)
67 comb
+= cr_bit
.eq((self
.i
.cr
& (1<<(31-bi
))) != 0)
69 # Whether the conditional branch should be taken
70 bc_taken
= Signal(reset_less
=True)
72 comb
+= bc_taken
.eq((cr_bit
== bo
[3]) | bo
[4])
74 # Yes, the CTR only counts 32 bits
75 ctr
= Signal(64, reset_less
=True)
76 comb
+= ctr
.eq(self
.i
.ctr
- 1)
77 comb
+= self
.o
.spr
.data
.eq(ctr
)
78 comb
+= self
.o
.spr
.ok
.eq(1)
79 ctr_eq_zero
= Signal(reset_less
=True)
80 comb
+= ctr_eq_zero
.eq(ctr
== 0)
81 with m
.If(bo
[3:5] == 0b00):
82 comb
+= bc_taken
.eq(~cr_bit
& (ctr_eq_zero
== bo
[1]))
83 with m
.Elif(bo
[3:5] == 0b01):
84 comb
+= bc_taken
.eq(cr_bit
& (ctr_eq_zero
== bo
[1]))
85 with m
.Elif(bo
[4] == 1):
86 comb
+= bc_taken
.eq(ctr_eq_zero
== bo
[1])
88 ### Main Switch Statement ###
89 with m
.Switch(op
.insn_type
):
91 with m
.Case(InternalOp
.OP_B
):
92 li
= Signal(i_fields
['LI'][0:-1].shape())
93 comb
+= li
.eq(i_fields
['LI'][0:-1])
94 comb
+= br_imm_addr
.eq(br_ext(li
))
95 comb
+= br_taken
.eq(1)
96 #### branch conditional ####
97 with m
.Case(InternalOp
.OP_BC
):
98 bd
= Signal(b_fields
['BD'][0:-1].shape())
99 comb
+= bd
.eq(b_fields
['BD'][0:-1])
100 comb
+= br_imm_addr
.eq(br_ext(bd
))
101 comb
+= br_taken
.eq(bc_taken
)
102 #### branch conditional reg ####
103 # TODOwith m.Case(InternalOp.OP_BCREG):
105 ###### output next instruction address #####
107 comb
+= nia_out
.data
.eq(br_addr
)
108 comb
+= nia_out
.ok
.eq(br_taken
)
110 ###### link register #####
113 comb
+= lr
.data
.eq(self
.i
.cia
+ 4)
116 ###### and context #####
117 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)