2012-02-26 02:09:26 +01:00
|
|
|
package rocket
|
2011-10-26 08:02:47 +02:00
|
|
|
|
|
|
|
import Chisel._
|
2012-02-25 04:22:35 +01:00
|
|
|
import Node._
|
|
|
|
import Constants._
|
|
|
|
import hwacha._
|
2012-02-26 00:55:10 +01:00
|
|
|
import hwacha.Constants._
|
2012-02-25 04:22:35 +01:00
|
|
|
|
|
|
|
class ioMultiplier extends Bundle {
|
2012-03-02 05:48:46 +01:00
|
|
|
val req = new io_imul_req().flip
|
2012-11-05 01:40:14 +01:00
|
|
|
val req_tag = UFix(INPUT, 5)
|
2012-02-25 04:22:35 +01:00
|
|
|
val req_kill = Bool(INPUT)
|
|
|
|
val resp_val = Bool(OUTPUT)
|
|
|
|
val resp_rdy = Bool(INPUT)
|
2012-11-05 01:40:14 +01:00
|
|
|
val resp_tag = UFix(OUTPUT, 5)
|
2012-07-13 03:12:49 +02:00
|
|
|
val resp_bits = Bits(OUTPUT, SZ_XLEN)
|
2012-02-25 04:22:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
class rocketVUMultiplier(nwbq: Int) extends Component {
|
|
|
|
val io = new Bundle {
|
|
|
|
val cpu = new ioMultiplier
|
|
|
|
val vu = new Bundle {
|
|
|
|
val req = new io_imul_req
|
2012-07-13 03:12:49 +02:00
|
|
|
val resp = Bits(INPUT, SZ_XLEN)
|
2012-02-25 04:22:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
val valid = Reg(resetVal = Bits(0, IMUL_STAGES))
|
2012-06-06 21:47:17 +02:00
|
|
|
val wbq_cnt = Reg(resetVal = Bits(0, log2Up(nwbq+1)))
|
2012-02-25 04:22:35 +01:00
|
|
|
val tag = Vec(IMUL_STAGES) { Reg() { Bits() } }
|
|
|
|
|
|
|
|
val fire = io.cpu.req.valid && io.cpu.req.ready
|
|
|
|
|
|
|
|
valid := Cat(fire, valid(IMUL_STAGES-1) && !io.cpu.req_kill, valid(IMUL_STAGES-2,1))
|
|
|
|
when (fire) {
|
|
|
|
tag(IMUL_STAGES-1) := io.cpu.req_tag
|
|
|
|
}
|
|
|
|
for (i <- 0 until IMUL_STAGES-1) {
|
|
|
|
tag(i) := tag(i+1)
|
|
|
|
}
|
|
|
|
when (valid(0) != (io.cpu.resp_val && io.cpu.resp_rdy)) {
|
|
|
|
wbq_cnt := Mux(valid(0), wbq_cnt + UFix(1), wbq_cnt - UFix(1))
|
|
|
|
}
|
|
|
|
|
|
|
|
var inflight_cnt = valid(0)
|
|
|
|
for (i <- 1 until IMUL_STAGES)
|
|
|
|
inflight_cnt = inflight_cnt + valid(i)
|
|
|
|
inflight_cnt = inflight_cnt + wbq_cnt
|
|
|
|
val wbq_rdy = inflight_cnt < UFix(nwbq)
|
|
|
|
|
2012-08-09 07:11:32 +02:00
|
|
|
val wbq = (new Queue(nwbq)) { Bits(width = io.cpu.resp_bits.width + io.cpu.resp_tag.width) }
|
2012-02-25 04:22:35 +01:00
|
|
|
wbq.io.enq.valid := valid(0)
|
|
|
|
wbq.io.enq.bits := Cat(io.vu.resp, tag(0))
|
|
|
|
wbq.io.deq.ready := io.cpu.resp_rdy
|
|
|
|
|
|
|
|
io.cpu.req.ready := io.vu.req.ready && wbq_rdy
|
|
|
|
io.cpu.resp_val := wbq.io.deq.valid
|
|
|
|
io.cpu.resp_bits := wbq.io.deq.bits >> UFix(io.cpu.resp_tag.width)
|
|
|
|
io.cpu.resp_tag := wbq.io.deq.bits(io.cpu.resp_tag.width-1,0)
|
|
|
|
|
|
|
|
io.vu.req <> io.cpu.req
|
2011-10-26 08:02:47 +02:00
|
|
|
}
|
|
|
|
|
2012-10-10 03:29:50 +02:00
|
|
|
class rocketMultiplier(unroll: Int = 1, earlyOut: Boolean = false) extends Component {
|
2012-02-25 04:22:35 +01:00
|
|
|
val io = new ioMultiplier
|
2011-12-20 13:18:28 +01:00
|
|
|
|
2012-10-07 02:32:01 +02:00
|
|
|
val w0 = io.req.bits.in0.getWidth
|
|
|
|
val w = (w0+1+unroll-1)/unroll*unroll
|
|
|
|
val cycles = w/unroll
|
2011-10-26 08:02:47 +02:00
|
|
|
|
|
|
|
val r_val = Reg(resetVal = Bool(false));
|
2012-02-25 04:22:35 +01:00
|
|
|
val r_dw = Reg { Bits() }
|
|
|
|
val r_fn = Reg { Bits() }
|
2012-11-05 01:40:14 +01:00
|
|
|
val r_tag = Reg { UFix() }
|
2011-12-20 12:49:07 +01:00
|
|
|
val r_lhs = Reg { Bits() }
|
2012-02-25 04:22:35 +01:00
|
|
|
val r_prod= Reg { Bits(width = w*2) }
|
2011-12-20 12:49:07 +01:00
|
|
|
val r_lsb = Reg { Bits() }
|
2012-06-06 21:47:17 +02:00
|
|
|
val r_cnt = Reg { UFix(width = log2Up(cycles+1)) }
|
2011-12-17 16:20:00 +01:00
|
|
|
|
2012-02-25 04:22:35 +01:00
|
|
|
val dw = io.req.bits.fn(io.req.bits.fn.width-1)
|
|
|
|
val fn = io.req.bits.fn(io.req.bits.fn.width-2,0)
|
|
|
|
|
2012-10-07 02:32:01 +02:00
|
|
|
val lhs_msb = Mux(dw === DW_64, io.req.bits.in0(w0-1), io.req.bits.in0(w0/2-1)).toBool
|
2012-02-25 04:22:35 +01:00
|
|
|
val lhs_sign = ((fn === MUL_H) || (fn === MUL_HSU)) && lhs_msb
|
2012-10-07 02:32:01 +02:00
|
|
|
val lhs_hi = Mux(dw === DW_64, io.req.bits.in0(w0-1,w0/2), Fill(w0/2, lhs_sign))
|
|
|
|
val lhs_in = Cat(lhs_sign, lhs_hi, io.req.bits.in0(w0/2-1,0))
|
2011-12-17 16:20:00 +01:00
|
|
|
|
2012-10-07 02:32:01 +02:00
|
|
|
val rhs_msb = Mux(dw === DW_64, io.req.bits.in1(w0-1), io.req.bits.in1(w0/2-1)).toBool
|
2012-02-25 04:22:35 +01:00
|
|
|
val rhs_sign = (fn === MUL_H) && rhs_msb
|
2012-10-07 02:32:01 +02:00
|
|
|
val rhs_hi = Mux(dw === DW_64, io.req.bits.in1(w0-1,w0/2), Fill(w0/2, rhs_sign))
|
|
|
|
val rhs_in = Cat(Fill(w-w0, rhs_sign), rhs_hi, io.req.bits.in1(w0/2-1,0))
|
2011-10-26 08:02:47 +02:00
|
|
|
|
2012-02-25 04:22:35 +01:00
|
|
|
when (io.req.valid && io.req.ready) {
|
2012-02-12 02:20:33 +01:00
|
|
|
r_val := Bool(true)
|
2012-06-06 21:47:17 +02:00
|
|
|
r_cnt := UFix(0, log2Up(cycles+1))
|
2012-02-25 04:22:35 +01:00
|
|
|
r_dw := dw
|
|
|
|
r_fn := fn
|
|
|
|
r_tag := io.req_tag
|
2012-02-12 02:20:33 +01:00
|
|
|
r_lhs := lhs_in
|
|
|
|
r_prod:= rhs_in
|
|
|
|
r_lsb := Bool(false)
|
2011-10-26 08:02:47 +02:00
|
|
|
}
|
2012-10-10 06:35:03 +02:00
|
|
|
.elsewhen (io.resp_val && io.resp_rdy || io.req_kill) {
|
2012-02-12 02:20:33 +01:00
|
|
|
r_val := Bool(false)
|
2011-12-20 12:49:07 +01:00
|
|
|
}
|
|
|
|
|
2012-10-10 03:29:50 +02:00
|
|
|
val eOutDist = (UFix(cycles)-r_cnt)*UFix(unroll)
|
|
|
|
val outShift = Mux(r_fn === MUL_LO, UFix(0), Mux(r_dw === DW_64, UFix(64), UFix(32)))
|
|
|
|
val shiftDist = Mux(r_cnt === UFix(cycles), outShift, eOutDist)
|
|
|
|
val eOutMask = (UFix(1) << eOutDist) - UFix(1)
|
|
|
|
val eOut = r_cnt != UFix(0) && Bool(earlyOut) && !((r_prod(w-1,0) ^ r_lsb.toFix) & eOutMask).orR
|
|
|
|
val shift = r_prod.toFix >> shiftDist
|
|
|
|
|
2012-10-07 02:32:01 +02:00
|
|
|
val sum = r_prod(2*w-1,w).toFix + r_prod(unroll-1,0).toFix * r_lhs.toFix + Mux(r_lsb, r_lhs.toFix, Fix(0))
|
2011-12-20 12:49:07 +01:00
|
|
|
when (r_val && (r_cnt != UFix(cycles))) {
|
2012-10-07 02:32:01 +02:00
|
|
|
r_lsb := r_prod(unroll-1)
|
|
|
|
r_prod := Cat(sum, r_prod(w-1,unroll)).toFix
|
2012-02-12 02:20:33 +01:00
|
|
|
r_cnt := r_cnt + UFix(1)
|
2012-10-10 03:29:50 +02:00
|
|
|
when (eOut) {
|
|
|
|
r_prod := shift
|
|
|
|
r_cnt := UFix(cycles)
|
|
|
|
}
|
2011-12-20 12:49:07 +01:00
|
|
|
}
|
|
|
|
|
2012-10-10 03:29:50 +02:00
|
|
|
val out32 = Cat(Fill(w0/2, shift(w0/2-1)), shift(w0/2-1,0))
|
|
|
|
val out64 = shift(w0-1,0)
|
2011-12-17 16:30:47 +01:00
|
|
|
|
2012-02-25 04:22:35 +01:00
|
|
|
io.req.ready := !r_val
|
2012-10-10 03:29:50 +02:00
|
|
|
io.resp_bits := Mux(r_dw === DW_64, out64, out32)
|
2012-02-25 04:22:35 +01:00
|
|
|
io.resp_tag := r_tag;
|
|
|
|
io.resp_val := r_val && (r_cnt === UFix(cycles))
|
2011-10-26 08:02:47 +02:00
|
|
|
}
|