1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* Copyright (c) 2020-2021 Peng Cheng Laboratory 4* 5* XiangShan is licensed under Mulan PSL v2. 6* You can use this software according to the terms and conditions of the Mulan PSL v2. 7* You may obtain a copy of Mulan PSL v2 at: 8* http://license.coscl.org.cn/MulanPSL2 9* 10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13* 14* See the Mulan PSL v2 for more details. 15***************************************************************************************/ 16 17package xiangshan.backend.fu 18 19import org.chipsalliance.cde.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import utility._ 23import utils._ 24import xiangshan._ 25import xiangshan.backend.fu.util.{C22, C32, C53} 26 27class MulDivCtrl extends Bundle{ 28 val sign = Bool() 29 val isW = Bool() 30 val isHi = Bool() // return hi bits of result ? 31} 32 33class ArrayMulDataModule(len: Int) extends Module { 34 val io = IO(new Bundle() { 35 val a, b = Input(UInt(len.W)) 36 val regEnables = Input(Vec(2, Bool())) 37 val result = Output(UInt((2 * len).W)) 38 }) 39 val (a, b) = (io.a, io.b) 40 41 val b_sext, bx2, neg_b, neg_bx2 = Wire(UInt((len+1).W)) 42 b_sext := SignExt(b, len+1) 43 bx2 := b_sext << 1 44 neg_b := (~b_sext).asUInt 45 neg_bx2 := neg_b << 1 46 47 val columns: Array[Seq[Bool]] = Array.fill(2*len)(Seq()) 48 49 var last_x = WireInit(0.U(3.W)) 50 for(i <- Range(0, len, 2)){ 51 val x = if(i==0) Cat(a(1,0), 0.U(1.W)) else if(i+1==len) SignExt(a(i, i-1), 3) else a(i+1, i-1) 52 val pp_temp = MuxLookup(x, 0.U)(Seq( 53 1.U -> b_sext, 54 2.U -> b_sext, 55 3.U -> bx2, 56 4.U -> neg_bx2, 57 5.U -> neg_b, 58 6.U -> neg_b 59 )) 60 val s = pp_temp(len) 61 val t = MuxLookup(last_x, 0.U(2.W))(Seq( 62 4.U -> 2.U(2.W), 63 5.U -> 1.U(2.W), 64 6.U -> 1.U(2.W) 65 )) 66 last_x = x 67 val (pp, weight) = i match { 68 case 0 => 69 (Cat(~s, s, s, pp_temp), 0) 70 case n if (n==len-1) || (n==len-2) => 71 (Cat(~s, pp_temp, t), i-2) 72 case _ => 73 (Cat(1.U(1.W), ~s, pp_temp, t), i-2) 74 } 75 for(j <- columns.indices){ 76 if(j >= weight && j < (weight + pp.getWidth)){ 77 columns(j) = columns(j) :+ pp(j-weight) 78 } 79 } 80 } 81 82 def addOneColumn(col: Seq[Bool], cin: Seq[Bool]): (Seq[Bool], Seq[Bool], Seq[Bool]) = { 83 var sum = Seq[Bool]() 84 var cout1 = Seq[Bool]() 85 var cout2 = Seq[Bool]() 86 col.size match { 87 case 1 => // do nothing 88 sum = col ++ cin 89 case 2 => 90 val c22 = Module(new C22) 91 c22.io.in := col 92 sum = c22.io.out(0).asBool +: cin 93 cout2 = Seq(c22.io.out(1).asBool) 94 case 3 => 95 val c32 = Module(new C32) 96 c32.io.in := col 97 sum = c32.io.out(0).asBool +: cin 98 cout2 = Seq(c32.io.out(1).asBool) 99 case 4 => 100 val c53 = Module(new C53) 101 for((x, y) <- c53.io.in.take(4) zip col){ 102 x := y 103 } 104 c53.io.in.last := (if(cin.nonEmpty) cin.head else 0.U) 105 sum = Seq(c53.io.out(0).asBool) ++ (if(cin.nonEmpty) cin.drop(1) else Nil) 106 cout1 = Seq(c53.io.out(1).asBool) 107 cout2 = Seq(c53.io.out(2).asBool) 108 case n => 109 val cin_1 = if(cin.nonEmpty) Seq(cin.head) else Nil 110 val cin_2 = if(cin.nonEmpty) cin.drop(1) else Nil 111 val (s_1, c_1_1, c_1_2) = addOneColumn(col take 4, cin_1) 112 val (s_2, c_2_1, c_2_2) = addOneColumn(col drop 4, cin_2) 113 sum = s_1 ++ s_2 114 cout1 = c_1_1 ++ c_2_1 115 cout2 = c_1_2 ++ c_2_2 116 } 117 (sum, cout1, cout2) 118 } 119 120 def max(in: Iterable[Int]): Int = in.reduce((a, b) => if(a>b) a else b) 121 def addAll(cols: Array[Seq[Bool]], depth: Int): (UInt, UInt) = { 122 if(max(cols.map(_.size)) <= 2){ 123 val sum = Cat(cols.map(_(0)).reverse) 124 var k = 0 125 while(cols(k).size == 1) k = k+1 126 val carry = Cat(cols.drop(k).map(_(1)).reverse) 127 (sum, Cat(carry, 0.U(k.W))) 128 } else { 129 val columns_next = Array.fill(2*len)(Seq[Bool]()) 130 var cout1, cout2 = Seq[Bool]() 131 for( i <- cols.indices){ 132 val (s, c1, c2) = addOneColumn(cols(i), cout1) 133 columns_next(i) = s ++ cout2 134 cout1 = c1 135 cout2 = c2 136 } 137 138 val needReg = depth == 4 139 val toNextLayer = if(needReg) 140 columns_next.map(_.map(x => RegEnable(x, io.regEnables(1)))) 141 else 142 columns_next 143 144 addAll(toNextLayer, depth+1) 145 } 146 } 147 148 val columns_reg = columns.map(col => col.map(b => RegEnable(b, io.regEnables(0)))) 149 val (sum, carry) = addAll(cols = columns_reg, depth = 0) 150 151 io.result := sum + carry 152} 153