Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ Session.vim
.idea/dictionaries
.idea/bsp.xml
.idea/scala_compiler.xml
.idea/misc.xml

# Sensitive or high-churn files:
.idea/dataSources.ids
Expand Down
6 changes: 0 additions & 6 deletions .idea/misc.xml

This file was deleted.

2 changes: 1 addition & 1 deletion chiplab-env
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export CHIPLAB_HOME="<Your own chiplab pwd address>"
export CHIPLAB_HOME="/home/Chris/Program/scala/chiplab/chiplab"
21 changes: 21 additions & 0 deletions src/src/pipeline/ctrl/CtrlStage.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package pipeline.ctrl

import chisel3._
import chisel3.util._
import chisel3.experimental.BundleLiterals.AddBundleLiteralConstructor
import spec.Param
import pipeline.ctrl.bundles.PipelineControlNDPort

class CtrlStage(ctrlControlNum: Integer = Param.ctrlControlNum) extends Module {

val io = IO(new Bundle {
// `ExeStage` -> `CtrlStage`
val exeStallRequest = Input(Bool())
// `CtrlStage` -> `IssueStage`, `RegReadStage`, `ExeStage`
val pipelineControlPort = Output(Vec(ctrlControlNum, new PipelineControlNDPort))
})

io.pipelineControlPort := DontCare
Seq.range(0, 3).foreach(io.pipelineControlPort(_).stall := io.exeStallRequest)

}
19 changes: 19 additions & 0 deletions src/src/pipeline/ctrl/bundles/PipelineControlNDPort.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package pipeline.ctrl.bundles

import chisel3._
import chisel3.util._
import chisel3.experimental.BundleLiterals.AddBundleLiteralConstructor

class PipelineControlNDPort extends Bundle {
val flush = Bool()
val clear = Bool()
val stall = Bool()
}

object PipelineControlNDPort {
val default = (new PipelineControlNDPort).Lit(
_.flush -> false.B,
_.clear -> false.B,
_.stall -> true.B
)
}
14 changes: 11 additions & 3 deletions src/src/pipeline/dispatch/IssueStage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,23 @@ import chisel3.util._
import pipeline.dispatch.bundles.{DecodeOutNdPort, DecodePort, InstInfoBundle, IssuedInfoNdPort, ScoreboardChangeNdPort}
import pipeline.dispatch.decode.{Decoder, Decoder_2RI12}
import spec._
import pipeline.ctrl.bundles.PipelineControlNDPort

class IssueStage(scoreChangeNum: Int = Param.scoreboardChangeNum) extends Module {
val io = IO(new Bundle {
// `InstQueue` -> `IssueStage`
val fetchInstInfoPort = Flipped(Decoupled(new InstInfoBundle))

// Scoreboard
// `IssueStage` <-> `Scoreboard`
val occupyPorts = Output(Vec(scoreChangeNum, new ScoreboardChangeNdPort))
val regScores = Input(Vec(Count.reg, Bool()))

// `IssueStage` -> `RegReadStage` (next clock pulse)
val issuedInfoPort = Output(new IssuedInfoNdPort)

// pipeline control signal
// `CtrlStage` -> `IssueStage`
val pipelineControlPort = Input(new PipelineControlNDPort)
})

// Pass to the next stage in a sequential way
Expand All @@ -31,6 +37,7 @@ class IssueStage(scoreChangeNum: Int = Param.scoreboardChangeNum) extends Module
// Select a decoder
val decoders = Seq(Module(new Decoder_2RI12))
decoders.foreach(_.io.inst := instInfo.inst)

val decoderWires = Wire(Vec(decoders.length, new DecodeOutNdPort))
decoderWires.zip(decoders).foreach {
case (port, decoder) =>
Expand All @@ -40,9 +47,10 @@ class IssueStage(scoreChangeNum: Int = Param.scoreboardChangeNum) extends Module
val selectedDecoder = WireDefault(decoderWires(decoderIndex))

// Check scoreboard
isNonBlocking := selectedDecoder.info.gprReadPorts.map { port =>
val scoreboardNonBlocking = WireDefault(selectedDecoder.info.gprReadPorts.map { port =>
!(port.en && io.regScores(port.addr))
}.reduce(_ || _)
}.reduce(_ || _))
isNonBlocking := scoreboardNonBlocking && ~io.pipelineControlPort.stall

val isInstValid = WireDefault(decoderWires.map(_.isMatched).reduce(_ || _))
val isNeedIssue = WireDefault((isInstAvailable || !isNonBlocking) && isInstValid)
Expand Down
71 changes: 57 additions & 14 deletions src/src/pipeline/dispatch/RegReadStage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,43 @@ package pipeline.dispatch

import chisel3._
import chisel3.util._
import common.bundles.{RfAccessInfoNdPort, RfReadPort}
import common.bundles.{RfAccessInfoNdPort, RfReadPort, RfWriteNdPort}
import bundles.{ExeInstNdPort, IssuedInfoNdPort}
import spec._
import pipeline.ctrl.bundles.PipelineControlNDPort

class RegReadStage(readNum: Int = Param.instRegReadNum) extends Module {
val io = IO(new Bundle {
// `IssueStage` -> `RegReadStage`
val issuedInfoPort = Input(new IssuedInfoNdPort)
val gprReadPorts = Vec(readNum, Flipped(new RfReadPort))
// `RegReadStage` <-> `Regfile`
val gprReadPorts = Vec(readNum, Flipped(new RfReadPort))

// `RegReadStage` -> `ExeStage` (next clock pulse)
val exeInstPort = Output(new ExeInstNdPort)

// 数据前推
// `ExeStage` -> `RegReadStage`
val exeRfWriteFeedbackPort = Input(new RfWriteNdPort)

// `pipeline control signal
// `CtrlStage` -> `RegReadStage`
val pipelineControlPort = Input(new PipelineControlNDPort)
})

// 暂停 目前仅实现对exeInstPort暂停
val stall = WireDefault(io.pipelineControlPort.stall)

// Pass to the next stage in a sequential way
val exeInstReg = RegInit(ExeInstNdPort.default)
io.exeInstPort := exeInstReg

// Pass through write-back info
exeInstReg.gprWritePort := io.issuedInfoPort.info.gprWritePort
exeInstReg.gprWritePort := Mux(
stall,
RfAccessInfoNdPort.default,
io.issuedInfoPort.info.gprWritePort
)

// Read from GPR
io.gprReadPorts.zip(io.issuedInfoPort.info.gprReadPorts).foreach {
Expand All @@ -32,22 +50,47 @@ class RegReadStage(readNum: Int = Param.instRegReadNum) extends Module {
// Determine left and right operands
exeInstReg.leftOperand := zeroWord
exeInstReg.rightOperand := zeroWord
when(io.issuedInfoPort.info.gprReadPorts(0).en) {
exeInstReg.leftOperand := io.gprReadPorts(0).data
}
when(io.issuedInfoPort.info.gprReadPorts(1).en) {
exeInstReg.rightOperand := io.gprReadPorts(1).data
}.elsewhen(io.issuedInfoPort.info.isHasImm) {
exeInstReg.rightOperand := io.issuedInfoPort.info.imm
when(~stall) {
// when(io.issuedInfoPort.info.gprReadPorts(0).en) {
// exeInstReg.leftOperand := io.gprReadPorts(0).data

// }

// when(io.issuedInfoPort.info.gprReadPorts(1).en) {
// exeInstReg.rightOperand := io.gprReadPorts(1).data

// }.elsewhen(io.issuedInfoPort.info.isHasImm) {
// exeInstReg.rightOperand := io.issuedInfoPort.info.imm
// }
when(io.issuedInfoPort.info.isHasImm) {
exeInstReg.rightOperand := io.issuedInfoPort.info.imm
}
Seq(exeInstReg.leftOperand, exeInstReg.rightOperand)
.zip(io.gprReadPorts)
.foreach {
case (oprand, gprReadPort) => {
when(
gprReadPort.en &&
io.exeRfWriteFeedbackPort.en &&
gprReadPort.addr === io.exeRfWriteFeedbackPort.addr
) {
oprand := io.exeRfWriteFeedbackPort.data
}.elsewhen(gprReadPort.en) {
oprand := gprReadPort.data
}
}
}
}

// Pass execution instruction if valid
exeInstReg.exeSel := ExeInst.Sel.none
exeInstReg.exeOp := ExeInst.Op.nop
exeInstReg.gprWritePort := RfAccessInfoNdPort.default
when(io.issuedInfoPort.isValid) {
exeInstReg.exeSel := io.issuedInfoPort.info.exeSel
exeInstReg.exeOp := io.issuedInfoPort.info.exeOp
exeInstReg.gprWritePort := io.issuedInfoPort.info.gprWritePort
when(~stall) {
when(io.issuedInfoPort.isValid) {
exeInstReg.exeSel := io.issuedInfoPort.info.exeSel
exeInstReg.exeOp := io.issuedInfoPort.info.exeOp
exeInstReg.gprWritePort := io.issuedInfoPort.info.gprWritePort
}
}
}
129 changes: 126 additions & 3 deletions src/src/pipeline/execution/Alu.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,141 @@ import pipeline.execution.bundles.{AluInstNdPort, AluResultNdPort}
import spec._
import ExeInst.Op

// Attention: if advance is false, the exeInstPort needs to keep unchange
class Alu extends Module {
val io = IO(new Bundle {
val aluInst = Input(new AluInstNdPort)
val result = Output(new AluResultNdPort)

val stallRequest = Output(Bool())
val divisorZeroException = Output(Bool())
})

io.result := DontCare

// Arithmetic computation
def lop = io.aluInst.leftOperand

def rop = io.aluInst.rightOperand

def arithmetic = io.result.arithmetic

def logic = io.result.logic

def shift = io.result.shift

// Logic computation
switch(io.aluInst.op) {
is(Op.nor) {
logic := ~(lop | rop)
}
is(Op.and) {
logic := lop & rop
}
is(Op.or) {
logic := lop | rop
}
is(Op.xor) {
logic := lop ^ rop
}
}

// shift computation
switch(io.aluInst.op) {
is(Op.add) {
io.result.arithmetic := (io.aluInst.leftOperand.asSInt + io.aluInst.rightOperand.asSInt).asUInt
is(Op.sll) {
shift := lop << rop(4, 0);
}
is(Op.srl) {
shift := lop >> rop(4, 0);
}
is(Op.sra) {
shift := (lop.asSInt << rop(4, 0)).asUInt
}
}

// mul

val useMul = WireDefault(
VecInit(
ExeInst.Op.mul,
ExeInst.Op.mulh,
ExeInst.Op.mulhu
).contains(io.aluInst.op)
)

val mulStart = Wire(Bool())

val mulStage = Module(new Mul)
mulStage.io.mulInst.valid := mulStart
mulStage.io.mulInst.bits.op := io.aluInst.op
mulStage.io.mulInst.bits.leftOperand := lop
mulStage.io.mulInst.bits.rightOperand := rop

mulStage.io.mulResult.ready := DontCare

mulStart := useMul & ~mulStage.io.mulResult.valid

val mulResult = WireDefault(mulStage.io.mulResult.bits)

// Div

val useDiv = WireDefault(
VecInit(
ExeInst.Op.div,
ExeInst.Op.divu,
ExeInst.Op.mod,
ExeInst.Op.modu
).contains(io.aluInst.op)
)

val divStart = Wire(Bool())

val divStage = Module(new Div)
divStage.io.divInst.valid := divStart
divStage.io.divInst.bits.op := io.aluInst.op
divStage.io.divInst.bits.leftOperand := lop
divStage.io.divInst.bits.rightOperand := rop

divStage.io.divResult.ready := DontCare

val divisorValid = WireDefault(rop.orR)
io.divisorZeroException := ~divisorValid & useDiv

divStart := (useDiv & ~divStage.io.isRunning & ~divStage.io.divResult.valid & divisorValid)

val quotient = WireDefault(divStage.io.divResult.bits.quotient)
val remainder = WireDefault(divStage.io.divResult.bits.remainder)

io.stallRequest := (mulStart | divStart | divStage.io.isRunning)

when(~io.stallRequest) {
switch(io.aluInst.op) {
is(Op.add) {
arithmetic := (lop.asSInt + rop.asSInt).asUInt
}
is(Op.sub) {
arithmetic := (lop.asSInt - rop.asSInt).asUInt
}
is(Op.slt) {
arithmetic := (lop.asSInt < rop.asSInt).asUInt
}
is(Op.sltu) {
arithmetic := (lop < rop).asUInt
}
is(Op.mul) {
arithmetic := mulResult(wordLength - 1, 0)
}
is(Op.mulh, Op.mulhu) {
arithmetic := mulResult(doubleWordLength - 1, wordLength)
}
is(Op.div, Op.divu) {
arithmetic := quotient
}
is(Op.mod, Op.modu) {
arithmetic := remainder
}
}
}.otherwise {
arithmetic := zeroWord
}

}
Loading