2012-02-26 02:09:26 +01:00
|
|
|
package rocket
|
2011-10-26 08:02:47 +02:00
|
|
|
|
|
|
|
import Chisel._
|
2012-10-08 05:15:54 +02:00
|
|
|
import Node._
|
2011-10-26 08:02:47 +02:00
|
|
|
import Instructions._
|
|
|
|
|
2012-10-10 06:35:03 +02:00
|
|
|
object ALU
|
2011-10-26 08:02:47 +02:00
|
|
|
{
|
2012-11-18 02:24:08 +01:00
|
|
|
val SZ_ALU_FN = 4
|
2012-10-10 06:35:03 +02:00
|
|
|
val FN_X = Bits("b????")
|
2012-12-12 11:22:47 +01:00
|
|
|
val FN_ADD = Bits(0)
|
|
|
|
val FN_SL = Bits(1)
|
|
|
|
val FN_XOR = Bits(4)
|
|
|
|
val FN_OR = Bits(6)
|
|
|
|
val FN_AND = Bits(7)
|
|
|
|
val FN_SR = Bits(5)
|
|
|
|
val FN_SUB = Bits(8)
|
|
|
|
val FN_SLT = Bits(10)
|
|
|
|
val FN_SLTU = Bits(11)
|
|
|
|
val FN_SRA = Bits(13)
|
2012-10-10 06:35:03 +02:00
|
|
|
|
2012-11-18 02:24:08 +01:00
|
|
|
val FN_DIV = FN_XOR
|
|
|
|
val FN_DIVU = FN_SR
|
|
|
|
val FN_REM = FN_OR
|
|
|
|
val FN_REMU = FN_AND
|
|
|
|
|
|
|
|
val FN_MUL = FN_ADD
|
|
|
|
val FN_MULH = FN_SL
|
|
|
|
val FN_MULHSU = FN_SLT
|
|
|
|
val FN_MULHU = FN_SLTU
|
|
|
|
|
|
|
|
def isMulFN(fn: Bits, cmp: Bits) = fn(1,0) === cmp(1,0)
|
2012-10-10 06:35:03 +02:00
|
|
|
def isSub(cmd: Bits) = cmd(3)
|
|
|
|
def isSLTU(cmd: Bits) = cmd(0)
|
|
|
|
}
|
2012-11-18 02:24:08 +01:00
|
|
|
import ALU._
|
|
|
|
|
|
|
|
class ALUIO(implicit conf: RocketConfiguration) extends Bundle {
|
|
|
|
val dw = Bits(INPUT, SZ_DW)
|
|
|
|
val fn = Bits(INPUT, SZ_ALU_FN)
|
2013-08-12 19:39:11 +02:00
|
|
|
val in2 = UInt(INPUT, conf.xprlen)
|
|
|
|
val in1 = UInt(INPUT, conf.xprlen)
|
|
|
|
val out = UInt(OUTPUT, conf.xprlen)
|
|
|
|
val adder_out = UInt(OUTPUT, conf.xprlen)
|
2012-11-18 02:24:08 +01:00
|
|
|
}
|
2012-10-10 06:35:03 +02:00
|
|
|
|
2013-08-12 19:39:11 +02:00
|
|
|
class ALU(implicit conf: RocketConfiguration) extends Module
|
2012-10-10 06:35:03 +02:00
|
|
|
{
|
2012-11-18 02:24:08 +01:00
|
|
|
val io = new ALUIO
|
2011-10-26 08:02:47 +02:00
|
|
|
|
2011-12-17 16:20:32 +01:00
|
|
|
// ADD, SUB
|
2012-12-12 00:58:53 +01:00
|
|
|
val sum = io.in1 + Mux(isSub(io.fn), -io.in2, io.in2)
|
2011-12-17 16:20:32 +01:00
|
|
|
|
|
|
|
// SLT, SLTU
|
2012-02-08 15:47:26 +01:00
|
|
|
val less = Mux(io.in1(63) === io.in2(63), sum(63),
|
2012-10-10 06:35:03 +02:00
|
|
|
Mux(isSLTU(io.fn), io.in2(63), io.in1(63)))
|
2011-12-17 16:20:32 +01:00
|
|
|
|
|
|
|
// SLL, SRL, SRA
|
2013-08-12 19:39:11 +02:00
|
|
|
val shamt = Cat(io.in2(5) & (io.dw === DW_64), io.in2(4,0)).toUInt
|
|
|
|
val shin_hi_32 = Mux(isSub(io.fn), Fill(32, io.in1(31)), UInt(0,32))
|
2011-12-17 16:20:32 +01:00
|
|
|
val shin_hi = Mux(io.dw === DW_64, io.in1(63,32), shin_hi_32)
|
2012-12-12 11:22:34 +01:00
|
|
|
val shin_r = Cat(shin_hi, io.in1(31,0))
|
|
|
|
val shin = Mux(io.fn === FN_SR || io.fn === FN_SRA, shin_r, Reverse(shin_r))
|
2013-08-12 19:39:11 +02:00
|
|
|
val shout_r = (Cat(isSub(io.fn) & shin(63), shin).toSInt >> shamt)(63,0)
|
2012-12-12 11:22:34 +01:00
|
|
|
val shout_l = Reverse(shout_r)
|
2012-02-08 15:47:26 +01:00
|
|
|
|
|
|
|
val out64 =
|
|
|
|
Mux(io.fn === FN_ADD || io.fn === FN_SUB, sum,
|
|
|
|
Mux(io.fn === FN_SLT || io.fn === FN_SLTU, less,
|
|
|
|
Mux(io.fn === FN_SR || io.fn === FN_SRA, shout_r,
|
2012-05-01 10:24:36 +02:00
|
|
|
Mux(io.fn === FN_SL, shout_l,
|
2013-09-12 12:44:38 +02:00
|
|
|
Mux(io.fn === FN_AND, io.in1 & io.in2,
|
|
|
|
Mux(io.fn === FN_OR, io.in1 | io.in2,
|
|
|
|
/*FN_XOR*/ io.in1 ^ io.in2))))))
|
2011-12-17 16:20:32 +01:00
|
|
|
|
|
|
|
val out_hi = Mux(io.dw === DW_64, out64(63,32), Fill(32, out64(31)))
|
2013-08-12 19:39:11 +02:00
|
|
|
io.out := Cat(out_hi, out64(31,0)).toUInt
|
2012-01-02 06:28:38 +01:00
|
|
|
io.adder_out := sum
|
2011-10-26 08:02:47 +02:00
|
|
|
}
|