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 chisel3._ 20import chisel3.util._ 21import utility._ 22import utils._ 23import xiangshan._ 24import xiangshan.backend.fu.util.{C22, C32, C53} 25 26class MulDivCtrl extends Bundle{ 27 val sign = Bool() 28 val isW = Bool() 29 val isHi = Bool() // return hi bits of result ? 30} 31 32class ArrayMulDataModule(len: Int) extends Module { 33 val io = IO(new Bundle() { 34 val a, b = Input(UInt(len.W)) 35 val regEnables = Input(Vec(2, Bool())) 36 val result = Output(UInt((2 * len).W)) 37 }) 38 val (a, b) = (io.a, io.b) 39 40 val b_sext, bx2, neg_b, neg_bx2 = Wire(UInt((len+1).W)) 41 b_sext := SignExt(b, len+1) 42 bx2 := b_sext << 1 43 neg_b := (~b_sext).asUInt() 44 neg_bx2 := neg_b << 1 45 46 val columns: Array[Seq[Bool]] = Array.fill(2*len)(Seq()) 47 48 var last_x = WireInit(0.U(3.W)) 49 for(i <- Range(0, len, 2)){ 50 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) 51 val pp_temp = MuxLookup(x, 0.U, Seq( 52 1.U -> b_sext, 53 2.U -> b_sext, 54 3.U -> bx2, 55 4.U -> neg_bx2, 56 5.U -> neg_b, 57 6.U -> neg_b 58 )) 59 val s = pp_temp(len) 60 val t = MuxLookup(last_x, 0.U(2.W), Seq( 61 4.U -> 2.U(2.W), 62 5.U -> 1.U(2.W), 63 6.U -> 1.U(2.W) 64 )) 65 last_x = x 66 val (pp, weight) = i match { 67 case 0 => 68 (Cat(~s, s, s, pp_temp), 0) 69 case n if (n==len-1) || (n==len-2) => 70 (Cat(~s, pp_temp, t), i-2) 71 case _ => 72 (Cat(1.U(1.W), ~s, pp_temp, t), i-2) 73 } 74 for(j <- columns.indices){ 75 if(j >= weight && j < (weight + pp.getWidth)){ 76 columns(j) = columns(j) :+ pp(j-weight) 77 } 78 } 79 } 80 81 def addOneColumn(col: Seq[Bool], cin: Seq[Bool]): (Seq[Bool], Seq[Bool], Seq[Bool]) = { 82 var sum = Seq[Bool]() 83 var cout1 = Seq[Bool]() 84 var cout2 = Seq[Bool]() 85 col.size match { 86 case 1 => // do nothing 87 sum = col ++ cin 88 case 2 => 89 val c22 = Module(new C22) 90 c22.io.in := col 91 sum = c22.io.out(0).asBool() +: cin 92 cout2 = Seq(c22.io.out(1).asBool()) 93 case 3 => 94 val c32 = Module(new C32) 95 c32.io.in := col 96 sum = c32.io.out(0).asBool() +: cin 97 cout2 = Seq(c32.io.out(1).asBool()) 98 case 4 => 99 val c53 = Module(new C53) 100 for((x, y) <- c53.io.in.take(4) zip col){ 101 x := y 102 } 103 c53.io.in.last := (if(cin.nonEmpty) cin.head else 0.U) 104 sum = Seq(c53.io.out(0).asBool()) ++ (if(cin.nonEmpty) cin.drop(1) else Nil) 105 cout1 = Seq(c53.io.out(1).asBool()) 106 cout2 = Seq(c53.io.out(2).asBool()) 107 case n => 108 val cin_1 = if(cin.nonEmpty) Seq(cin.head) else Nil 109 val cin_2 = if(cin.nonEmpty) cin.drop(1) else Nil 110 val (s_1, c_1_1, c_1_2) = addOneColumn(col take 4, cin_1) 111 val (s_2, c_2_1, c_2_2) = addOneColumn(col drop 4, cin_2) 112 sum = s_1 ++ s_2 113 cout1 = c_1_1 ++ c_2_1 114 cout2 = c_1_2 ++ c_2_2 115 } 116 (sum, cout1, cout2) 117 } 118 119 def max(in: Iterable[Int]): Int = in.reduce((a, b) => if(a>b) a else b) 120 def addAll(cols: Array[Seq[Bool]], depth: Int): (UInt, UInt) = { 121 if(max(cols.map(_.size)) <= 2){ 122 val sum = Cat(cols.map(_(0)).reverse) 123 var k = 0 124 while(cols(k).size == 1) k = k+1 125 val carry = Cat(cols.drop(k).map(_(1)).reverse) 126 (sum, Cat(carry, 0.U(k.W))) 127 } else { 128 val columns_next = Array.fill(2*len)(Seq[Bool]()) 129 var cout1, cout2 = Seq[Bool]() 130 for( i <- cols.indices){ 131 val (s, c1, c2) = addOneColumn(cols(i), cout1) 132 columns_next(i) = s ++ cout2 133 cout1 = c1 134 cout2 = c2 135 } 136 137 val needReg = depth == 4 138 val toNextLayer = if(needReg) 139 columns_next.map(_.map(x => RegEnable(x, io.regEnables(1)))) 140 else 141 columns_next 142 143 addAll(toNextLayer, depth+1) 144 } 145 } 146 147 val columns_reg = columns.map(col => col.map(b => RegEnable(b, io.regEnables(0)))) 148 val (sum, carry) = addAll(cols = columns_reg, depth = 0) 149 150 io.result := sum + carry 151} 152