xref: /XiangShan/src/main/scala/xiangshan/cache/dcache/mainpipe/AMOALU.scala (revision 38c29594d00da67087523376f6a6f3243679884e)
1// See LICENSE.SiFive for license details.
2// See LICENSE.Berkeley for license details.
3
4/***************************************************************************************
5* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
6* Copyright (c) 2020-2021 Peng Cheng Laboratory
7*
8* XiangShan is licensed under Mulan PSL v2.
9* You can use this software according to the terms and conditions of the Mulan PSL v2.
10* You may obtain a copy of Mulan PSL v2 at:
11*          http://license.coscl.org.cn/MulanPSL2
12*
13* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
14* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
15* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
16*
17* See the Mulan PSL v2 for more details.
18***************************************************************************************/
19
20package xiangshan.cache
21
22import chisel3._
23import chisel3.util._
24
25class AMOALU(operandBits: Int) extends Module
26  with MemoryOpConstants {
27  val minXLen = 32
28  val widths = (0 to log2Ceil(operandBits / minXLen)).map(minXLen << _)
29
30  val io = IO(new Bundle {
31    val mask = Input(UInt((operandBits/8).W))
32    val cmd = Input(Bits(M_SZ.W))
33    val lhs = Input(Bits(operandBits.W))
34    val rhs = Input(Bits(operandBits.W))
35    val out = Output(Bits(operandBits.W))
36    val out_unmasked = Output(Bits(operandBits.W))
37  })
38
39  val max = io.cmd === M_XA_MAX || io.cmd === M_XA_MAXU
40  val min = io.cmd === M_XA_MIN || io.cmd === M_XA_MINU
41  val add = io.cmd === M_XA_ADD
42  val logic_and = io.cmd === M_XA_OR || io.cmd === M_XA_AND
43  val logic_xor = io.cmd === M_XA_XOR || io.cmd === M_XA_OR
44
45  val adder_out = {
46    // partition the carry chain to support sub-xLen addition
47    val mask = ~(0.U(operandBits.W) +: widths.init.map(w => !io.mask(w/8-1) << (w-1))).reduce(_|_)
48    (io.lhs & mask) + (io.rhs & mask)
49  }
50
51  val less = {
52    // break up the comparator so the lower parts will be CSE'd
53    def isLessUnsigned(x: UInt, y: UInt, n: Int): Bool = {
54      if (n == minXLen) x(n-1, 0) < y(n-1, 0)
55      else x(n-1, n/2) < y(n-1, n/2) || x(n-1, n/2) === y(n-1, n/2) && isLessUnsigned(x, y, n/2)
56    }
57
58    def isLess(x: UInt, y: UInt, n: Int): Bool = {
59      val signed = {
60        val mask = M_XA_MIN ^ M_XA_MINU
61        (io.cmd & mask) === (M_XA_MIN & mask)
62      }
63      Mux(x(n-1) === y(n-1), isLessUnsigned(x, y, n), Mux(signed, x(n-1), y(n-1)))
64    }
65
66    PriorityMux(widths.reverse.map(w => (io.mask(w/8/2), isLess(io.lhs, io.rhs, w))))
67  }
68
69  val minmax = Mux(Mux(less, min, max), io.lhs, io.rhs)
70  val logic =
71    Mux(logic_and, io.lhs & io.rhs, 0.U) |
72    Mux(logic_xor, io.lhs ^ io.rhs, 0.U)
73  val out =
74    Mux(add,                    adder_out,
75    Mux(logic_and || logic_xor, logic,
76                                minmax))
77
78  val wmask = FillInterleaved(8, io.mask)
79  io.out := wmask & out | ~wmask & io.lhs
80  io.out_unmasked := out
81}
82