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