2016-11-28 01:16:37 +01:00
|
|
|
// See LICENSE.SiFive for license details.
|
|
|
|
// See LICENSE.Berkeley for license details.
|
2014-09-13 03:06:41 +02:00
|
|
|
|
2012-02-26 02:09:26 +01:00
|
|
|
package rocket
|
2011-10-26 08:02:47 +02:00
|
|
|
|
|
|
|
import Chisel._
|
2016-11-18 23:05:14 +01:00
|
|
|
import config._
|
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
|
2017-01-31 22:54:02 +01:00
|
|
|
def FN_X = BitPat("b????")
|
|
|
|
def FN_ADD = UInt(0)
|
|
|
|
def FN_SL = UInt(1)
|
|
|
|
def FN_SEQ = UInt(2)
|
|
|
|
def FN_SNE = UInt(3)
|
|
|
|
def FN_XOR = UInt(4)
|
|
|
|
def FN_SR = UInt(5)
|
|
|
|
def FN_OR = UInt(6)
|
|
|
|
def FN_AND = UInt(7)
|
|
|
|
def FN_SUB = UInt(10)
|
|
|
|
def FN_SRA = UInt(11)
|
|
|
|
def FN_SLT = UInt(12)
|
|
|
|
def FN_SGE = UInt(13)
|
|
|
|
def FN_SLTU = UInt(14)
|
|
|
|
def FN_SGEU = UInt(15)
|
2012-10-10 06:35:03 +02:00
|
|
|
|
2017-01-31 22:54:02 +01:00
|
|
|
def FN_DIV = FN_XOR
|
|
|
|
def FN_DIVU = FN_SR
|
|
|
|
def FN_REM = FN_OR
|
|
|
|
def FN_REMU = FN_AND
|
2012-11-18 02:24:08 +01:00
|
|
|
|
2017-01-31 22:54:02 +01:00
|
|
|
def FN_MUL = FN_ADD
|
|
|
|
def FN_MULH = FN_SL
|
|
|
|
def FN_MULHSU = FN_SLT
|
|
|
|
def FN_MULHU = FN_SLTU
|
2012-11-18 02:24:08 +01:00
|
|
|
|
2016-01-21 02:42:31 +01:00
|
|
|
def isMulFN(fn: UInt, cmp: UInt) = fn(1,0) === cmp(1,0)
|
|
|
|
def isSub(cmd: UInt) = cmd(3)
|
|
|
|
def isCmp(cmd: UInt) = cmd === FN_SEQ || cmd === FN_SNE || cmd >= FN_SLT
|
|
|
|
def cmpUnsigned(cmd: UInt) = cmd(1)
|
|
|
|
def cmpInverted(cmd: UInt) = cmd(0)
|
|
|
|
def cmpEq(cmd: UInt) = !cmd(3)
|
2012-10-10 06:35:03 +02:00
|
|
|
}
|
2012-11-18 02:24:08 +01:00
|
|
|
import ALU._
|
|
|
|
|
2015-12-01 02:35:33 +01:00
|
|
|
class ALU(implicit p: Parameters) extends CoreModule()(p) {
|
2015-11-25 04:17:07 +01:00
|
|
|
val io = new Bundle {
|
|
|
|
val dw = Bits(INPUT, SZ_DW)
|
|
|
|
val fn = Bits(INPUT, SZ_ALU_FN)
|
|
|
|
val in2 = UInt(INPUT, xLen)
|
|
|
|
val in1 = UInt(INPUT, xLen)
|
|
|
|
val out = UInt(OUTPUT, xLen)
|
|
|
|
val adder_out = UInt(OUTPUT, xLen)
|
2016-01-21 02:42:31 +01:00
|
|
|
val cmp_out = Bool(OUTPUT)
|
2015-11-25 04:17:07 +01:00
|
|
|
}
|
2011-10-26 08:02:47 +02:00
|
|
|
|
2011-12-17 16:20:32 +01:00
|
|
|
// ADD, SUB
|
2016-01-21 02:42:31 +01:00
|
|
|
val in2_inv = Mux(isSub(io.fn), ~io.in2, io.in2)
|
|
|
|
val in1_xor_in2 = io.in1 ^ in2_inv
|
|
|
|
io.adder_out := io.in1 + in2_inv + isSub(io.fn)
|
2011-12-17 16:20:32 +01:00
|
|
|
|
|
|
|
// SLT, SLTU
|
2016-01-21 02:42:31 +01:00
|
|
|
io.cmp_out := cmpInverted(io.fn) ^
|
|
|
|
Mux(cmpEq(io.fn), in1_xor_in2 === UInt(0),
|
|
|
|
Mux(io.in1(xLen-1) === io.in2(xLen-1), io.adder_out(xLen-1),
|
2015-11-25 04:17:07 +01:00
|
|
|
Mux(cmpUnsigned(io.fn), io.in2(xLen-1), io.in1(xLen-1))))
|
2011-12-17 16:20:32 +01:00
|
|
|
|
|
|
|
// SLL, SRL, SRA
|
2015-11-25 04:17:07 +01:00
|
|
|
val (shamt, shin_r) =
|
2016-01-21 02:42:31 +01:00
|
|
|
if (xLen == 32) (io.in2(4,0), io.in1)
|
2015-11-25 04:17:07 +01:00
|
|
|
else {
|
|
|
|
require(xLen == 64)
|
|
|
|
val shin_hi_32 = Fill(32, isSub(io.fn) && io.in1(31))
|
|
|
|
val shin_hi = Mux(io.dw === DW_64, io.in1(63,32), shin_hi_32)
|
2016-01-21 02:42:31 +01:00
|
|
|
val shamt = Cat(io.in2(5) & (io.dw === DW_64), io.in2(4,0))
|
2015-11-25 04:17:07 +01:00
|
|
|
(shamt, Cat(shin_hi, io.in1(31,0)))
|
|
|
|
}
|
2012-12-12 11:22:34 +01:00
|
|
|
val shin = Mux(io.fn === FN_SR || io.fn === FN_SRA, shin_r, Reverse(shin_r))
|
2016-08-01 02:13:52 +02:00
|
|
|
val shout_r = (Cat(isSub(io.fn) & shin(xLen-1), shin).asSInt >> shamt)(xLen-1,0)
|
2012-12-12 11:22:34 +01:00
|
|
|
val shout_l = Reverse(shout_r)
|
2016-01-21 02:42:31 +01:00
|
|
|
val shout = Mux(io.fn === FN_SR || io.fn === FN_SRA, shout_r, UInt(0)) |
|
|
|
|
Mux(io.fn === FN_SL, shout_l, UInt(0))
|
2012-02-08 15:47:26 +01:00
|
|
|
|
2016-01-21 02:42:31 +01:00
|
|
|
// AND, OR, XOR
|
|
|
|
val logic = Mux(io.fn === FN_XOR || io.fn === FN_OR, in1_xor_in2, UInt(0)) |
|
|
|
|
Mux(io.fn === FN_OR || io.fn === FN_AND, io.in1 & io.in2, UInt(0))
|
|
|
|
val shift_logic = (isCmp(io.fn) && io.cmp_out) | logic | shout
|
|
|
|
val out = Mux(io.fn === FN_ADD || io.fn === FN_SUB, io.adder_out, shift_logic)
|
2011-12-17 16:20:32 +01:00
|
|
|
|
2015-11-25 04:17:07 +01:00
|
|
|
io.out := out
|
|
|
|
if (xLen > 32) {
|
|
|
|
require(xLen == 64)
|
|
|
|
when (io.dw === DW_32) { io.out := Cat(Fill(32, out(31)), out(31,0)) }
|
|
|
|
}
|
2011-10-26 08:02:47 +02:00
|
|
|
}
|