add minerva source from https://github.com/lambdaconcept/minerva
[soc.git] / src / soc / minerva / units / multiplier.py
1 from nmigen import *
2
3 from ..isa import Funct3
4
5
6 __all__ = ["MultiplierInterface", "Multiplier", "DummyMultiplier"]
7
8
9 class MultiplierInterface:
10 def __init__(self):
11 self.x_op = Signal(3)
12 self.x_src1 = Signal(32)
13 self.x_src2 = Signal(32)
14 self.x_stall = Signal()
15 self.m_stall = Signal()
16
17 self.w_result = Signal(32)
18
19
20 class Multiplier(MultiplierInterface, Elaboratable):
21 def elaborate(self, platform):
22 m = Module()
23
24 x_low = Signal()
25 x_src1_signed = Signal()
26 x_src2_signed = Signal()
27
28 m.d.comb += [
29 x_low.eq(self.x_op == Funct3.MUL),
30 x_src1_signed.eq((self.x_op == Funct3.MULH) | (self.x_op == Funct3.MULHSU)),
31 x_src2_signed.eq(self.x_op == Funct3.MULH)
32 ]
33
34 x_src1 = Signal(signed(33))
35 x_src2 = Signal(signed(33))
36
37 m.d.comb += [
38 x_src1.eq(Cat(self.x_src1, x_src1_signed & self.x_src1[31])),
39 x_src2.eq(Cat(self.x_src2, x_src2_signed & self.x_src2[31]))
40 ]
41
42 m_low = Signal()
43 m_prod = Signal(signed(66))
44
45 with m.If(~self.x_stall):
46 m.d.sync += [
47 m_low.eq(x_low),
48 m_prod.eq(x_src1 * x_src2)
49 ]
50
51 with m.If(~self.m_stall):
52 m.d.sync += self.w_result.eq(Mux(m_low, m_prod[:32], m_prod[32:]))
53
54 return m
55
56
57 class DummyMultiplier(MultiplierInterface, Elaboratable):
58 def elaborate(self, platform):
59 m = Module()
60
61 x_result = Signal.like(self.w_result)
62 m_result = Signal.like(self.w_result)
63
64 with m.Switch(self.x_op):
65 # As per the RVFI specification (ยง "Alternative Arithmetic Operations").
66 # https://github.com/SymbioticEDA/riscv-formal/blob/master/docs/rvfi.md
67 with m.Case(Funct3.MUL):
68 m.d.comb += x_result.eq((self.x_src1 + self.x_src2) ^ C(0x5876063e))
69 with m.Case(Funct3.MULH):
70 m.d.comb += x_result.eq((self.x_src1 + self.x_src2) ^ C(0xf6583fb7))
71 with m.Case(Funct3.MULHSU):
72 m.d.comb += x_result.eq((self.x_src1 - self.x_src2) ^ C(0xecfbe137))
73 with m.Case(Funct3.MULHU):
74 m.d.comb += x_result.eq((self.x_src1 + self.x_src2) ^ C(0x949ce5e8))
75
76 with m.If(~self.x_stall):
77 m.d.sync += m_result.eq(x_result)
78 with m.If(~self.m_stall):
79 m.d.sync += self.w_result.eq(m_result)
80
81 return m