1
0
rocket-chip/src/main/scala/rocket/ALU.scala
Henry Cook e8c8d2af71 Heterogeneous Tiles (#550)
Fundamental new features:

* Added tile package: This package is intended to hold components re-usable across different types of tile. Will be the future location of TL2-RoCC accelerators and new diplomatic versions of intra-tile interfaces.
* Adopted [ModuleName]Params convention: Code base was very inconsistent about what to name case classes that provide parameters to modules. Settled on calling them [ModuleName]Params to distinguish them from config.Parameters and config.Config. So far applied mostly only to case classes defined within rocket and tile.
* Defined RocketTileParams: A nested case class containing case classes for all the components of a tile (L1 caches and core). Allows all such parameters to vary per-tile.
* Defined RocketCoreParams: All the parameters that can be varied per-core.
* Defined L1CacheParams: A trait defining the parameters common to L1 caches, made concrete in different derived case classes.
* Defined RocketTilesKey: A sequence of RocketTileParams, one for every tile to be created.
* Provided HeterogeneousDualCoreConfig: An example of making a heterogeneous chip with two cores, one big and one little.
* Changes to legacy code: ReplacementPolicy moved to package util. L1Metadata moved to package tile. Legacy L2 cache agent removed because it can no longer share the metadata array implementation with the L1. Legacy GroundTests on life support.

Additional changes that got rolled in along the way:

* rocket: 	Fix critical path through BTB for I$ index bits > pgIdxBits
* coreplex: tiles connected via :=*
* groundtest: updated to use TileParams
* tilelink: cache cork requirements are relaxed to allow more cacheless masters
2017-02-09 13:59:09 -08:00

99 lines
2.9 KiB
Scala

// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.
package rocket
import Chisel._
import config._
import tile._
import Instructions._
object ALU
{
val SZ_ALU_FN = 4
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)
def FN_DIV = FN_XOR
def FN_DIVU = FN_SR
def FN_REM = FN_OR
def FN_REMU = FN_AND
def FN_MUL = FN_ADD
def FN_MULH = FN_SL
def FN_MULHSU = FN_SLT
def FN_MULHU = FN_SLTU
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)
}
import ALU._
class ALU(implicit p: Parameters) extends CoreModule()(p) {
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)
val cmp_out = Bool(OUTPUT)
}
// ADD, SUB
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)
// SLT, SLTU
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),
Mux(cmpUnsigned(io.fn), io.in2(xLen-1), io.in1(xLen-1))))
// SLL, SRL, SRA
val (shamt, shin_r) =
if (xLen == 32) (io.in2(4,0), io.in1)
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)
val shamt = Cat(io.in2(5) & (io.dw === DW_64), io.in2(4,0))
(shamt, Cat(shin_hi, io.in1(31,0)))
}
val shin = Mux(io.fn === FN_SR || io.fn === FN_SRA, shin_r, Reverse(shin_r))
val shout_r = (Cat(isSub(io.fn) & shin(xLen-1), shin).asSInt >> shamt)(xLen-1,0)
val shout_l = Reverse(shout_r)
val shout = Mux(io.fn === FN_SR || io.fn === FN_SRA, shout_r, UInt(0)) |
Mux(io.fn === FN_SL, shout_l, UInt(0))
// 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)
io.out := out
if (xLen > 32) {
require(xLen == 64)
when (io.dw === DW_32) { io.out := Cat(Fill(32, out(31)), out(31,0)) }
}
}