7d21be6a0dcae2993c837a799fa0324fb8454c51
[soc.git] / src / soc / branch / main_stage.py
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
6 # to the output stage
7
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
12
13 from soc.decoder.power_fields import DecodeFields
14 from soc.decoder.power_fieldsn import SignalBitRange
15
16 def br_ext(bd):
17 return Cat(Const(0, 2), bd, Repl(bd[-1], 64-(bd.width + 2)))
18
19
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()
25
26 def ispec(self):
27 return BranchInputData(self.pspec)
28
29 def ospec(self):
30 return BranchOutputData(self.pspec) # TODO: ALUIntermediateData
31
32 def elaborate(self, platform):
33 m = Module()
34 comb = m.d.comb
35 op = self.i.ctx.op
36 nia_out, lr = self.o.nia_out, self.o.lr
37
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])
44
45 br_imm_addr = Signal(64, reset_less=True)
46 br_addr = Signal(64, reset_less=True)
47 br_taken = Signal(reset_less=True)
48
49 # Handle absolute or relative branches
50 with m.If(aa):
51 comb += br_addr.eq(br_imm_addr)
52 with m.Else():
53 comb += br_addr.eq(br_imm_addr + self.i.cia)
54
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])
64
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)
68
69 # Whether the conditional branch should be taken
70 bc_taken = Signal(reset_less=True)
71 with m.If(bo[2]):
72 comb += bc_taken.eq((cr_bit == bo[3]) | bo[4])
73 with m.Else():
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])
87
88 ### Main Switch Statement ###
89 with m.Switch(op.insn_type):
90 #### branch ####
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):
104
105 ###### output next instruction address #####
106
107 comb += nia_out.data.eq(br_addr)
108 comb += nia_out.ok.eq(br_taken)
109
110 ###### link register #####
111
112 with m.If(lk):
113 comb += lr.data.eq(self.i.cia + 4)
114 comb += lr.ok.eq(lk)
115
116 ###### and context #####
117 comb += self.o.ctx.eq(self.i.ctx)
118
119 return m