Add special handlers for shift instructions.

This commit is contained in:
peteraa 2019-09-04 11:52:49 +02:00
parent 9358c3a6be
commit 8e2d686b5c
8 changed files with 84 additions and 62 deletions

4
.jvmopts Normal file
View file

@ -0,0 +1,4 @@
-Xms512M
-Xmx4096M
-Xss32M
-XX:MaxMetaspaceSize=1024M

View file

@ -61,6 +61,6 @@ class InstructionFetch extends MultiIOModule {
when(testHarness.IMEMsetup.setup) { when(testHarness.IMEMsetup.setup) {
PC := 0.U PC := 0.U
// TODO: You should probably set the instruction to Instruction.NOP here. // TODO: You should probably set the instruction to Instruction.NOP here.
throw new Exception("Just making sure you're seeing the line above.\nYou can delete this exception now, it's found at line 64 at IF.scala") // throw new Exception("Just making sure you're seeing the line above.\nYou can delete this exception now, it's found at line 64 at IF.scala")
} }
} }

View file

@ -93,14 +93,17 @@ object Ops {
def or( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), OR) def or( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), OR)
def xor( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), XOR) def xor( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), XOR)
def and( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), AND) def and( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), AND)
def sll( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), SLL)
def srl( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), SRL)
def sra( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), SRA)
def slt( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), SLT) def slt( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), SLT)
def sltu(rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), SLTU) def sltu(rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), SLTU)
def nop = add(0, 0, 0) def nop = add(0, 0, 0)
} }
case class ArithImmShift(imm11: Imm, rd: Reg, rs1: Reg, shamt: Imm, op: ArithOp) extends Op with IType
object ArithImmShift {
def sll( rd: Int, rs1: Int, imm: Int) = ArithImmShift(Imm(0), Reg(rd), Reg(rs1), Imm(imm), SLL)
def srl( rd: Int, rs1: Int, imm: Int) = ArithImmShift(Imm(0), Reg(rd), Reg(rs1), Imm(imm), SRL)
def sra( rd: Int, rs1: Int, imm: Int) = ArithImmShift(Imm(32), Reg(rd), Reg(rs1), Imm(imm), SRA)
}
case class LUI(rd: Reg, imm: Imm) extends Op with UType case class LUI(rd: Reg, imm: Imm) extends Op with UType
case class AUIPC(rd: Reg, imm: Imm) extends Op with UType case class AUIPC(rd: Reg, imm: Imm) extends Op with UType

View file

@ -84,9 +84,9 @@ object Parser {
stringWs("xori") ~> arithImm.mapN{ArithImm.xor}, stringWs("xori") ~> arithImm.mapN{ArithImm.xor},
stringWs("andi") ~> arithImm.mapN{ArithImm.and}, stringWs("andi") ~> arithImm.mapN{ArithImm.and},
stringWs("slli") ~> arithImm.mapN{ArithImm.sll}, stringWs("slli") ~> arithImm.mapN{ArithImmShift.sll},
stringWs("srli") ~> arithImm.mapN{ArithImm.srl}, stringWs("srli") ~> arithImm.mapN{ArithImmShift.srl},
stringWs("srai") ~> arithImm.mapN{ArithImm.sra}, stringWs("srai") ~> arithImm.mapN{ArithImmShift.sra},
stringWs("slti") ~> arithImm.mapN{ArithImm.slt}, stringWs("slti") ~> arithImm.mapN{ArithImm.slt},
stringWs("sltiu") ~> arithImm.mapN{ArithImm.sltu}, stringWs("sltiu") ~> arithImm.mapN{ArithImm.sltu},
@ -160,16 +160,16 @@ object Parser {
SW(placeHolder, 0, 2048), SW(placeHolder, 0, 2048),
LW(placeHolder, rs1.value, (offset & 0xFFFFFF1C)), LW(placeHolder, rs1.value, (offset & 0xFFFFFF1C)),
LW(rd.value, rs1.value, (offset & 0xFFFFFF1C) + 4), LW(rd.value, rs1.value, (offset & 0xFFFFFF1C) + 4),
ArithImm.sra(placeHolder, placeHolder, 24), ArithImmShift.sra(placeHolder, placeHolder, 24),
ArithImm.sll(rd.value, rd.value, 24), ArithImmShift.sll(rd.value, rd.value, 24),
ArithImm.sra(rd.value, rd.value, 16), ArithImmShift.sra(rd.value, rd.value, 16),
Arith.add(rd, rd, placeHolder), Arith.add(rd, rd, placeHolder),
LW(placeHolder, 0, 2048)).reverse LW(placeHolder, 0, 2048)).reverse
} }
case (rd, offset, rs1) if (offset % 4 == 2) => { case (rd, offset, rs1) if (offset % 4 == 2) => {
List( List(
LW(rd, rs1, (offset & 0xFFFFFF1C)), LW(rd, rs1, (offset & 0xFFFFFF1C)),
ArithImm.sra(rd, rd, 16) ArithImmShift.sra(rd, rd, 16)
).reverse ).reverse
} }
@ -177,8 +177,8 @@ object Parser {
val leftShift = if((offset % 4) == 0) 16 else 8 val leftShift = if((offset % 4) == 0) 16 else 8
List( List(
LW(rd, rs1, (offset & 0xFFFFFF1C)), LW(rd, rs1, (offset & 0xFFFFFF1C)),
ArithImm.sll(rd, rd, leftShift), ArithImmShift.sll(rd, rd, leftShift),
ArithImm.sra(rd, rd, 16), ArithImmShift.sra(rd, rd, 16),
).reverse ).reverse
} }
}.map(_.widen[Op]), }.map(_.widen[Op]),

View file

@ -23,16 +23,17 @@ case class VM(
def stepInstruction: Either[Finished, ExecutionTrace[VM]] = { def stepInstruction: Either[Finished, ExecutionTrace[VM]] = {
if (pc.value == 0xEB1CEB1C) Left(Success) if (pc.value == 0xEB1CEB1C) Left(Success)
else getOp flatMap { else getOp flatMap {
case op: Branch => executeBranch(op) case op: Branch => executeBranch(op)
case op: Arith => executeArith(op) case op: Arith => executeArith(op)
case op: ArithImm => executeArithImm(op) case op: ArithImm => executeArithImm(op)
case op: AUIPC => executeAUIPC(op) case op: ArithImmShift => executeArithImmShift(op)
case op: LUI => executeLUI(op) case op: AUIPC => executeAUIPC(op)
case op: JALR => executeJALR(op) case op: LUI => executeLUI(op)
case op: JAL => executeJAL(op) case op: JALR => executeJALR(op)
case op: LW => executeLW(op) case op: JAL => executeJAL(op)
case op: SW => executeSW(op) case op: LW => executeLW(op)
case DONE => Left(Success) case op: SW => executeSW(op)
case DONE => Left(Success)
} }
} }
@ -75,6 +76,13 @@ case class VM(
} }
private def executeArithImmShift(op: ArithImmShift) = {
val (regUpdate, nextRegs) = regs.arithImm(op.rd, op.rs1, op.shamt, op.op.run)
val nextVM = this.copy(regs = nextRegs)
Right(step(nextVM, regUpdate.toList:_*))
}
private def executeLUI(op: LUI) = { private def executeLUI(op: LUI) = {
val (regUpdate, nextRegs) = regs + (op.rd -> (op.imm.value << 12)) val (regUpdate, nextRegs) = regs + (op.rd -> (op.imm.value << 12))
val nextVM = this.copy(regs = nextRegs) val nextVM = this.copy(regs = nextRegs)

View file

@ -125,12 +125,17 @@ object assembler {
} }
/** /**
* Currently not used, thus we allow too larg shifts. * Used by SRI, SRAI, SLLI
*/ */
def setShiftTypeImmediate(instruction: Int, immediate: Int): Int = { def setShiftTypeImmediate(funct7: Int, shamt: Int, addr: Addr): Int => InstructionFragment = {
val points = List((24, 5)) val shamtPoints = List((24, 5))
val withField = applyImmediate(5, immediate, points)(instruction) val funct7Points = List((31, 6))
withField
base => {
val withF7 = applyImmediateU(funct7, funct7Points, addr)(base)
val withShamt = withF7.flatMap(base2 => applyImmediateU(shamt, shamtPoints, addr)(base2))
withShamt
}
} }
def setOpCode(opcode: Int): Int => Int = setField(0, 7, opcode) def setOpCode(opcode: Int): Int => Int = setField(0, 7, opcode)
@ -142,16 +147,17 @@ object assembler {
def setOpCode(op: Op): Int => Int = op match { def setOpCode(op: Op): Int => Int = op match {
case x: Branch => setOpCode("1100011".binary) case x: Branch => setOpCode("1100011".binary)
case x: Arith => setOpCode("0110011".binary) case x: Arith => setOpCode("0110011".binary)
case x: ArithImm => setOpCode("0010011".binary) case x: ArithImm => setOpCode("0010011".binary)
case x: LW => setOpCode("0000011".binary) case x: ArithImmShift => setOpCode("0010011".binary)
case x: SW => setOpCode("0100011".binary) case x: LW => setOpCode("0000011".binary)
case x: JALR => setOpCode("1100111".binary) case x: SW => setOpCode("0100011".binary)
case x: JAL => setOpCode("1101111".binary) case x: JALR => setOpCode("1100111".binary)
case x: AUIPC => setOpCode("0110111".binary) case x: JAL => setOpCode("1101111".binary)
case x: LUI => setOpCode("0010111".binary) case x: AUIPC => setOpCode("0110111".binary)
case DONE => setOpCode("0010011".binary) // done is turned into a NOP in the assembler. case x: LUI => setOpCode("0010111".binary)
case DONE => setOpCode("0010011".binary) // done is turned into a NOP in the assembler.
} }
def setComparisonFunct(cmp: Comparison): Int => Int = cmp match { def setComparisonFunct(cmp: Comparison): Int => Int = cmp match {
@ -195,7 +201,6 @@ object assembler {
setRs1(op.rs1.value) setRs1(op.rs1.value)
def assembleSType(op: SType): Int => Int = { def assembleSType(op: SType): Int => Int = {
// say("stype")
instruction => instruction =>
(setRs1(op.rs1.value) andThen (setRs1(op.rs1.value) andThen
setRs2(op.rs2.value))(instruction) setRs2(op.rs2.value))(instruction)
@ -214,16 +219,17 @@ object assembler {
def assembleImmediate(op: Op, addr: Addr, labelMap: Map[Label, Addr]): Int => Either[(String, Addr), Int] = op match { def assembleImmediate(op: Op, addr: Addr, labelMap: Map[Label, Addr]): Int => Either[(String, Addr), Int] = op match {
case DONE => instruction => Right(instruction) case DONE => instruction => Right(instruction)
case op: Arith => instruction => Right(instruction) case op: Arith => instruction => Right(instruction)
case op: ArithImm => setItypeImmediate(op.imm.value, addr) case op: ArithImm => setItypeImmediate(op.imm.value, addr)
case op: Branch => setBranchDestination(labelMap, op, addr) case op: ArithImmShift => setShiftTypeImmediate(op.imm11.value, op.shamt.value, addr)
case op: JALR => instruction => labelMap.lift(op.dst).toRight(s"label ${op.dst} not found", addr).flatMap(addr => setItypeImmediate(addr.value, addr)(instruction)) case op: Branch => setBranchDestination(labelMap, op, addr)
case op: AUIPC => setUtypeImmediate(op.imm.value, addr) case op: JALR => instruction => labelMap.lift(op.dst).toRight(s"label ${op.dst} not found", addr).flatMap(addr => setItypeImmediate(addr.value, addr)(instruction))
case op: LUI => setUtypeImmediate(op.imm.value, addr) case op: AUIPC => setUtypeImmediate(op.imm.value, addr)
case op: LW => setItypeImmediate(op.offset.value, addr) case op: LUI => setUtypeImmediate(op.imm.value, addr)
case op: SW => setStypeImmediate(op.offset.value, addr) case op: LW => setItypeImmediate(op.offset.value, addr)
case op: JAL => instruction => { case op: SW => setStypeImmediate(op.offset.value, addr)
case op: JAL => instruction => {
val addressDistance = labelMap val addressDistance = labelMap
.lift(op.dst).toRight(s"label ${op.dst} not found", addr) .lift(op.dst).toRight(s"label ${op.dst} not found", addr)
.map(absoluteAddr => absoluteAddr - addr) .map(absoluteAddr => absoluteAddr - addr)

View file

@ -81,16 +81,17 @@ object PrintUtils {
val UNKNOWN = "UNKNOWN" val UNKNOWN = "UNKNOWN"
def printInstruction(op: Ops.Op, labelMap: Map[Label, Addr]): fansi.Str = op match { def printInstruction(op: Ops.Op, labelMap: Map[Label, Addr]): fansi.Str = op match {
case op: Branch => fansi.Color.Red(s"B${op.comp}\t${op.rs1.show}, ${op.rs2.show}, ${op.dst.show}\t[${labelMap.lift(op.dst).getOrElse(UNKNOWN)}]") case op: Branch => fansi.Color.Red(s"B${op.comp}\t${op.rs1.show}, ${op.rs2.show}, ${op.dst.show}\t[${labelMap.lift(op.dst).getOrElse(UNKNOWN)}]")
case op: Arith => s"${op.op}\t${op.rd.show}, ${op.rs1.show}, ${op.rs2.show}" case op: Arith => s"${op.op}\t${op.rd.show}, ${op.rs1.show}, ${op.rs2.show}"
case op: ArithImm => s"${op.op}I\t${op.rd.show}, ${op.rs1.show}, ${op.imm.show}" case op: ArithImm => s"${op.op}I\t${op.rd.show}, ${op.rs1.show}, ${op.imm.show}"
case op: JALR => fansi.Color.Green(s"JALR\t${op.rd.show}, ${op.rs1.show}, ${op.dst.show}\t[${labelMap.lift(op.dst).getOrElse(UNKNOWN)}]") case op: ArithImmShift => s"${op.op}I\t${op.rd.show}, ${op.rs1.show}, ${op.shamt.show}"
case op: JAL => fansi.Color.Magenta(s"JAL\t${op.rd.show}, ${op.dst.show} [${labelMap.lift(op.dst).getOrElse(UNKNOWN)}]") case op: JALR => fansi.Color.Green(s"JALR\t${op.rd.show}, ${op.rs1.show}, ${op.dst.show}\t[${labelMap.lift(op.dst).getOrElse(UNKNOWN)}]")
case op: LW => s"LW\t${op.rd.show}, ${op.offset.show}(${op.rs1.show})" case op: JAL => fansi.Color.Magenta(s"JAL\t${op.rd.show}, ${op.dst.show} [${labelMap.lift(op.dst).getOrElse(UNKNOWN)}]")
case op: SW => s"SW\t${op.rs2.show}, ${op.offset.show}(${op.rs1.show})" case op: LW => s"LW\t${op.rd.show}, ${op.offset.show}(${op.rs1.show})"
case op: LUI => s"LUI\t${op.rd.show}, ${op.imm.show}" case op: SW => s"SW\t${op.rs2.show}, ${op.offset.show}(${op.rs1.show})"
case op: AUIPC => s"AUIPC\t${op.rd.show}, ${op.imm.show}" case op: LUI => s"LUI\t${op.rd.show}, ${op.imm.show}"
case DONE => s"DONE" case op: AUIPC => s"AUIPC\t${op.rd.show}, ${op.imm.show}"
case DONE => s"DONE"
} }

View file

@ -136,9 +136,9 @@ object TestUtils {
(s"ori ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(imm).show}", ArithImm.or(rd, rs1, imm)), (s"ori ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(imm).show}", ArithImm.or(rd, rs1, imm)),
(s"xori ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(imm).show}", ArithImm.xor(rd, rs1, imm)), (s"xori ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(imm).show}", ArithImm.xor(rd, rs1, imm)),
(s"andi ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(imm).show}", ArithImm.and(rd, rs1, imm)), (s"andi ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(imm).show}", ArithImm.and(rd, rs1, imm)),
(s"slli ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(shift).show}", ArithImm.sll(rd, rs1, shift)), (s"slli ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(shift).show}", ArithImmShift.sll(rd, rs1, shift % 32)),
(s"srli ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(shift).show}", ArithImm.srl(rd, rs1, shift)), (s"srli ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(shift).show}", ArithImmShift.srl(rd, rs1, shift % 32)),
(s"srai ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(shift).show}", ArithImm.sra(rd, rs1, shift)), (s"srai ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(shift).show}", ArithImmShift.sra(rd, rs1, shift % 32)),
(s"slti ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(imm).show}", ArithImm.slt(rd, rs1, imm)), (s"slti ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(imm).show}", ArithImm.slt(rd, rs1, imm)),
(s"sltiu ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(imm).show}", ArithImm.sltu(rd, rs1, imm))) (s"sltiu ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(imm).show}", ArithImm.sltu(rd, rs1, imm)))
(rd, choices.shuffle(r).head) (rd, choices.shuffle(r).head)