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) {
PC := 0.U
// 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 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 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 sltu(rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), SLTU)
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 AUIPC(rd: Reg, imm: Imm) extends Op with UType

View file

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

View file

@ -23,16 +23,17 @@ case class VM(
def stepInstruction: Either[Finished, ExecutionTrace[VM]] = {
if (pc.value == 0xEB1CEB1C) Left(Success)
else getOp flatMap {
case op: Branch => executeBranch(op)
case op: Arith => executeArith(op)
case op: ArithImm => executeArithImm(op)
case op: AUIPC => executeAUIPC(op)
case op: LUI => executeLUI(op)
case op: JALR => executeJALR(op)
case op: JAL => executeJAL(op)
case op: LW => executeLW(op)
case op: SW => executeSW(op)
case DONE => Left(Success)
case op: Branch => executeBranch(op)
case op: Arith => executeArith(op)
case op: ArithImm => executeArithImm(op)
case op: ArithImmShift => executeArithImmShift(op)
case op: AUIPC => executeAUIPC(op)
case op: LUI => executeLUI(op)
case op: JALR => executeJALR(op)
case op: JAL => executeJAL(op)
case op: LW => executeLW(op)
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) = {
val (regUpdate, nextRegs) = regs + (op.rd -> (op.imm.value << 12))
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 = {
val points = List((24, 5))
val withField = applyImmediate(5, immediate, points)(instruction)
withField
def setShiftTypeImmediate(funct7: Int, shamt: Int, addr: Addr): Int => InstructionFragment = {
val shamtPoints = List((24, 5))
val funct7Points = List((31, 6))
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)
@ -142,16 +147,17 @@ object assembler {
def setOpCode(op: Op): Int => Int = op match {
case x: Branch => setOpCode("1100011".binary)
case x: Arith => setOpCode("0110011".binary)
case x: ArithImm => setOpCode("0010011".binary)
case x: LW => setOpCode("0000011".binary)
case x: SW => setOpCode("0100011".binary)
case x: JALR => setOpCode("1100111".binary)
case x: JAL => setOpCode("1101111".binary)
case x: AUIPC => setOpCode("0110111".binary)
case x: LUI => setOpCode("0010111".binary)
case DONE => setOpCode("0010011".binary) // done is turned into a NOP in the assembler.
case x: Branch => setOpCode("1100011".binary)
case x: Arith => setOpCode("0110011".binary)
case x: ArithImm => setOpCode("0010011".binary)
case x: ArithImmShift => setOpCode("0010011".binary)
case x: LW => setOpCode("0000011".binary)
case x: SW => setOpCode("0100011".binary)
case x: JALR => setOpCode("1100111".binary)
case x: JAL => setOpCode("1101111".binary)
case x: AUIPC => setOpCode("0110111".binary)
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 {
@ -195,7 +201,6 @@ object assembler {
setRs1(op.rs1.value)
def assembleSType(op: SType): Int => Int = {
// say("stype")
instruction =>
(setRs1(op.rs1.value) andThen
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 {
case DONE => instruction => Right(instruction)
case op: Arith => instruction => Right(instruction)
case op: ArithImm => setItypeImmediate(op.imm.value, addr)
case op: Branch => setBranchDestination(labelMap, op, 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: AUIPC => setUtypeImmediate(op.imm.value, addr)
case op: LUI => setUtypeImmediate(op.imm.value, addr)
case op: LW => setItypeImmediate(op.offset.value, addr)
case op: SW => setStypeImmediate(op.offset.value, addr)
case op: JAL => instruction => {
case DONE => instruction => Right(instruction)
case op: Arith => instruction => Right(instruction)
case op: ArithImm => setItypeImmediate(op.imm.value, addr)
case op: ArithImmShift => setShiftTypeImmediate(op.imm11.value, op.shamt.value, addr)
case op: Branch => setBranchDestination(labelMap, op, 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: AUIPC => setUtypeImmediate(op.imm.value, addr)
case op: LUI => setUtypeImmediate(op.imm.value, addr)
case op: LW => setItypeImmediate(op.offset.value, addr)
case op: SW => setStypeImmediate(op.offset.value, addr)
case op: JAL => instruction => {
val addressDistance = labelMap
.lift(op.dst).toRight(s"label ${op.dst} not found", addr)
.map(absoluteAddr => absoluteAddr - addr)

View file

@ -81,16 +81,17 @@ object PrintUtils {
val UNKNOWN = "UNKNOWN"
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: 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: 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: JAL => fansi.Color.Magenta(s"JAL\t${op.rd.show}, ${op.dst.show} [${labelMap.lift(op.dst).getOrElse(UNKNOWN)}]")
case op: LW => s"LW\t${op.rd.show}, ${op.offset.show}(${op.rs1.show})"
case op: SW => s"SW\t${op.rs2.show}, ${op.offset.show}(${op.rs1.show})"
case op: LUI => s"LUI\t${op.rd.show}, ${op.imm.show}"
case op: AUIPC => s"AUIPC\t${op.rd.show}, ${op.imm.show}"
case DONE => s"DONE"
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: ArithImm => s"${op.op}I\t${op.rd.show}, ${op.rs1.show}, ${op.imm.show}"
case op: ArithImmShift => s"${op.op}I\t${op.rd.show}, ${op.rs1.show}, ${op.shamt.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: JAL => fansi.Color.Magenta(s"JAL\t${op.rd.show}, ${op.dst.show} [${labelMap.lift(op.dst).getOrElse(UNKNOWN)}]")
case op: LW => s"LW\t${op.rd.show}, ${op.offset.show}(${op.rs1.show})"
case op: SW => s"SW\t${op.rs2.show}, ${op.offset.show}(${op.rs1.show})"
case op: LUI => s"LUI\t${op.rd.show}, ${op.imm.show}"
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"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"slli ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(shift).show}", ArithImm.sll(rd, rs1, shift)),
(s"srli ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(shift).show}", ArithImm.srl(rd, rs1, shift)),
(s"srai ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(shift).show}", ArithImm.sra(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}", ArithImmShift.srl(rd, rs1, shift % 32)),
(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"sltiu ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(imm).show}", ArithImm.sltu(rd, rs1, imm)))
(rd, choices.shuffle(r).head)