blob: 06818c1738e7f02a7f0c852da1a3d2b08441af8e [file] [log] [blame]
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package kelvin
import chisel3._
import chisel3.util._
import common._
object Alu {
def apply(p: Parameters): Alu = {
return Module(new Alu(p))
}
}
case class AluOp() {
val ADD = 0
val SUB = 1
val SLT = 2
val SLTU = 3
val XOR = 4
val OR = 5
val AND = 6
val SLL = 7
val SRL = 8
val SRA = 9
val LUI = 10
val CLZ = 11
val CTZ = 12
val PCNT = 13
val MIN = 14
val MINU = 15
val MAX = 16
val MAXU = 17
val Entries = 18
}
class AluIO(p: Parameters) extends Bundle {
val valid = Input(Bool())
val addr = Input(UInt(5.W))
val op = Input(UInt(new AluOp().Entries.W))
}
class Alu(p: Parameters) extends Module {
val io = IO(new Bundle {
// Decode cycle.
val req = new AluIO(p)
// Execute cycle.
val rs1 = Flipped(new RegfileReadDataIO)
val rs2 = Flipped(new RegfileReadDataIO)
val rd = Flipped(new RegfileWriteDataIO)
})
val alu = new AluOp()
val valid = RegInit(false.B)
val addr = Reg(UInt(5.W))
val op = RegInit(0.U(alu.Entries.W))
// Pulse the cycle after the decoded request.
valid := io.req.valid
// Avoid output toggles by not updating state between uses.
// The Regfile has the same behavior, leaving read ports unchanged.
when (io.req.valid) {
addr := io.req.addr
op := io.req.op
}
val rs1 = io.rs1.data
val rs2 = io.rs2.data
val shamt = rs2(4,0)
io.rd.valid := valid
io.rd.addr := addr
io.rd.data := MuxOR(op(alu.ADD), rs1 + rs2) |
MuxOR(op(alu.SUB), rs1 - rs2) |
MuxOR(op(alu.SLT), rs1.asSInt < rs2.asSInt) |
MuxOR(op(alu.SLTU), rs1 < rs2) |
MuxOR(op(alu.XOR), rs1 ^ rs2) |
MuxOR(op(alu.OR), rs1 | rs2) |
MuxOR(op(alu.AND), rs1 & rs2) |
MuxOR(op(alu.SLL), rs1 << shamt) |
MuxOR(op(alu.SRL), rs1 >> shamt) |
MuxOR(op(alu.SRA), (rs1.asSInt >> shamt).asUInt) |
MuxOR(op(alu.LUI), rs2) |
MuxOR(op(alu.CLZ), Clz(rs1)) |
MuxOR(op(alu.CTZ), Ctz(rs1)) |
MuxOR(op(alu.PCNT), PopCount(rs1)) |
MuxOR(op(alu.MIN), Mux(rs1.asSInt < rs2.asSInt, rs1, rs2)) |
MuxOR(op(alu.MAX), Mux(rs1.asSInt > rs2.asSInt, rs1, rs2)) |
MuxOR(op(alu.MINU), Mux(rs1 < rs2, rs1, rs2)) |
MuxOR(op(alu.MAXU), Mux(rs1 > rs2, rs1, rs2))
// Assertions.
assert(!(valid && !io.rs1.valid && !op(alu.LUI)))
assert(!(valid && !io.rs2.valid))
}