Added many pipelining option into IBusSimplePlugin

This commit is contained in:
Dolu1990 2018-03-23 19:07:03 +01:00
parent 351ad10925
commit c48c7170e8
4 changed files with 216 additions and 159 deletions

View File

@ -11,6 +11,12 @@ trait JumpService{
def createJumpInterface(stage : Stage, priority : Int = 0) : Flow[UInt]
}
trait IBusFetcher{
def haltIt() : Unit
def nextPc() : (Bool, UInt)
}
trait DecoderService{
def add(key : MaskedLiteral,values : Seq[(Stageable[_ <: BaseType],Any)])
def add(encoding :Seq[(MaskedLiteral,Seq[(Stageable[_ <: BaseType],Any)])])

View File

@ -22,55 +22,7 @@ case class IBusSimpleRsp() extends Bundle with IMasterSlave{
}
}
object StreamVexPimper{
implicit class StreamFlushPimper[T <: Data](pimped : Stream[T]){
def m2sPipe(flush : Bool, collapsBubble : Boolean = true): Stream[T] = {
val ret = cloneOf(pimped)
val rValid = RegInit(False)
val rData = Reg(pimped.dataType)
pimped.ready := (Bool(collapsBubble) && !ret.valid) || ret.ready
when(pimped.ready) {
rValid := pimped.valid
rData := pimped.payload
}
ret.valid := rValid
ret.payload := rData
rValid.clearWhen(flush)
ret
}
def s2mPipe(flush : Bool): Stream[T] = {
val ret = cloneOf(pimped)
val rValid = RegInit(False)
val rBits = Reg(pimped.dataType)
ret.valid := pimped.valid || rValid
pimped.ready := !rValid
ret.payload := Mux(rValid, rBits, pimped.payload)
when(ret.ready) {
rValid := False
}
when(pimped.ready && (!ret.ready)) {
rValid := pimped.valid
rBits := pimped.payload
}
rValid.clearWhen(flush)
ret
}
}
}
import StreamVexPimper._
@ -150,98 +102,7 @@ case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMaste
}
}
trait IBusFetcher{
def haltIt() : Unit
def nextPc() : (Bool, UInt)
}
object RvcDecompressor{
def main(args: Array[String]): Unit = {
SpinalVerilog(new Component{
out(Delay((apply(Delay(in Bits(16 bits),2))),2))
}.setDefinitionName("Decompressor"))
}
def apply(i : Bits): Bits ={
val ret = Bits(32 bits).assignDontCare()
val rch = B"01" ## i(9 downto 7)
val rcl = B"01" ## i(4 downto 2)
val addi5spnImm = B"00" ## i(10 downto 7) ## i(12 downto 11) ## i(5) ## i(6) ## B"00"
val lwImm = B"00000" ## i(5) ## i(12 downto 10) ## i(6) ## B"00"
def swImm = lwImm
val addImm = B((11 downto 5) -> i(12), (4 downto 0) -> i(6 downto 2))
def lImm = addImm
val jalImm = B((9 downto 0) -> i(12)) ## i(8) ## i(10 downto 9) ## i(6) ## i(7) ## i(2) ## i(11) ## i(5 downto 3) ## B"0"
val luiImm = B((14 downto 0) -> i(12)) ## i(6 downto 2) ## B"0000_0000_0000"
val shiftImm = i(6 downto 2)
val addi16spImm = B((2 downto 0) -> i(12)) ## i(4 downto 3) ## i(5) ## i(2) ## i(6) ## B"0000"
val jImm = B((9 downto 0) -> i(12)) ## i(8) ## i(10 downto 9) ## i(6) ## i(7) ## i(2) ## i(11) ## i(5 downto 3) ## B"0"
val bImm = B((4 downto 0) -> i(12)) ## i(6 downto 5) ## i(2) ## i(11 downto 10) ## i(4 downto 3) ## B"0"
def lwspImm = B"0000" ## i(3 downto 2) ## i(12) ## i(6 downto 4) ## B"00"
def swspImm = B"0000" ## i(8 downto 7) ## i(12 downto 9) ## B"00"
val x0 = B"00000"
val x1 = B"00001"
val x2 = B"00010"
switch(i(1 downto 0) ## i(15 downto 13)){
is(0){ret := addi5spnImm ## B"00010" ## B"000" ## rcl ## B"0010011"} //C.ADDI4SPN -> addi rd0, x2, nzuimm[9:2].
is(2){ret := lwImm ## rch ## B"010" ## rcl ## B"0000011"} //C.LW -> lw rd', offset[6:2](rs1')
is(6){ret := swImm(11 downto 5) ## rcl ## rch ## B"010" ## swImm(4 downto 0) ## B"0100011"} //C.SW -> sw rs2',offset[6:2](rs1')
is(8){ret := addImm ## i(11 downto 7) ## B"000" ## i(11 downto 7) ## B"0010011"} //C.ADDI -> addi rd, rd, nzimm[5:0].
is(9){ret := jalImm(20) ## jalImm(10 downto 1) ## jalImm(11) ## jalImm(19 downto 12) ## x1 ## B"1101111"} //C.JAL -> jalr x1, rs1, 0.
is(10){ret := lImm ## B"00000" ## B"000" ## i(11 downto 7) ## B"0010011"} //C.LI -> addi rd, x0, imm[5:0].
is(11){ //C.ADDI16SP C.LUI ->
val addi16sp = addi16spImm ## i(11 downto 7) ## B"000" ## i(11 downto 7) ## B"0010011"
val lui = luiImm(31 downto 12) ## i(11 downto 7) ## B"0110111"
ret := (i(11 downto 7) === 2) ? addi16sp | lui
}
is(12){
val isImmediate = i(11 downto 10) =/= "11"
val isShift = !i(11)
val func3 = i(11 downto 10).mux(
0 -> B"101",
1 -> B"101",
2 -> B"111",
3 -> i(6 downto 5).mux(
0 -> B"000",
1 -> B"100",
2 -> B"110",
3 -> B"111"
)
)
val msbs = Mux(
sel = i(11 downto 10) === "10",
whenTrue = B((6 downto 0) -> i(12)), //andi
whenFalse = B"0" ## (i(11 downto 10) === B"01" || (i(11 downto 10) === B"11" && i(6 downto 5) === B"00")) ## B"00000"
)
val rs2Shift = isShift ? shiftImm | rcl
val opc = (isImmediate ? B"0010011" | B"0110011")
ret := msbs ## rs2Shift ## rch ## func3 ## rch ## opc
}
is(13){ ret := jImm(20) ## jImm(10 downto 1) ## jImm(11) ## jImm(19 downto 12) ## x0 ## B"1101111"}
is(14){ ret := bImm(12) ## bImm(10 downto 5) ## x0 ## rch ## B"000" ## bImm(4 downto 1) ## bImm(11) ## B"1100011" }
is(15){ ret := bImm(12) ## bImm(10 downto 5) ## x0 ## rch ## B"001" ## bImm(4 downto 1) ## bImm(11) ## B"1100011" }
is(16){ ret := B"0000000" ## i(6 downto 2) ## i(11 downto 7) ## B"001" ## i(11 downto 7) ## B"0010011" }
is(18){ ret := lwspImm ## x2 ## B"010" ## i(11 downto 7) ## B"0000011" }
is(20) {
val add = B"000_0000" ## i(6 downto 2) ## (i(12) ? i(11 downto 7) | x0) ## B"000" ## i(11 downto 7) ## B"0110011" //add => add rd, rd, rs2 mv => add rd, x0, rs2
val j = B"0000_0000_0000" ## i(11 downto 7) ## B"000" ## (i(12) ? x1 | x0) ## B"1100111" //jr => jalr x0, rs1, 0. jalr => jalr x1, rs1, 0.
val ebreak = B"000000000001_00000_000_00000_1110011" //EBREAK
val addJ = (i(6 downto 2) === 0) ? j | add
ret := (i(12 downto 2) === B"100_0000_0000") ? ebreak | addJ
}
is(22){ ret := swspImm(11 downto 5) ## i(6 downto 2) ## x2 ## B"010" ## swspImm(4 downto 0) ## B"0100011" }
}
ret
}
}
class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean, pendingMax : Int = 7) extends Plugin[VexRiscv] with JumpService with IBusFetcher{
var iBus : IBusSimpleBus = null
@ -250,6 +111,9 @@ class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean,
def keepPcPlus4 = false
def decodePcGen = true
def compressedGen = true
def cmdToRspStageCount = 3
def rspStageGen = true
def injectorReadyCutGen = true
assert(!(compressedGen && !decodePcGen))
lazy val fetcherHalt = False
lazy val decodeNextPcValid = Bool
@ -370,9 +234,13 @@ class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean,
val isRvc = Bool
}
def recursive[T](that : T,depth : Int, func : (T) => T) : T = depth match {
case 0 => that
case _ => recursive(func(that), depth -1, func)
}
val iBusRsp = new Area {
val input = iBusCmd.output.m2sPipe(flush)// ASYNC .throwWhen(flush)
val input = recursive[Stream[UInt]](iBusCmd.output, cmdToRspStageCount, x => x.m2sPipe(flush))//iBusCmd.output.m2sPipe(flush)// ASYNC .throwWhen(flush)
//Manage flush for iBus transactions in flight
val discardCounter = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0)
@ -381,16 +249,20 @@ class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean,
discardCounter := iBusCmd.pendingCmdNext
}
val rsp = iBus.rsp.throwWhen(discardCounter =/= 0).toStream.s2mPipe(flush)
// val rsp = recursive[Stream[IBusSimpleRsp]](rspUnbuffered, cmdToRspStageCount, x => x.s2mPipe(flush))
val rspBuffer = StreamFifoLowLatency(IBusSimpleRsp(), cmdToRspStageCount)
rspBuffer.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream
rspBuffer.io.flush := flush
val fetchRsp = FetchRsp()
fetchRsp.pc := input.payload
fetchRsp.rsp := rsp.payload
fetchRsp.rsp.error.clearWhen(!rsp.valid) //Avoid interference with instruction injection from the debug plugin
fetchRsp.rsp := rspBuffer.io.pop.payload
fetchRsp.rsp.error.clearWhen(!rspBuffer.io.pop.valid) //Avoid interference with instruction injection from the debug plugin
val output = StreamJoin(Seq(input, rsp), fetchRsp)
def outputGen = StreamJoin(Seq(input, rspBuffer.io.pop), fetchRsp)
val output = if(rspStageGen) outputGen.m2sPipe(flush) else outputGen
}
val decompressor = ifGen(decodePcGen)(new Area{
@ -420,15 +292,16 @@ class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean,
when(input.ready){
when(input.valid) {
bufferValid := !(!isRvc && !input.pc(1) && !bufferValid) && !(isRvc && input.pc(1))
}
bufferError := input.rsp.error
bufferData := input.rsp.inst(31 downto 16)
}
}
bufferValid.clearWhen(flush)
})
def condApply[T](that : T, cond : Boolean)(func : (T) => T) = if(cond)func(that) else that
val injector = new Area {
val inputBeforeHalt = if(decodePcGen) decompressor.output else iBusRsp.output//.s2mPipe(flush)
val inputBeforeHalt = condApply(if(decodePcGen) decompressor.output else iBusRsp.output, injectorReadyCutGen)(_.s2mPipe(flush))
val input = inputBeforeHalt.haltWhen(fetcherHalt)
val stage = input.m2sPipe(flush || decode.arbitration.isRemoved)

View File

@ -0,0 +1,170 @@
package vexriscv.plugin
import spinal.core._
import spinal.lib._
object RvcDecompressor{
def main(args: Array[String]): Unit = {
SpinalVerilog(new Component{
out(Delay((apply(Delay(in Bits(16 bits),2))),2))
}.setDefinitionName("Decompressor"))
}
def apply(i : Bits): Bits ={
val ret = Bits(32 bits).assignDontCare()
val rch = B"01" ## i(9 downto 7)
val rcl = B"01" ## i(4 downto 2)
val addi5spnImm = B"00" ## i(10 downto 7) ## i(12 downto 11) ## i(5) ## i(6) ## B"00"
val lwImm = B"00000" ## i(5) ## i(12 downto 10) ## i(6) ## B"00"
def swImm = lwImm
val addImm = B((11 downto 5) -> i(12), (4 downto 0) -> i(6 downto 2))
def lImm = addImm
val jalImm = B((9 downto 0) -> i(12)) ## i(8) ## i(10 downto 9) ## i(6) ## i(7) ## i(2) ## i(11) ## i(5 downto 3) ## B"0"
val luiImm = B((14 downto 0) -> i(12)) ## i(6 downto 2) ## B"0000_0000_0000"
val shiftImm = i(6 downto 2)
val addi16spImm = B((2 downto 0) -> i(12)) ## i(4 downto 3) ## i(5) ## i(2) ## i(6) ## B"0000"
val jImm = B((9 downto 0) -> i(12)) ## i(8) ## i(10 downto 9) ## i(6) ## i(7) ## i(2) ## i(11) ## i(5 downto 3) ## B"0"
val bImm = B((4 downto 0) -> i(12)) ## i(6 downto 5) ## i(2) ## i(11 downto 10) ## i(4 downto 3) ## B"0"
def lwspImm = B"0000" ## i(3 downto 2) ## i(12) ## i(6 downto 4) ## B"00"
def swspImm = B"0000" ## i(8 downto 7) ## i(12 downto 9) ## B"00"
val x0 = B"00000"
val x1 = B"00001"
val x2 = B"00010"
switch(i(1 downto 0) ## i(15 downto 13)){
is(0){ret := addi5spnImm ## B"00010" ## B"000" ## rcl ## B"0010011"} //C.ADDI4SPN -> addi rd0, x2, nzuimm[9:2].
is(2){ret := lwImm ## rch ## B"010" ## rcl ## B"0000011"} //C.LW -> lw rd', offset[6:2](rs1')
is(6){ret := swImm(11 downto 5) ## rcl ## rch ## B"010" ## swImm(4 downto 0) ## B"0100011"} //C.SW -> sw rs2',offset[6:2](rs1')
is(8){ret := addImm ## i(11 downto 7) ## B"000" ## i(11 downto 7) ## B"0010011"} //C.ADDI -> addi rd, rd, nzimm[5:0].
is(9){ret := jalImm(20) ## jalImm(10 downto 1) ## jalImm(11) ## jalImm(19 downto 12) ## x1 ## B"1101111"} //C.JAL -> jalr x1, rs1, 0.
is(10){ret := lImm ## B"00000" ## B"000" ## i(11 downto 7) ## B"0010011"} //C.LI -> addi rd, x0, imm[5:0].
is(11){ //C.ADDI16SP C.LUI ->
val addi16sp = addi16spImm ## i(11 downto 7) ## B"000" ## i(11 downto 7) ## B"0010011"
val lui = luiImm(31 downto 12) ## i(11 downto 7) ## B"0110111"
ret := (i(11 downto 7) === 2) ? addi16sp | lui
}
is(12){
val isImmediate = i(11 downto 10) =/= "11"
val isShift = !i(11)
val func3 = i(11 downto 10).mux(
0 -> B"101",
1 -> B"101",
2 -> B"111",
3 -> i(6 downto 5).mux(
0 -> B"000",
1 -> B"100",
2 -> B"110",
3 -> B"111"
)
)
val msbs = Mux(
sel = i(11 downto 10) === "10",
whenTrue = B((6 downto 0) -> i(12)), //andi
whenFalse = B"0" ## (i(11 downto 10) === B"01" || (i(11 downto 10) === B"11" && i(6 downto 5) === B"00")) ## B"00000"
)
val rs2Shift = isShift ? shiftImm | rcl
val opc = (isImmediate ? B"0010011" | B"0110011")
ret := msbs ## rs2Shift ## rch ## func3 ## rch ## opc
}
is(13){ ret := jImm(20) ## jImm(10 downto 1) ## jImm(11) ## jImm(19 downto 12) ## x0 ## B"1101111"}
is(14){ ret := bImm(12) ## bImm(10 downto 5) ## x0 ## rch ## B"000" ## bImm(4 downto 1) ## bImm(11) ## B"1100011" }
is(15){ ret := bImm(12) ## bImm(10 downto 5) ## x0 ## rch ## B"001" ## bImm(4 downto 1) ## bImm(11) ## B"1100011" }
is(16){ ret := B"0000000" ## i(6 downto 2) ## i(11 downto 7) ## B"001" ## i(11 downto 7) ## B"0010011" }
is(18){ ret := lwspImm ## x2 ## B"010" ## i(11 downto 7) ## B"0000011" }
is(20) {
val add = B"000_0000" ## i(6 downto 2) ## (i(12) ? i(11 downto 7) | x0) ## B"000" ## i(11 downto 7) ## B"0110011" //add => add rd, rd, rs2 mv => add rd, x0, rs2
val j = B"0000_0000_0000" ## i(11 downto 7) ## B"000" ## (i(12) ? x1 | x0) ## B"1100111" //jr => jalr x0, rs1, 0. jalr => jalr x1, rs1, 0.
val ebreak = B"000000000001_00000_000_00000_1110011" //EBREAK
val addJ = (i(6 downto 2) === 0) ? j | add
ret := (i(12 downto 2) === B"100_0000_0000") ? ebreak | addJ
}
is(22){ ret := swspImm(11 downto 5) ## i(6 downto 2) ## x2 ## B"010" ## swspImm(4 downto 0) ## B"0100011" }
}
ret
}
}
object StreamVexPimper{
implicit class StreamFlushPimper[T <: Data](pimped : Stream[T]){
def m2sPipe(flush : Bool, collapsBubble : Boolean = true): Stream[T] = {
val ret = cloneOf(pimped)
val rValid = RegInit(False)
val rData = Reg(pimped.dataType)
pimped.ready := (Bool(collapsBubble) && !ret.valid) || ret.ready
when(pimped.ready) {
rValid := pimped.valid
rData := pimped.payload
}
ret.valid := rValid
ret.payload := rData
rValid.clearWhen(flush)
ret
}
def s2mPipe(flush : Bool): Stream[T] = {
val ret = cloneOf(pimped)
val rValid = RegInit(False)
val rBits = Reg(pimped.dataType)
ret.valid := pimped.valid || rValid
pimped.ready := !rValid
ret.payload := Mux(rValid, rBits, pimped.payload)
when(ret.ready) {
rValid := False
}
when(pimped.ready && (!ret.ready)) {
rValid := pimped.valid
rBits := pimped.payload
}
rValid.clearWhen(flush)
ret
}
}
}
//case class FlowFifoLowLatency[T <: Data](dataType: T, depth: Int) extends Component {
// require(depth >= 1)
// val io = new Bundle {
// val push = slave Flow (dataType)
// val pop = master Stream (dataType)
// val flush = in Bool()
// }
//
//
// val mem = Vec(Reg(dataType), depth)
// val rPtr, wPtr = Counter(depth + 1)
// when(io.push.valid){
// mem(wPtr) := io.push.payload
// wPtr.increment()
// }
//
// when(io.pop.fire){
// rPtr.increment()
// }
// io.pop.valid := rPtr =/= wPtr
//
//
//}

View File

@ -241,7 +241,7 @@ public:
virtual void iBusAccess(uint32_t addr, uint32_t *data, bool *error) {
if(addr % 4 != 0) {
cout << "Warning, unaligned IBusAccess : " << addr << endl;
//cout << "Warning, unaligned IBusAccess : " << addr << endl;
// fail();
}
*data = ( (mem[addr + 0] << 0)
@ -512,9 +512,8 @@ public:
#ifdef IBUS_SIMPLE
class IBusSimple : public SimElement{
public:
uint32_t inst_next = VL_RANDOM_I(32);
bool error_next = false;
bool pending = false;
uint32_t pendings[256];
uint32_t rPtr = 0, wPtr = 0;
Workspace *ws;
VVexRiscv* top;
@ -529,22 +528,29 @@ public:
}
virtual void preCycle(){
if (top->iBus_cmd_valid && top->iBus_cmd_ready && !pending) {
if (top->iBus_cmd_valid && top->iBus_cmd_ready) {
//assertEq(top->iBus_cmd_payload_pc & 3,0);
pending = true;
ws->iBusAccess(top->iBus_cmd_payload_pc,&inst_next,&error_next);
pendings[wPtr] = (top->iBus_cmd_payload_pc);
wPtr = (wPtr + 1) & 0xFF;
//ws->iBusAccess(top->iBus_cmd_payload_pc,&inst_next,&error_next);
}
}
//TODO doesn't catch when instruction removed ?
virtual void postCycle(){
top->iBus_rsp_valid = 0;
if(pending && (!ws->iStall || VL_RANDOM_I(7) < 100)){
if(rPtr != wPtr && (!ws->iStall || VL_RANDOM_I(7) < 100)){
uint32_t inst_next;
bool error_next;
ws->iBusAccess(pendings[rPtr], &inst_next,&error_next);
rPtr = (rPtr + 1) & 0xFF;
top->iBus_rsp_payload_inst = inst_next;
pending = false;
top->iBus_rsp_valid = 1;
top->iBus_rsp_payload_error = error_next;
} else {
top->iBus_rsp_payload_inst = VL_RANDOM_I(32);
top->iBus_rsp_payload_error = VL_RANDOM_I(1);
}
if(ws->iStall) top->iBus_cmd_ready = VL_RANDOM_I(7) < 100 && !pending;
if(ws->iStall) top->iBus_cmd_ready = VL_RANDOM_I(7) < 100;
}
};
#endif
@ -1329,10 +1335,11 @@ public:
}
virtual void checks(){
if(top->VexRiscv->writeBack_INSTRUCTION == 0x00000073){
if(top->VexRiscv->writeBack_arbitration_isFiring && top->VexRiscv->writeBack_INSTRUCTION == 0x00000013){
uint32_t instruction;
bool error;
iBusAccess(top->VexRiscv->writeBack_PC, &instruction, &error);
Workspace::iBusAccess(top->VexRiscv->writeBack_PC, &instruction, &error);
//printf("%x => %x\n", top->VexRiscv->writeBack_PC, instruction );
if(instruction == 0x00000073){
uint32_t code = top->VexRiscv->RegFilePlugin_regFile[28];
uint32_t code2 = top->VexRiscv->RegFilePlugin_regFile[3];
@ -1353,6 +1360,7 @@ public:
virtual void iBusAccess(uint32_t addr, uint32_t *data, bool *error){
Workspace::iBusAccess(addr,data,error);
if(*data == 0x0ff0000f) *data = 0x00000013;
if(*data == 0x00000073) *data = 0x00000013;
}
};
#endif