Skip to content

Commit

Permalink
add A extension
Browse files Browse the repository at this point in the history
  • Loading branch information
LoveLonelyTime committed Jan 26, 2024
1 parent f4774f0 commit cf8be2a
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 14 deletions.
7 changes: 7 additions & 0 deletions src/main/scala/lltriscv/core/Core.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import decode.Decode
import lltriscv.cache.Parallel2Flusher
import lltriscv.core.execute.OutOfOrderedExecuteQueue
import lltriscv.core.fetch.BranchPredictorUpdateIO
import lltriscv.core.execute.UpdateLoadReservationIO

/*
* LLT RISC-V Core Exquisite integration
Expand Down Expand Up @@ -124,6 +125,7 @@ class LLTRISCVCoreExq(config: CoreConfig) extends Module {
coreBackend.io.iCacheFlush.empty := true.B
coreBackend.io.tlbFlush <> tlbFlusher.io.in
coreBackend.io.update <> coreFrontend.io.update
coreBackend.io.updateLoadReservation <> coreExecute.io.updateLoadReservation
coreBackend.io.predictorUpdate <> coreFrontend.io.predictorUpdate
coreBackend.io.store <> coreExecute.io.retire

Expand Down Expand Up @@ -233,6 +235,7 @@ class CoreExecute(config: CoreConfig) extends Module {

val dTLBFlush = Flipped(new FlushCacheIO())
val dCacheFlush = Flipped(new FlushCacheIO())
val updateLoadReservation = Flipped(new UpdateLoadReservationIO())

val retire = Flipped(new StoreQueueRetireIO())

Expand Down Expand Up @@ -313,6 +316,7 @@ class CoreExecute(config: CoreConfig) extends Module {
memory.io.dtlb <> dtlb.io.request
memory.io.sma <> smaWithStoreQueueInterconnect.io.in
memory.io.alloc <> storeQueue.io.alloc
memory.io.updateLoadReservation <> io.updateLoadReservation
memory.io.recover := io.recover
memoryExecuteQueue.io.broadcast <> io.broadcast
memoryExecuteQueue.io.recover := io.recover
Expand Down Expand Up @@ -355,6 +359,8 @@ class CoreBackend(config: CoreConfig) extends Module {
val dCacheFlush = new FlushCacheIO()
val iCacheFlush = new FlushCacheIO()
val tlbFlush = new FlushCacheIO()

val updateLoadReservation = new UpdateLoadReservationIO()
})
private val broadcaster = Module(new RoundRobinBroadcaster(config.executeQueueWidth))
private val instructionRetire = Module(new InstructionRetire(config.robDepth))
Expand All @@ -370,6 +376,7 @@ class CoreBackend(config: CoreConfig) extends Module {
instructionRetire.io.retired <> rob.io.retired
instructionRetire.io.tableRetire <> rob.io.tableRetire
instructionRetire.io.update <> io.update
instructionRetire.io.updateLoadReservation <> io.updateLoadReservation
instructionRetire.io.predictorUpdate <> io.predictorUpdate
instructionRetire.io.store <> io.store
io.recover := instructionRetire.io.recover
Expand Down
8 changes: 4 additions & 4 deletions src/main/scala/lltriscv/core/execute/ALU.scala
Original file line number Diff line number Diff line change
Expand Up @@ -344,16 +344,16 @@ class ALUExecuteStage extends Module {
io.out.bits.result := (inReg.op1 * inReg.op2)(63, 32)
}
is(ALUOperationType.div) {
io.out.bits.result := (inReg.op1.asSInt / inReg.op2.asSInt).asUInt
io.out.bits.result := Mux(inReg.op2 === 0.U, "hffffffff".U, (inReg.op1.asSInt / inReg.op2.asSInt).asUInt)
}
is(ALUOperationType.divu) {
io.out.bits.result := inReg.op1 / inReg.op2
io.out.bits.result := Mux(inReg.op2 === 0.U, "hffffffff".U, inReg.op1 / inReg.op2)
}
is(ALUOperationType.rem) {
io.out.bits.result := (inReg.op1.asSInt % inReg.op2.asSInt).asUInt
io.out.bits.result := Mux(inReg.op2 === 0.U, inReg.op1, (inReg.op1.asSInt % inReg.op2.asSInt).asUInt)
}
is(ALUOperationType.remu) {
io.out.bits.result := inReg.op1 % inReg.op2
io.out.bits.result := Mux(inReg.op2 === 0.U, inReg.op1, inReg.op1 % inReg.op2)
}
is(ALUOperationType.csrrw) {
io.out.bits.result := inReg.op1
Expand Down
17 changes: 17 additions & 0 deletions src/main/scala/lltriscv/core/execute/ExecuteEntry.scala
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ class ExecuteResultEntry extends Bundle {
// Predictor field
val branch = Bool()

// LRSC field
val lr = Bool()
val lrAddress = DataType.address
val sc = Bool()

val rd = DataType.receipt // Destination receipt
val pc = DataType.address // Corresponding PC
val next = DataType.address // Next PC
Expand Down Expand Up @@ -117,6 +122,11 @@ class ExecuteResultEntry extends Bundle {
csrData := wdata
}

def resultLR(addr: UInt) = {
lr := true.B
lrAddress := addr
}

def noMemory() = {
write := false.B
writeID := 0.U
Expand All @@ -133,12 +143,19 @@ class ExecuteResultEntry extends Bundle {
flushTLB := false.B
}

def noLRSC() = {
lr := false.B
sc := false.B
lrAddress := 0.U
}

def noResult() = {
result := 0.U
noException()
noCSR()
noMemory()
noFlush()
noLRSC()
xret := false.B
rd := 0.U
pc := 0.U
Expand Down
48 changes: 44 additions & 4 deletions src/main/scala/lltriscv/core/execute/Memory.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class Memory extends Module {
val sma = new SMAReaderIO()
// Store queue interface
val alloc = new StoreQueueAllocIO()
val updateLoadReservation = Flipped(new UpdateLoadReservationIO())
// Recovery logic
val recover = Input(Bool())
})
Expand All @@ -53,6 +54,7 @@ class Memory extends Module {
memoryTLBStage.io.dtlb <> io.dtlb
memoryReadWriteStage.io.sma <> io.sma
memoryReadWriteStage.io.alloc <> io.alloc
memoryReadWriteStage.io.updateLoadReservation <> io.updateLoadReservation

memoryDecodeStage.io.recover := io.recover
memoryExecuteStage.io.recover := io.recover
Expand Down Expand Up @@ -109,8 +111,8 @@ class MemoryDecodeStage extends Module {
}
is(InstructionType.R) {
switch(inReg.func7(6, 2)) {
is("b00010".U) { io.out.bits.op := MemoryOperationType.lw }
is("b00011".U) { io.out.bits.op := MemoryOperationType.sw }
is("b00010".U) { io.out.bits.op := MemoryOperationType.lr }
is("b00011".U) { io.out.bits.op := MemoryOperationType.sc }
is("b00001".U) { io.out.bits.op := MemoryOperationType.amoswap }
is("b00000".U) { io.out.bits.op := MemoryOperationType.amoadd }
is("b00100".U) { io.out.bits.op := MemoryOperationType.amoxor }
Expand Down Expand Up @@ -289,10 +291,14 @@ class MemoryReadWriteStage extends Module {
val sma = new SMAReaderIO()
// Store queue interface
val alloc = new StoreQueueAllocIO()
val updateLoadReservation = Flipped(new UpdateLoadReservationIO())
// Recovery interface
val recover = Input(Bool())
})

private val loadReservation = RegInit(new LoadReservationEntry().zero)
private val recoveryLoadReservation = RegInit(new LoadReservationEntry().zero)

private val statusReg = RegInit(Status.idle)
private object Status extends ChiselEnum {
val idle, read, write = Value
Expand All @@ -303,10 +309,18 @@ class MemoryReadWriteStage extends Module {
private val readResult = RegInit(DataType.operation.zeroAsUInt)
private val readError = RegInit(false.B)
private val allocID = RegInit(DataType.receipt.zeroAsUInt)
private val scSuccess = inReg.vaddress === loadReservation.address && loadReservation.valid

io.in.ready := statusReg === Status.idle && io.out.ready // Idle

when(io.out.fire) { // Stall
inReg.valid := false.B

// SC
when(inReg.op === MemoryOperationType.sc) {
// Clear load reservation
loadReservation.valid := false.B
}
}

when(io.in.fire) { // Sample
Expand All @@ -315,7 +329,9 @@ class MemoryReadWriteStage extends Module {
when(io.in.bits.op in MemoryOperationType.readValues) {
statusReg := Status.read
}.elsewhen(io.in.bits.op in MemoryOperationType.writeValues) {
statusReg := Status.write
when(io.in.bits.op =/= MemoryOperationType.sc || scSuccess) { // SC
statusReg := Status.write
}
}
}
}
Expand All @@ -342,6 +358,11 @@ class MemoryReadWriteStage extends Module {
readResult := io.sma.data
readError := io.sma.error

when(inReg.op === MemoryOperationType.lr && !readError) { // lr
loadReservation.address := inReg.vaddress
loadReservation.valid := true.B
}

when((inReg.op in MemoryOperationType.amoValues) && !readError) { // AMO
statusReg := Status.write
}.otherwise {
Expand Down Expand Up @@ -401,6 +422,10 @@ class MemoryReadWriteStage extends Module {
// Result
io.out.bits.noResult()

when(inReg.op === MemoryOperationType.lr) {
io.out.bits.resultLR(inReg.vaddress)
}

when(inReg.op === MemoryOperationType.lb) {
io.out.bits.result := CoreUtils.signExtended(readResult, 7)
}.elsewhen(inReg.op === MemoryOperationType.lbu) {
Expand All @@ -409,8 +434,11 @@ class MemoryReadWriteStage extends Module {
io.out.bits.result := CoreUtils.signExtended(readResult, 15)
}.elsewhen(inReg.op === MemoryOperationType.lhu) {
io.out.bits.result := readResult(15, 0)
}.elsewhen(inReg.op === MemoryOperationType.lw || (inReg.op in MemoryOperationType.amoValues)) {
}.elsewhen(inReg.op in (MemoryOperationType.lw :: MemoryOperationType.lr :: MemoryOperationType.amoValues)) {
io.out.bits.result := readResult
}.elsewhen(inReg.op === MemoryOperationType.sc) {
io.out.bits.result := Mux(scSuccess, 0.U, 1.U)
io.out.bits.sc := true.B
}

when(inReg.op in MemoryOperationType.writeValues) {
Expand Down Expand Up @@ -458,10 +486,22 @@ class MemoryReadWriteStage extends Module {

io.out.valid := statusReg === Status.idle

// Update load reservation
when(io.updateLoadReservation.valid) {
when(io.updateLoadReservation.load) { // LR
recoveryLoadReservation.address := io.updateLoadReservation.address
recoveryLoadReservation.valid := true.B
}.otherwise { // SC
recoveryLoadReservation.valid := false.B
}
}

// Recovery logic
when(io.recover) {
inReg.valid := false.B
// Undo write FSM to prevent writing to store queue
when(statusReg === Status.write) { statusReg := Status.idle }

loadReservation := recoveryLoadReservation
}
}
23 changes: 19 additions & 4 deletions src/main/scala/lltriscv/core/execute/MemoryEntry.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,22 @@ object MemoryOperationType extends ChiselEnum {
* - amoand: read and and
* - amomax(u): read and max(unsigned)
* - amomin(u): read and min(unsigned)
*
* LR/SC operations:
* - lr: load reserved
* - sc: store conditional
*/
val none, undefined, lb, lh, lw, lbu, lhu, sb, sh, sw, amoswap, amoadd, amoxor, amoand, amoor, amomin, amomax, amominu, amomaxu = Value
val none, undefined, lb, lh, lw, lbu, lhu, sb, sh, sw, amoswap, amoadd, amoxor, amoand, amoor, amomin, amomax, amominu, amomaxu, lr, sc = Value

// By type
val amoValues = List(amoswap, amoadd, amoxor, amoand, amoor, amomin, amomax, amominu, amomaxu)
val readValues = List(lb, lh, lw, lbu, lhu) ::: amoValues
val writeValues = List(sb, sh, sw) ::: amoValues
val readValues = List(lb, lh, lw, lbu, lhu, lr) ::: amoValues
val writeValues = List(sb, sh, sw, sc) ::: amoValues

// By width
val byteValues = List(lb, lbu, sb)
val halfValues = List(lh, lhu, sh)
val wordValues = List(lw, sw) ::: amoValues
val wordValues = List(lw, sw, lr, sc) ::: amoValues
}

/** Memory access length
Expand All @@ -64,6 +68,17 @@ object MemoryErrorCode extends ChiselEnum {
val none, misaligned, pageFault, memoryFault = Value
}

class LoadReservationEntry extends Bundle {
val address = DataType.address
val valid = Bool()
}

class UpdateLoadReservationIO extends Bundle {
val load = Output(Bool())
val address = Output(DataType.address)
val valid = Output(Bool())
}

/** Memory execute stage entry
*
* The input entry of MemoryExecuteStage
Expand Down
20 changes: 20 additions & 0 deletions src/main/scala/lltriscv/core/retire/InstructionRetire.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import lltriscv.core.record.ExceptionRequestIO
import lltriscv.core.record.StoreQueueRetireIO
import lltriscv.cache.FlushCacheIO
import lltriscv.core.fetch.BranchPredictorUpdateIO
import lltriscv.core.execute.UpdateLoadReservationIO

/*
* Instruction retire
Expand Down Expand Up @@ -48,6 +49,8 @@ class InstructionRetire(depth: Int) extends Module {
// Exception interface
val exception = new ExceptionRequestIO()

val updateLoadReservation = new UpdateLoadReservationIO()

// Flush interface
val dCacheFlush = new FlushCacheIO()
val iCacheFlush = new FlushCacheIO()
Expand Down Expand Up @@ -107,6 +110,10 @@ class InstructionRetire(depth: Int) extends Module {
io.iCacheFlush.req := false.B
io.tlbFlush.req := false.B

io.updateLoadReservation.load := false.B
io.updateLoadReservation.address := 0.U
io.updateLoadReservation.valid := false.B

private def gotoExceptionHandler(id: Int) = {
io.recover := true.B

Expand Down Expand Up @@ -196,6 +203,17 @@ class InstructionRetire(depth: Int) extends Module {
io.csr.data := retireEntries(id).executeResult.csrData
}

private def updateLoadReservation(id: Int) = {
when(retireEntries(id).executeResult.sc) {
io.updateLoadReservation.load := false.B
io.updateLoadReservation.valid := true.B
}.elsewhen(retireEntries(id).executeResult.lr) {
io.updateLoadReservation.load := true.B
io.updateLoadReservation.address := retireEntries(id).executeResult.lrAddress
io.updateLoadReservation.valid := true.B
}
}

io.retired.ready := false.B
when(statusReg === Status.retire) {
when(io.retired.valid && retireValid(0) && retireValid(1)) {
Expand All @@ -216,6 +234,7 @@ class InstructionRetire(depth: Int) extends Module {
}.otherwise { // Normal 0
when(retireEntries(0).valid) {
updateRegister(0)
updateLoadReservation(0)
retireStoreQueue(0)
}

Expand All @@ -235,6 +254,7 @@ class InstructionRetire(depth: Int) extends Module {
flushID := 1.U
}.otherwise { // Normal 1
when(retireEntries(1).valid) {
updateLoadReservation(1)
updateRegister(1)
retireStoreQueue(1)
}
Expand Down
6 changes: 4 additions & 2 deletions src/test/scala/lltriscv/test/riscvtests/RV32PTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ class RV32PTest extends AnyFlatSpec with ChiselScalatestTester {
// Collect tests
private val uiTests = new File("riscv-tests/isa").listFiles().filter(_.getName().matches(raw"rv32ui-p-.*\.bin"))
private val ucTests = new File("riscv-tests/isa").listFiles().filter(_.getName().matches(raw"rv32uc-p-.*\.bin"))
private val uaTests = new File("riscv-tests/isa").listFiles().filter(_.getName().matches(raw"rv32ua-p-amoadd_w\.bin"))
private val needToTest = uiTests
private val uaTests = new File("riscv-tests/isa").listFiles().filter(_.getName().matches(raw"rv32ua-p-.*\.bin"))
private val umTests = new File("riscv-tests/isa").listFiles().filter(_.getName().matches(raw"rv32um-p-.*\.bin"))

private val needToTest = uiTests ++ ucTests ++ uaTests ++ umTests

private def expectPass(memory: MemoryMock) = {
assert(memory.loadInt(hostAddress) == passTestNum)
Expand Down

0 comments on commit cf8be2a

Please sign in to comment.