From e640daffaa8c67862fe6edb2e45c42171b4428a8 Mon Sep 17 00:00:00 2001 From: peteraa Date: Wed, 28 Aug 2019 15:49:12 +0200 Subject: [PATCH 01/15] remove unused files --- src/test/scala/RISCV/deleteMe.scala | 178 --------------------------- src/test/scala/RISCV/deleteMe2.scala | 164 ------------------------ 2 files changed, 342 deletions(-) delete mode 100644 src/test/scala/RISCV/deleteMe.scala delete mode 100644 src/test/scala/RISCV/deleteMe2.scala diff --git a/src/test/scala/RISCV/deleteMe.scala b/src/test/scala/RISCV/deleteMe.scala deleted file mode 100644 index 0ed9892..0000000 --- a/src/test/scala/RISCV/deleteMe.scala +++ /dev/null @@ -1,178 +0,0 @@ -package FiveStage -import cats.data.Writer -import cats._ -import cats.data.{ Op => _ } -import cats.implicits._ - -object DTree { - - // opaques WHEN - type Feature = String - type Value = String - type Cls = String - - case class TrainingData(values: Map[Feature, Value], cls: Cls) - - type TestData = Map[Feature, Value] - - // Base - // def predict(data: TestData): Cls = "Died" - - // Gendered - def predictStatic(data: TestData): Cls = - if(data("gender") == "female") - "survived" - else "died" - - - sealed trait Tree - case class Node(feature: Feature, children: Map[Value, Tree]) extends Tree - case class Leaf(cls: Cls) extends Tree - - val genderBased: Tree = Node( - "gender", Map( - "female" -> Leaf("survived"), - "male" -> Leaf("died"), - )) - - - def predict(data: TestData)(tree: Tree): Cls = - tree match { - case Leaf(cls) => cls - case Node(feature, children) => predict(data)(children(data(feature))) - } - - val data = Map("gender" -> "female", "family size" -> "0", "ticket" -> "1") - - predict(data)(genderBased) // true - - - def entropy(classes: List[Cls]): Double = { - val total = classes.size - classes.groupBy(identity) - .mapValues { group => - val prop = group.size / total - prop * math.log(1.0 / prop) - }.values.sum - } - - def bucketedEntropy(data: List[TrainingData], feature: Feature): Double = { - val total = data.size - val bucketed = data.groupBy(_.values(feature)) - .mapValues(_.map(_.cls)) - .toMap - bucketed.values.map { classes => - val prop = classes.size / total - prop * entropy(classes) - }.sum - } - - def best(data: List[TrainingData], features: Set[Feature]): Feature = features.minBy(bucketedEntropy(data, _)) - - def mostCommonCls(data: List[TrainingData]): Cls = ??? - - def build(data: List[TrainingData], features: Set[Feature]): Tree = { - if(features.nonEmpty) { - val feature = best(data, features) - val buckets = data.groupBy(_.values(feature)) - Node(feature, buckets.mapValues(build(_, features - feature))) - } else { - Leaf(mostCommonCls(data)) - } - } - - def withHKT { - - sealed trait Tree[A] - case class Node[A](feature: Feature, children: Map[Value, A]) extends Tree[A] - case class Leaf[A](cls: Cls) extends Tree[A] - - // import matryoshka._ - // import matryoshka.data.Fix - // import matryoshka.implicits._ - - case class Fix[F[_]](unfix: F[Fix[F]]) - case class Cofree[F[_], A](head: A, tail: F[Cofree[F, A]]){ - def counit: A = head - def map[B](f: A => B)(implicit ev: Functor[F]): Cofree[F, B] = Cofree(f(head), tail.map(_.map(f))) - - /** - * Coflatmap alters the value of the node based on its context, then recursively - * alters its tail independently (which makes sense as it's the only thing Cofree[F, A] => B can do. - */ - def coflatMap[B](fa: Cofree[F, A] => B)(implicit ev: Functor[F]): Cofree[F, B] = { - val b = fa(this) - val fb = tail.map(_.coflatMap(fa)) - Cofree(b, fb) - } - } - - implicit val treeFunctor: Functor[Tree] = new Functor[Tree] { - def map[A, B](fa: Tree[A])(f: A => B): Tree[B] = fa match { - case Node(name, children) => Node(name, children.mapValues(f)) - case Leaf(cls) => Leaf(cls) - } - } - - val genderBased: Fix[Tree] = - Fix(Node( - "gender", - Map( - "female" -> Fix(Leaf[Fix[Tree]]("survived")), - "male" -> Fix(Leaf[Fix[Tree]]("died")) - ))) - - def build: ((List[TrainingData], Set[Feature])) => Tree[(List[TrainingData], Set[Feature])] = { - case (data, features) => - if(features.nonEmpty) { - val feature = best(data, features) - val buckets = data.groupBy(_.values(feature)) - val next = buckets.mapValues { subset => (subset, features - feature) } - Node(feature, next) - } else { - Leaf(mostCommonCls(data)) - } - } - - def explore(testData: TestData): Fix[Tree] => Cls Either Fix[Tree] = - fix => fix.unfix match { - case Leaf(cls) => Left(cls) - case Node(feature, children) => Right(children.get(testData(feature)).get) - } - - // Anamorphism: Generalized unfold, builds structures - def ana[F[_]: Functor, A](f: A => F[A])(a: A): Fix[F] = - Fix( (f(a)).map(ana(f)) ) - - // Catamorphism: Generalized fold, tears structures down. - def cata[F[_]: Functor, A](fa: F[A] => A)(f: Fix[F]): A = { - fa(f.unfix.map(cata(fa))) - } - - // def hyloSimple[F[_] : Functor, A, B](f: F[B] => B)(g: A => F[A]): A => B - def hyloSimple[F[_]: Functor, A, B](f: F[B] => B)(g: A => F[A])(a: A): B = - cata(f)(ana(g)(a)) - - // A more powerful cata - def para[F[_]: Functor, A](f: F[(Fix[F], A)] => A)(fa: Fix[F]): A = - f(fa.unfix.map(x => (x, para(f)(x)))) - - // A more powerful ana - def apo[F[_]: Functor, A](f: A => F[Either[Fix[F], A]])(a: A): Fix[F] = { - Fix(f(a).map{ - case Right(a) => apo(f)(a) - case Left(fix) => fix - }) - } - - // When we have cofree - def histo[F[_]: Functor, A](f: F[Cofree[F, A]] => A)(fix: Fix[F]): A = { - def toCofree(fix: Fix[F]): Cofree[F, A] = - Cofree(histo(f)(fix), fix.unfix.map(toCofree)) - - f(fix.unfix.map(toCofree)) - } - - - } -} diff --git a/src/test/scala/RISCV/deleteMe2.scala b/src/test/scala/RISCV/deleteMe2.scala deleted file mode 100644 index 74662cb..0000000 --- a/src/test/scala/RISCV/deleteMe2.scala +++ /dev/null @@ -1,164 +0,0 @@ -package FiveStage -import cats.data.Writer -import cats._ -import cats.data.{ Op => _ } -import cats.implicits._ - -import fileUtils.say - -object DeletDis { - - def delet = { - - case class Fix[F[_]](unfix: F[Fix[F]]) - case class Cofree[F[_], A](head: A, tail: F[Cofree[F, A]]){ - def counit: A = head - def map[B](f: A => B)(implicit ev: Functor[F]): Cofree[F, B] = Cofree(f(head), tail.map(_.map(f))) - - /** - * Coflatmap alters the value of the node based on its context, then recursively - * alters its tail independently (which makes sense as it's the only thing Cofree[F, A] => B can do. - */ - def coflatMap[B](fa: Cofree[F, A] => B)(implicit ev: Functor[F]): Cofree[F, B] = { - val b = fa(this) - val fb = tail.map(_.coflatMap(fa)) - Cofree(b, fb) - } - } - - // Anamorphism: Generalized unfold, builds structures - def ana[F[_]: Functor, A](f: A => F[A])(a: A): Fix[F] = - Fix( (f(a)).map(ana(f)) ) - - // Catamorphism: Generalized fold, tears structures down. - def cata[F[_]: Functor, A](fa: F[A] => A)(f: Fix[F]): A = { - fa(f.unfix.map(cata(fa))) - } - - // def hyloSimple[F[_] : Functor, A, B](f: F[B] => B)(g: A => F[A]): A => B - def hylo[F[_]: Functor, A, B](f: F[B] => B)(g: A => F[A])(a: A): B = - cata(f)(ana(g)(a)) - - // A more powerful cata - def para[F[_]: Functor, A](f: F[(Fix[F], A)] => A)(fa: Fix[F]): A = - f(fa.unfix.map(x => (x, para(f)(x)))) - - // A more powerful ana - def apo[F[_]: Functor, A](f: A => F[Either[Fix[F], A]])(a: A): Fix[F] = { - Fix(f(a).map{ - case Right(a) => apo(f)(a) - case Left(fix) => fix - }) - } - - // When we have cofree - def histo[F[_]: Functor, A](f: F[Cofree[F, A]] => A)(fix: Fix[F]): A = { - def toCofree(fix: Fix[F]): Cofree[F, A] = - Cofree(histo(f)(fix), fix.unfix.map(toCofree)) - - f(fix.unfix.map(toCofree)) - } - - sealed trait StackR - final case class DoneR(result: Int = 1) extends StackR - final case class MoreR(stack: StackR, next: Int) extends StackR - - def unfoldStackR(n: Int): StackR = - if(n > 0) MoreR(unfoldStackR(n-1), n) else DoneR() - - say(unfoldStackR(5)) - - sealed trait Stack[A] - final case class Done[A](result: Int) extends Stack[A] - final case class More[A](a: A, next: Int) extends Stack[A] - - object Stack { - implicit val stackFunctor: Functor[Stack] = new Functor[Stack] { - def map[A, B](fa: Stack[A])(f: A => B): Stack[B] = fa match { - case Done(result) => Done(result) - case More(a, next) => More(f(a), next) - } - } - - def done[A](result: Int = 1): Stack[A] = Done(result) - def more[A](a: A, next: Int): Stack[A] = More(a, next) - } - - import Stack._ - - val stackCoalgebra: Int => Stack[Int] = - n => if(n > 0) more(n - 1, n) else done() - - say(ana(stackCoalgebra)(5)) - - val stackAlgebra: Stack[Int] => Int = { - case Done(result) => result - case More(acc, next) => acc * next - } - - say(cata(stackAlgebra)(ana(stackCoalgebra)(5))) - say(hylo(stackAlgebra)(stackCoalgebra)(5)) - - - sealed trait Nat[A] - final case class Zero[A]() extends Nat[A] - final case class Succ[A](prev: A) extends Nat[A] - - object Nat { - implicit val natFunctor: Functor[Nat] = new Functor[Nat] { - override def map[A, B](na: Nat[A])(f: A => B): Nat[B] = - na match { - case Zero() => Zero() - case Succ(a) => Succ(f(a)) - } - } - } - - val natAlgebra: Nat[Int] => Int = { - case Zero() => 1 - case Succ(n) => { - say(s"nat alg succ $n") - n + 1 - } - } - - val natAlgebraS: Nat[String] => String = { - case Zero() => "N" - case Succ(n) => n match { - case "N" => "NI" - case "NI" => "NIG" - case "NIG" => "NIGG" - case "NIGG" => "NIGGE" - case "NIGGE" => "NIGGER :-" - case s => s + "D" - } - } - - val natCoalgebra: Int => Nat[Int] = - n => if (n == 0) Zero() else Succ(n - 1) - - val b = ana(natCoalgebra)(9) - val c = cata(natAlgebraS)(b) - say(c) - - - val natAlgebraPara: Nat[(Fix[Nat], Int)] => Int = { - case Zero() => 1 - case Succ((fix, acc)) => { - say(s"nat para alg succ $fix, $acc") - cata(natAlgebra)(fix) * acc - } - } - - val build = ana(natCoalgebra)(_) - say("built") - val tear = para(natAlgebraPara)(_) - say(tear(build(5))) - // say(ana(natCoalgebra)(5)) - - val lastThreeSteps: Fix[Stack] = Fix(More(Fix(More(Fix(More(Fix(Done(1)),1)),2)),3)) - - val stackCoalgebraApo: Int => Stack[Either[Fix[Stack], Int]] = - n => if(n > 3) more(n - 1, n).map(_.asRight) else lastThreeSteps.unfix.map(_.asLeft) - } -} From 8982b5529c7074de31e4efd5e79c2d2fae3c5fb2 Mon Sep 17 00:00:00 2001 From: peteraa Date: Wed, 28 Aug 2019 16:13:15 +0200 Subject: [PATCH 02/15] Clarify setup instructions for IF.scala --- src/main/scala/IF.scala | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/scala/IF.scala b/src/main/scala/IF.scala index 55b9c87..2195819 100644 --- a/src/main/scala/IF.scala +++ b/src/main/scala/IF.scala @@ -49,11 +49,18 @@ class InstructionFetch extends MultiIOModule { /** - * Setup. You should not change this code + * Setup. + * + * When you have added an instruction signal to this module you + * should ensure that it is set to NOP during program loading. + * + * If not you will end up issuing instructions during program load + * which will start executing before memory, registers and programs + * are fully loaded. */ when(testHarness.IMEMsetup.setup) { PC := 0.U - // TODO: You must set the instruction to Instruction.NOP here. - // throw new Exception("Just making sure you're seeing the line above") + // 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") } } From cad9fa0521d422d82e14cdc22da685fea21c11a1 Mon Sep 17 00:00:00 2001 From: peteraa Date: Thu, 29 Aug 2019 16:18:09 +0200 Subject: [PATCH 03/15] Fix parser typo for sltiu --- src/test/scala/RISCV/Parser.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/RISCV/Parser.scala b/src/test/scala/RISCV/Parser.scala index f987d48..7bd5a45 100644 --- a/src/test/scala/RISCV/Parser.scala +++ b/src/test/scala/RISCV/Parser.scala @@ -89,7 +89,7 @@ object Parser { stringWs("srai") ~> arithImm.mapN{ArithImm.sra}, stringWs("slti") ~> arithImm.mapN{ArithImm.slt}, - stringWs("sltui") ~> arithImm.mapN{ArithImm.sltu}, + stringWs("sltiu") ~> arithImm.mapN{ArithImm.sltu}, // pseudos stringWs("not") ~> (reg <~ sep, reg, ok(-1)).mapN{ArithImm.xor}, From 9358c3a6be66dd15bfc34846d09c639e7a266f8a Mon Sep 17 00:00:00 2001 From: peteraa Date: Thu, 29 Aug 2019 16:33:06 +0200 Subject: [PATCH 04/15] Fix wrong MuxLookup definition. Sorry :( --- exercise.org | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exercise.org b/exercise.org index e7155b5..c33faad 100644 --- a/exercise.org +++ b/exercise.org @@ -247,7 +247,8 @@ ... ) - io.aluResult := MuxLookup(0.U(32.W), io.aluOp, ALUopMap) + // MuxLookup API: https://github.com/freechipsproject/chisel3/wiki/Muxes-and-Input-Selection#muxlookup + io.aluResult := MuxLookup(io.aluOp, 0.U(32.W), ALUopMap) #+END_SRC *** Step 6: From 8e2d686b5c938a828eba1bfe1dd8c42d0643bae3 Mon Sep 17 00:00:00 2001 From: peteraa Date: Wed, 4 Sep 2019 11:52:49 +0200 Subject: [PATCH 05/15] Add special handlers for shift instructions. --- .jvmopts | 4 ++ src/main/scala/IF.scala | 2 +- src/test/scala/RISCV/Ops.scala | 9 +++-- src/test/scala/RISCV/Parser.scala | 18 ++++----- src/test/scala/RISCV/VM.scala | 28 ++++++++----- src/test/scala/RISCV/assembler.scala | 58 +++++++++++++++------------ src/test/scala/RISCV/printUtils.scala | 21 +++++----- src/test/scala/TestUtils.scala | 6 +-- 8 files changed, 84 insertions(+), 62 deletions(-) create mode 100644 .jvmopts diff --git a/.jvmopts b/.jvmopts new file mode 100644 index 0000000..03918b6 --- /dev/null +++ b/.jvmopts @@ -0,0 +1,4 @@ +-Xms512M +-Xmx4096M +-Xss32M +-XX:MaxMetaspaceSize=1024M \ No newline at end of file diff --git a/src/main/scala/IF.scala b/src/main/scala/IF.scala index 2195819..232442f 100644 --- a/src/main/scala/IF.scala +++ b/src/main/scala/IF.scala @@ -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") } } diff --git a/src/test/scala/RISCV/Ops.scala b/src/test/scala/RISCV/Ops.scala index e627d90..9158312 100644 --- a/src/test/scala/RISCV/Ops.scala +++ b/src/test/scala/RISCV/Ops.scala @@ -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 diff --git a/src/test/scala/RISCV/Parser.scala b/src/test/scala/RISCV/Parser.scala index 7bd5a45..c00bcd2 100644 --- a/src/test/scala/RISCV/Parser.scala +++ b/src/test/scala/RISCV/Parser.scala @@ -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]), diff --git a/src/test/scala/RISCV/VM.scala b/src/test/scala/RISCV/VM.scala index fe545bd..203161f 100644 --- a/src/test/scala/RISCV/VM.scala +++ b/src/test/scala/RISCV/VM.scala @@ -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) diff --git a/src/test/scala/RISCV/assembler.scala b/src/test/scala/RISCV/assembler.scala index 298a85b..7c4f943 100644 --- a/src/test/scala/RISCV/assembler.scala +++ b/src/test/scala/RISCV/assembler.scala @@ -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) diff --git a/src/test/scala/RISCV/printUtils.scala b/src/test/scala/RISCV/printUtils.scala index 77fe516..4c18a8a 100644 --- a/src/test/scala/RISCV/printUtils.scala +++ b/src/test/scala/RISCV/printUtils.scala @@ -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" } diff --git a/src/test/scala/TestUtils.scala b/src/test/scala/TestUtils.scala index 5943fd7..0a671d1 100644 --- a/src/test/scala/TestUtils.scala +++ b/src/test/scala/TestUtils.scala @@ -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) From de7d01f7100e987cd354b01ef381f51165ab3dea Mon Sep 17 00:00:00 2001 From: peteraa Date: Wed, 4 Sep 2019 12:01:46 +0200 Subject: [PATCH 06/15] Add new forward.s tests with correct shifts. --- src/test/resources/tests/basic/forward1.s | 384 ++++++++++----------- src/test/resources/tests/basic/forward2.s | 402 +++++++++++----------- src/test/scala/TestUtils.scala | 12 +- 3 files changed, 399 insertions(+), 399 deletions(-) diff --git a/src/test/resources/tests/basic/forward1.s b/src/test/resources/tests/basic/forward1.s index 205a781..b6d7d97 100644 --- a/src/test/resources/tests/basic/forward1.s +++ b/src/test/resources/tests/basic/forward1.s @@ -1,204 +1,204 @@ main: - ori gp, gp, 0xFFFFFE09 - and gp, gp, ra - xor ra, ra, sp - sra ra, sp, sp + sltiu gp, ra, 0x01AE + srli sp, sp, 0x0005 + addi ra, sp, 0x0177 + srai sp, ra, 0x0003 + sub sp, ra, sp + slli sp, ra, 0x000B + add sp, gp, ra + slli gp, sp, 0x0006 + ori sp, ra, 0xFFFFFF64 + and gp, gp, gp + andi gp, gp, 0x0084 + xori ra, ra, 0xFFFFFEB4 or sp, ra, ra - xori ra, sp, 0x003D - srli sp, sp, 0xFFFFFFF2 - addi ra, sp, 0x0012 - add ra, gp, sp - ori gp, ra, 0xFFFFFFB8 - sll ra, ra, ra - sll sp, gp, ra - slt ra, gp, ra - srai gp, gp, 0xFFFFFFFB - slli ra, ra, 0x0007 - sub sp, gp, sp - andi ra, gp, 0x002D - sub gp, gp, sp - srai ra, gp, 0x0005 - or sp, ra, sp - xori ra, gp, 0xFFFFFF54 - sll ra, sp, ra - sub gp, gp, sp - add ra, sp, sp - sll ra, gp, ra - add gp, sp, sp - ori gp, sp, 0xFFFFFE68 - srli sp, gp, 0xFFFFFFF1 - sltui ra, ra, 0xFFFFFE5D - srli ra, gp, 0x0006 - srai sp, sp, 0x0005 - andi sp, sp, 0x0129 - and sp, sp, sp - slli gp, ra, 0x0001 - or gp, gp, gp - or sp, gp, gp - slli gp, gp, 0x0006 - srl sp, ra, gp - sltui gp, ra, 0xFFFFFEC3 - add sp, gp, sp - xori ra, ra, 0xFFFFFFA2 - or gp, gp, sp - and sp, gp, gp - srai gp, sp, 0x0008 - add sp, sp, ra - slti sp, ra, 0xFFFFFFF7 - srli gp, ra, 0xFFFFFFFD - sll gp, ra, gp - sltu sp, sp, gp - srli gp, ra, 0x0002 - ori gp, sp, 0xFFFFFF28 - srl ra, gp, ra - slti gp, ra, 0x0054 - or gp, ra, ra - ori sp, gp, 0x01D9 + addi sp, ra, 0x0078 + sltiu sp, sp, 0xFFFFFF1E + srli gp, sp, 0x0000 + slti sp, ra, 0xFFFFFEF7 + srai ra, ra, 0x0001 + or sp, ra, gp + xor sp, sp, ra + sub sp, ra, sp + sub ra, gp, ra + sltiu gp, sp, 0xFFFFFE85 + addi sp, gp, 0x017C + sltiu ra, gp, 0xFFFFFF64 + xori sp, gp, 0x00A1 + xor ra, sp, gp + ori gp, ra, 0x00B6 + add ra, ra, sp + sltiu gp, ra, 0xFFFFFFEC + sltu gp, sp, ra + sll sp, ra, gp + add gp, ra, ra + or gp, ra, gp + xor sp, ra, sp + addi sp, gp, 0xFFFFFF4C + xor ra, sp, gp + xori ra, sp, 0xFFFFFF72 + xori gp, sp, 0xFFFFFE95 + or ra, ra, ra + slti ra, gp, 0xFFFFFE75 + slli sp, sp, 0x0004 + sltiu ra, ra, 0xFFFFFE25 + add sp, ra, gp + sltiu gp, gp, 0xFFFFFFDB + addi sp, sp, 0x003D + sll ra, ra, sp + ori ra, ra, 0x012C + add gp, ra, gp + xori sp, sp, 0x0157 + slti gp, sp, 0xFFFFFF2A and sp, ra, ra - addi sp, gp, 0x0054 - slli gp, ra, 0xFFFFFFF2 - ori sp, sp, 0x0093 - add gp, gp, gp - and gp, gp, gp - sltui gp, ra, 0x00DE - slli sp, gp, 0x000D - slli sp, ra, 0xFFFFFFF5 - sltui sp, ra, 0xFFFFFF0E - and ra, gp, ra - add gp, sp, sp - slti ra, sp, 0x008C - srli ra, sp, 0x0000 - addi sp, sp, 0x0168 - slli ra, ra, 0xFFFFFFF3 - addi ra, gp, 0x012A - or sp, gp, ra - add ra, sp, gp - and gp, ra, ra - slli ra, gp, 0xFFFFFFF6 - or sp, gp, sp - or gp, ra, ra - ori gp, ra, 0x00EB - or sp, gp, ra - ori gp, sp, 0x01DA - andi ra, ra, 0xFFFFFFE9 - addi gp, sp, 0x00C9 - sltui ra, ra, 0xFFFFFF13 - sltui ra, ra, 0xFFFFFF3A - sltui sp, gp, 0xFFFFFE5A - ori sp, sp, 0xFFFFFFFE - and gp, sp, gp - sltui sp, ra, 0x0034 - srl gp, gp, ra - sll gp, sp, ra - ori ra, gp, 0xFFFFFEB6 - sll ra, sp, ra - sra ra, gp, sp - sub ra, sp, gp - xor gp, gp, sp - sub ra, ra, sp - srl gp, gp, sp - andi ra, ra, 0xFFFFFFCB - ori ra, ra, 0xFFFFFE1B - andi ra, ra, 0xFFFFFEC8 - sltui sp, gp, 0x0108 + add gp, ra, ra + sltiu ra, gp, 0xFFFFFE56 + sra gp, gp, ra + xori sp, gp, 0xFFFFFF0D sub sp, gp, ra - slti ra, sp, 0x015D - slli sp, sp, 0x0004 - xor gp, sp, ra - srl ra, gp, ra - sltui ra, ra, 0xFFFFFF3C - add sp, sp, sp - add gp, gp, ra - andi sp, sp, 0xFFFFFF3A - srli ra, sp, 0x0004 - ori sp, gp, 0xFFFFFEAB - ori sp, ra, 0xFFFFFE95 - slli sp, sp, 0xFFFFFFF2 - xori gp, sp, 0x0040 - slti gp, sp, 0xFFFFFED1 - or sp, sp, sp - sltui sp, gp, 0x01B4 - addi ra, gp, 0x002D - and sp, gp, gp - or ra, ra, ra - or ra, gp, ra - or ra, gp, ra - sra ra, ra, gp - sra gp, ra, sp - sub ra, sp, ra + slti ra, ra, 0x0154 + slli ra, ra, 0x000A + ori ra, gp, 0xFFFFFEC2 + ori ra, sp, 0x0075 + addi gp, sp, 0x0079 + xor gp, ra, sp + srli ra, sp, 0x0008 srai ra, ra, 0x000F - sltu sp, sp, ra - slli ra, gp, 0xFFFFFFF5 - slti gp, gp, 0x00E0 - addi gp, ra, 0xFFFFFF72 - srl ra, ra, gp - sltui gp, sp, 0xFFFFFEAA - xor sp, ra, gp - and gp, sp, ra - srli gp, gp, 0x0003 - xori ra, ra, 0x01BD - sub ra, gp, sp + slli gp, gp, 0x0006 + sra sp, gp, gp + add sp, sp, sp + srai ra, sp, 0x0001 + slli gp, ra, 0x0010 + andi ra, ra, 0xFFFFFFA8 + add sp, ra, sp + srai ra, gp, 0x000E + srai ra, sp, 0x0005 + addi ra, gp, 0xFFFFFF83 + xor gp, sp, ra + srai sp, gp, 0x0004 + srli ra, ra, 0x0007 sll gp, ra, gp - xori ra, sp, 0x0065 - or ra, sp, ra - slt sp, gp, ra - addi ra, sp, 0xFFFFFE34 - slli gp, sp, 0x0007 - sll ra, sp, gp - sltui gp, gp, 0xFFFFFE62 - slti sp, sp, 0x0019 - xori ra, gp, 0x0092 - sltui gp, sp, 0xFFFFFF29 - srl sp, ra, gp - xori sp, gp, 0xFFFFFF4C - add sp, ra, gp - add sp, gp, ra + xori gp, gp, 0x0163 + add ra, gp, gp + srli gp, gp, 0x000B + add sp, ra, ra + sltu ra, ra, sp + sll sp, ra, ra + ori sp, sp, 0xFFFFFF6B + slli gp, gp, 0x0006 + xori sp, ra, 0x00A7 + add sp, ra, ra + add ra, gp, gp + addi gp, gp, 0xFFFFFFE9 + sra sp, ra, gp + add gp, ra, ra + ori gp, gp, 0x0002 + addi gp, gp, 0x002F + sll sp, sp, ra + srli sp, ra, 0x000E + ori gp, sp, 0x00EB + sra gp, ra, sp sra sp, sp, gp - slli sp, ra, 0x0008 - srl sp, sp, sp + and gp, ra, ra + sra ra, ra, gp add sp, gp, ra - andi sp, sp, 0x0039 - sll ra, gp, sp - andi gp, ra, 0xFFFFFECC - sll sp, sp, sp - sub sp, sp, ra - srai ra, sp, 0x0008 - xor gp, ra, sp - add sp, sp, sp - sub gp, ra, gp - xori gp, sp, 0x01EE - and ra, ra, ra - ori gp, ra, 0xFFFFFE96 - slli ra, gp, 0x0002 - srli gp, ra, 0x000D - add ra, sp, sp - andi sp, gp, 0xFFFFFEC0 - andi sp, gp, 0xFFFFFE7A - xori ra, sp, 0x0169 - xori gp, sp, 0xFFFFFE02 - andi ra, ra, 0xFFFFFFD1 - xor ra, sp, gp - xori gp, gp, 0x00AB - srl ra, ra, gp - and ra, ra, sp - xori gp, sp, 0x005D - srai sp, sp, 0x000A - addi ra, sp, 0xFFFFFE19 + srl gp, sp, gp + add ra, ra, sp + srai gp, ra, 0x000E + sltu gp, gp, sp + srli sp, ra, 0x0004 + ori gp, sp, 0xFFFFFE6E + and gp, ra, ra + ori gp, ra, 0xFFFFFFAF + srl ra, ra, ra or sp, ra, ra - addi ra, gp, 0x0084 - ori sp, sp, 0xFFFFFF3D - xor gp, ra, gp - sra ra, ra, gp - xori ra, sp, 0x0040 - srai gp, gp, 0x0002 - xori ra, ra, 0xFFFFFE9A - sra ra, sp, sp - ori gp, sp, 0xFFFFFFB8 - sll sp, ra, ra - sll sp, ra, gp - sll gp, sp, sp - sra gp, ra, ra - srli gp, gp, 0x0001 + ori gp, sp, 0x0018 + and gp, gp, gp + sll gp, sp, gp + srli gp, sp, 0x0006 + add gp, ra, ra + add gp, ra, sp + sra sp, ra, ra + ori sp, ra, 0x0022 + and gp, gp, gp + add ra, sp, ra + sll sp, gp, gp + ori gp, sp, 0x008E + add sp, ra, sp + and sp, gp, gp + addi ra, sp, 0x0145 + and sp, gp, gp + sll gp, ra, sp + addi sp, sp, 0xFFFFFFAF + xori sp, ra, 0xFFFFFE2C + srl gp, ra, gp + sub ra, sp, gp + add sp, ra, ra + slli sp, sp, 0x0006 + sltu gp, sp, ra + sub gp, ra, sp + xori ra, ra, 0xFFFFFF9A + addi sp, sp, 0xFFFFFE12 + slli ra, ra, 0x0003 + slli gp, ra, 0x0004 + add gp, gp, gp + xori ra, ra, 0xFFFFFED7 + andi gp, gp, 0xFFFFFE05 + and gp, gp, sp + addi gp, gp, 0xFFFFFEE5 + slli ra, gp, 0x000A + sll sp, gp, gp + and ra, gp, sp + ori ra, gp, 0xFFFFFE22 + srl sp, sp, gp + srli ra, sp, 0x0005 + slli ra, ra, 0x0005 + srai ra, ra, 0x0007 + srli ra, gp, 0x000F + andi gp, gp, 0xFFFFFF96 + sra sp, gp, gp + srai gp, gp, 0x000F + sub sp, sp, gp + sltiu ra, ra, 0xFFFFFF41 + and sp, sp, sp + xor gp, sp, ra + srai gp, sp, 0x000A + xori gp, gp, 0x00D3 + or gp, sp, sp + sltu gp, ra, gp + slli ra, gp, 0x0002 + or sp, gp, ra + addi ra, ra, 0x002B + addi gp, ra, 0x0035 + slli sp, gp, 0x0008 + addi gp, sp, 0x015E + xor ra, gp, sp + or ra, gp, ra + sll ra, gp, ra + sll gp, gp, ra + srli gp, ra, 0x000C + slt sp, ra, sp + sltiu sp, sp, 0xFFFFFE1C + ori sp, ra, 0xFFFFFE83 + andi sp, sp, 0xFFFFFEFC + addi ra, ra, 0xFFFFFF85 + ori gp, ra, 0x0084 + sll gp, gp, ra + xori gp, sp, 0xFFFFFF6D + sll gp, sp, gp + sra ra, sp, ra + xor ra, gp, sp + srl ra, ra, sp + srl ra, ra, sp + andi gp, ra, 0xFFFFFE7B + srai ra, sp, 0x000F + sub sp, sp, ra + or sp, gp, gp + slt ra, ra, gp + or gp, gp, sp + srli ra, sp, 0x000B + andi ra, gp, 0xFFFFFFD4 + slli ra, gp, 0x0009 done #regset x1, 123 #regset x2, -40 diff --git a/src/test/resources/tests/basic/forward2.s b/src/test/resources/tests/basic/forward2.s index 9b5e973..b49b85b 100644 --- a/src/test/resources/tests/basic/forward2.s +++ b/src/test/resources/tests/basic/forward2.s @@ -1,205 +1,205 @@ main: - sltui gp, ra, 0x01AE - srli sp, sp, 0xFFFFFFFB - addi ra, sp, 0x0177 - sub sp, ra, sp - slli sp, ra, 0x000B - add sp, gp, ra - slli gp, sp, 0x0006 - ori sp, ra, 0xFFFFFF64 - and gp, gp, gp - andi gp, gp, 0x0084 - xori ra, ra, 0xFFFFFEB4 - or sp, ra, ra - addi sp, ra, 0x0078 - srli gp, sp, 0x0000 - srl sp, gp, sp - andi ra, gp, 0xFFFFFFF4 - srai ra, ra, 0xFFFFFFFF - sltu gp, sp, gp - or sp, ra, gp - sub ra, gp, ra - addi sp, gp, 0x017C - sltui ra, gp, 0xFFFFFF64 - xori sp, gp, 0x00A1 - xor ra, sp, gp - ori gp, ra, 0x00B6 - add ra, ra, sp - sltui gp, ra, 0xFFFFFFEC - sltu gp, sp, ra - sll sp, ra, gp - add gp, ra, ra - or gp, ra, gp - xor sp, ra, sp - addi sp, gp, 0xFFFFFF4C - xor ra, sp, gp - xori ra, sp, 0xFFFFFF72 - xori gp, sp, 0xFFFFFE95 - or ra, ra, ra - slti ra, gp, 0xFFFFFE75 - slli sp, sp, 0xFFFFFFFC - sltui ra, ra, 0xFFFFFE25 - add sp, ra, gp - sltui gp, gp, 0xFFFFFFDB - addi sp, sp, 0x003D - sll ra, ra, sp - ori ra, ra, 0x012C - add gp, ra, gp - xori sp, sp, 0x0157 - slti gp, sp, 0xFFFFFF2A - and sp, ra, ra - add gp, ra, ra - sltui ra, gp, 0xFFFFFE56 - sra gp, gp, ra - xori sp, gp, 0xFFFFFF0D - sub sp, gp, ra - slti ra, ra, 0x0154 - slli ra, ra, 0x000A - ori ra, gp, 0xFFFFFEC2 - ori ra, sp, 0x0075 - addi gp, sp, 0x0079 - xor gp, ra, sp - srli ra, sp, 0xFFFFFFF8 - slli gp, gp, 0x0006 - sra sp, gp, gp - add sp, sp, sp - slli gp, ra, 0xFFFFFFF0 - add sp, ra, sp - srai ra, sp, 0x0005 - addi ra, gp, 0xFFFFFF83 - xor gp, sp, ra - srli ra, ra, 0x0007 - sll gp, ra, gp - xori gp, gp, 0x0163 - add ra, gp, gp - add sp, ra, ra - sltu ra, ra, sp - sll sp, ra, ra - ori sp, sp, 0xFFFFFF6B - slli gp, gp, 0xFFFFFFFA - xori sp, ra, 0x00A7 - add sp, ra, ra - add ra, gp, gp - addi gp, gp, 0xFFFFFFE9 - sra sp, ra, gp - add gp, ra, ra - ori gp, gp, 0x0002 - addi gp, gp, 0x002F - sll sp, sp, ra - srli sp, ra, 0xFFFFFFF2 - ori gp, sp, 0x00EB - sra gp, ra, sp - sra sp, sp, gp - and gp, ra, ra - sra ra, ra, gp - add sp, gp, ra - srl gp, sp, gp - add ra, ra, sp - srai gp, ra, 0xFFFFFFF2 - srli sp, ra, 0xFFFFFFFC - ori gp, sp, 0xFFFFFE6E - and gp, ra, ra - ori gp, ra, 0xFFFFFFAF - srl ra, ra, ra - or sp, ra, ra - ori gp, sp, 0x0018 - and gp, gp, gp - slti gp, ra, 0x00C6 - sll gp, sp, gp - srli gp, sp, 0xFFFFFFFA - add gp, ra, ra - add gp, ra, sp - sra sp, ra, ra - ori sp, ra, 0x0022 - and gp, gp, gp - add ra, sp, ra - sll sp, gp, gp - ori gp, sp, 0x008E - slti ra, gp, 0x00B5 - add sp, ra, sp - and sp, gp, gp - addi ra, sp, 0x0145 - and sp, gp, gp - sll gp, ra, sp - addi sp, sp, 0xFFFFFFAF - xori sp, ra, 0xFFFFFE2C - srl gp, ra, gp - sub ra, sp, gp - add sp, ra, ra - slli sp, sp, 0x0006 - sub gp, ra, sp - sltu sp, ra, gp - xori ra, ra, 0xFFFFFF9A - addi sp, sp, 0xFFFFFE12 - slli ra, ra, 0xFFFFFFFD - add gp, gp, gp - xori ra, ra, 0xFFFFFED7 - andi gp, gp, 0xFFFFFE05 - and gp, gp, sp - addi gp, gp, 0xFFFFFEE5 - slli ra, gp, 0xFFFFFFF6 - sll sp, gp, gp - and ra, gp, sp - ori ra, gp, 0xFFFFFE22 - srl sp, sp, gp - srli ra, sp, 0x0005 - slli ra, ra, 0xFFFFFFFB - srai ra, ra, 0xFFFFFFF9 - srli ra, gp, 0xFFFFFFF1 - andi gp, gp, 0xFFFFFF96 - sra sp, gp, gp - srai gp, gp, 0x000F - sub sp, sp, gp - sltui ra, ra, 0xFFFFFF41 - and sp, sp, sp - xor gp, sp, ra - srai gp, sp, 0xFFFFFFF6 - xori gp, gp, 0x00D3 - or gp, sp, sp - sltu gp, ra, gp - slli ra, gp, 0x0002 - or sp, gp, ra - addi ra, ra, 0x002B - addi gp, ra, 0x0035 - slli sp, gp, 0x0008 - addi gp, sp, 0x015E - xor ra, gp, sp - or ra, gp, ra - sll ra, gp, ra - sll gp, gp, ra - srli gp, ra, 0xFFFFFFF4 - slt sp, ra, sp - sltui sp, sp, 0xFFFFFE1C - ori sp, ra, 0xFFFFFE83 - andi sp, sp, 0xFFFFFEFC - addi ra, ra, 0xFFFFFF85 - ori gp, ra, 0x0084 - sll gp, gp, ra - xori gp, sp, 0xFFFFFF6D - sll gp, sp, gp - sra ra, sp, ra - xor ra, gp, sp - srl ra, ra, sp - srl ra, ra, sp - andi gp, ra, 0xFFFFFE7B - srai ra, sp, 0xFFFFFFF1 - sub sp, sp, ra - or sp, gp, gp - slt ra, ra, gp - or gp, gp, sp - srli ra, sp, 0xFFFFFFF5 - andi ra, gp, 0xFFFFFFD4 - sra sp, sp, sp - add sp, ra, sp - sub gp, ra, sp - xori ra, gp, 0x0131 - add sp, sp, ra - addi sp, gp, 0x0003 - sll ra, ra, ra - slli gp, ra, 0x000E - andi ra, gp, 0xFFFFFE88 - srai ra, gp, 0xFFFFFFFA - done + ori gp, gp, 0xFFFFFE09 + and gp, gp, ra + srli sp, ra, 0x0002 + xor ra, ra, sp + or sp, ra, ra + xori ra, sp, 0x003D + addi ra, sp, 0x0012 + add ra, gp, sp + ori gp, ra, 0xFFFFFFB8 + sll ra, ra, ra + sll sp, gp, ra + slt ra, gp, ra + srai gp, gp, 0x0005 + slli ra, ra, 0x0007 + sub sp, gp, sp + andi ra, gp, 0x002D + sub gp, gp, sp + srai ra, gp, 0x0005 + or sp, ra, sp + xori ra, gp, 0xFFFFFF54 + sll ra, sp, ra + sub gp, gp, sp + add ra, sp, sp + sll ra, gp, ra + add gp, sp, sp + ori gp, sp, 0xFFFFFE68 + srli sp, gp, 0x000F + sltiu ra, ra, 0xFFFFFE5D + srli ra, gp, 0x0006 + srai sp, sp, 0x0005 + andi sp, sp, 0x0129 + and sp, sp, sp + slli gp, ra, 0x0001 + or gp, gp, gp + or sp, gp, gp + slli gp, gp, 0x0006 + srl sp, ra, gp + sltiu gp, ra, 0xFFFFFEC3 + add sp, gp, sp + srli ra, sp, 0x0001 + xori ra, ra, 0xFFFFFFA2 + or gp, gp, sp + and sp, gp, gp + srai gp, sp, 0x0008 + add sp, sp, ra + slti sp, ra, 0xFFFFFFF7 + srli gp, ra, 0x0003 + sll gp, ra, gp + sltu sp, sp, gp + srli gp, ra, 0x0002 + ori gp, sp, 0xFFFFFF28 + srl ra, gp, ra + or gp, ra, ra + ori sp, gp, 0x01D9 + and sp, ra, ra + addi sp, gp, 0x0054 + slli gp, ra, 0x000E + ori sp, sp, 0x0093 + srai sp, ra, 0x000F + slti ra, gp, 0xFFFFFFCB + add gp, gp, gp + and gp, gp, gp + sltiu gp, ra, 0x00DE + slli sp, gp, 0x000D + slli sp, ra, 0x000B + sltiu sp, ra, 0xFFFFFF0E + and ra, gp, ra + add gp, sp, sp + slti ra, sp, 0x008C + srli ra, sp, 0x0000 + addi sp, sp, 0x0168 + slli ra, ra, 0x000D + addi ra, gp, 0x012A + or sp, gp, ra + add ra, sp, gp + and gp, ra, ra + slli ra, gp, 0x000A + or sp, gp, sp + or gp, ra, ra + srli ra, sp, 0x0002 + ori gp, ra, 0x00EB + or sp, gp, ra + ori gp, sp, 0x01DA + andi ra, ra, 0xFFFFFFE9 + addi gp, sp, 0x00C9 + sltiu ra, ra, 0xFFFFFF13 + sltiu ra, ra, 0xFFFFFF3A + sltiu sp, gp, 0xFFFFFE5A + ori sp, sp, 0xFFFFFFFE + and gp, sp, gp + sltiu sp, ra, 0x0034 + srl gp, gp, ra + sll gp, sp, ra + ori ra, gp, 0xFFFFFEB6 + sll ra, sp, ra + sra ra, gp, sp + sub ra, sp, gp + xor gp, gp, sp + sub ra, ra, sp + srl gp, gp, sp + andi ra, ra, 0xFFFFFFCB + ori ra, ra, 0xFFFFFE1B + andi ra, ra, 0xFFFFFEC8 + sltiu sp, gp, 0x0108 + sub sp, gp, ra + slti ra, sp, 0x015D + slli sp, sp, 0x0004 + xor gp, sp, ra + srl ra, gp, ra + sltiu ra, ra, 0xFFFFFF3C + add sp, sp, sp + add gp, gp, ra + slli gp, gp, 0x0001 + andi sp, sp, 0xFFFFFF3A + slt gp, sp, gp + srli ra, sp, 0x0004 + ori sp, gp, 0xFFFFFEAB + ori sp, ra, 0xFFFFFE95 + slli sp, sp, 0x000E + xori gp, sp, 0x0040 + slti gp, sp, 0xFFFFFED1 + or sp, sp, sp + sltiu sp, gp, 0x01B4 + addi ra, gp, 0x002D + and sp, gp, gp + or ra, ra, ra + or ra, gp, ra + srli ra, ra, 0x0004 + or ra, gp, ra + sra ra, ra, gp + slli ra, gp, 0x000B + slti gp, gp, 0x00E0 + addi gp, ra, 0xFFFFFF72 + sltiu gp, sp, 0xFFFFFEAA + xor sp, ra, gp + and gp, sp, ra + srli gp, gp, 0x0003 + xori ra, ra, 0x01BD + srl ra, ra, gp + srai ra, gp, 0x0006 + sub ra, gp, sp + sll gp, ra, gp + xori ra, sp, 0x0065 + and ra, gp, ra + or ra, sp, ra + slt sp, gp, ra + addi ra, sp, 0xFFFFFE34 + slli gp, sp, 0x0007 + sll ra, sp, gp + sltiu gp, gp, 0xFFFFFE62 + slti sp, sp, 0x0019 + xori ra, gp, 0x0092 + sltiu gp, sp, 0xFFFFFF29 + srl sp, ra, gp + xori sp, gp, 0xFFFFFF4C + add sp, ra, gp + add sp, gp, ra + sra sp, sp, gp + slli sp, ra, 0x0008 + srl sp, sp, sp + add sp, gp, ra + andi sp, sp, 0x0039 + sll ra, gp, sp + andi gp, ra, 0xFFFFFECC + sll sp, sp, sp + sub sp, sp, ra + srai ra, sp, 0x0008 + xor gp, ra, sp + add sp, sp, sp + sub gp, ra, gp + xori gp, sp, 0x01EE + and ra, ra, ra + ori gp, ra, 0xFFFFFE96 + slli ra, gp, 0x0002 + srli gp, ra, 0x000D + srli sp, gp, 0x0005 + add ra, sp, sp + andi sp, gp, 0xFFFFFEC0 + andi sp, gp, 0xFFFFFE7A + xori ra, sp, 0x0169 + xori gp, sp, 0xFFFFFE02 + andi ra, ra, 0xFFFFFFD1 + xor ra, sp, gp + xori gp, gp, 0x00AB + srl ra, ra, gp + and ra, ra, sp + xori gp, sp, 0x005D + srai sp, sp, 0x000A + addi ra, sp, 0xFFFFFE19 + or sp, ra, ra + addi ra, gp, 0x0084 + ori sp, sp, 0xFFFFFF3D + xor gp, ra, gp + sra ra, ra, gp + xori ra, sp, 0x0040 + srai gp, gp, 0x0002 + xori ra, ra, 0xFFFFFE9A + sra ra, sp, sp + ori gp, sp, 0xFFFFFFB8 + sll sp, ra, ra + done #regset x1, 123 #regset x2, -40 #regset x3, 0xFFEE diff --git a/src/test/scala/TestUtils.scala b/src/test/scala/TestUtils.scala index 0a671d1..acaa741 100644 --- a/src/test/scala/TestUtils.scala +++ b/src/test/scala/TestUtils.scala @@ -75,7 +75,7 @@ object TestUtils { val entry = hasLeft + (leftIndex << 1) + (hasRight << 8) + (rightIndex << 9) + (root.value << 16) - say(s"with leftIndex: ${leftIndex.hs}, rightIndex: ${rightIndex.hs}, value: ${root.value.hs} we got ${entry.hs}") + // say(s"with leftIndex: ${leftIndex.hs}, rightIndex: ${rightIndex.hs}, value: ${root.value.hs} we got ${entry.hs}") entry :: foldAnno(root.left) ::: foldAnno(root.right) }.getOrElse(Nil) @@ -98,8 +98,8 @@ object TestUtils { */ def generateHazardsForward(steps: Int) : Unit = { - // val r = new scala.util.Random(0xF01D1EF7) - val r = new scala.util.Random(0xF01D1EF8) + val r = new scala.util.Random(0xF01D1EF7) + // val r = new scala.util.Random(0xF01D1EF8) import Ops._ val active = List(1, 2, 3) @@ -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}", 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"slli ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(math.abs(shift).toInt % 32).show}", ArithImmShift.sll(rd, rs1, math.abs(shift).toInt % 32)), + (s"srli ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(math.abs(shift).toInt % 32).show}", ArithImmShift.srl(rd, rs1, math.abs(shift).toInt % 32)), + (s"srai ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(math.abs(shift).toInt % 32).show}", ArithImmShift.sra(rd, rs1, math.abs(shift).toInt % 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) From 6fa8d3537a464cfe75c2640ee643fa092f9c1c5c Mon Sep 17 00:00:00 2001 From: peteraa Date: Wed, 4 Sep 2019 13:55:05 +0200 Subject: [PATCH 07/15] Fix nonexhaustive match causing funct3 to not be applied to imm shifts --- src/test/scala/RISCV/Ops.scala | 8 +++---- src/test/scala/RISCV/assembler.scala | 34 +++++++++++++-------------- src/test/scala/RISCV/printUtils.scala | 2 +- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/test/scala/RISCV/Ops.scala b/src/test/scala/RISCV/Ops.scala index 9158312..f77a351 100644 --- a/src/test/scala/RISCV/Ops.scala +++ b/src/test/scala/RISCV/Ops.scala @@ -98,11 +98,11 @@ object Ops { def nop = add(0, 0, 0) } - case class ArithImmShift(imm11: Imm, rd: Reg, rs1: Reg, shamt: Imm, op: ArithOp) extends Op with IType + case class ArithImmShift(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) + def sll( rd: Int, rs1: Int, imm: Int) = ArithImmShift(Reg(rd), Reg(rs1), Imm(imm), SLL) + def srl( rd: Int, rs1: Int, imm: Int) = ArithImmShift(Reg(rd), Reg(rs1), Imm(imm), SRL) + def sra( rd: Int, rs1: Int, imm: Int) = ArithImmShift(Reg(rd), Reg(rs1), Imm(imm), SRA) } case class LUI(rd: Reg, imm: Imm) extends Op with UType diff --git a/src/test/scala/RISCV/assembler.scala b/src/test/scala/RISCV/assembler.scala index 7c4f943..1f7ff49 100644 --- a/src/test/scala/RISCV/assembler.scala +++ b/src/test/scala/RISCV/assembler.scala @@ -127,15 +127,9 @@ object assembler { /** * Used by SRI, SRAI, SLLI */ - 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 setShiftTypeImmediate(shamt: Int, addr: Addr): Int => InstructionFragment = { + val points = List((24, 5)) + applyImmediateU(shamt, points, addr) } def setOpCode(opcode: Int): Int => Int = setField(0, 7, opcode) @@ -222,7 +216,7 @@ object assembler { 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: ArithImmShift => setShiftTypeImmediate(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) @@ -252,14 +246,18 @@ object assembler { val opcode = setOpCode(op) val extras: Int => Int = (instruction: Int) => op match { - case op: Branch => setComparisonFunct(op.comp)(instruction) - case op: ArithImm => setArithFunct(op.op)(instruction) - case op: Arith => setArithFunct(op.op)(instruction) - case op: JALR => setFunct3("000".binary)(instruction) - case op: LW => setFunct3("010".binary)(instruction) - case op: SW => setFunct3("010".binary)(instruction) - case DONE => (setFunct3("000".binary) andThen setFunct7("0000000".binary))(instruction) - case _ => instruction + case op: Branch => setComparisonFunct(op.comp)(instruction) + case op: ArithImm => setArithFunct(op.op)(instruction) + case op: ArithImmShift => setArithFunct(op.op)(instruction) + case op: Arith => setArithFunct(op.op)(instruction) + case op: JALR => setFunct3("000".binary)(instruction) + case op: LW => setFunct3("010".binary)(instruction) + case op: SW => setFunct3("010".binary)(instruction) + case DONE => (setFunct3("000".binary) andThen setFunct7("0000000".binary))(instruction) + + case op: AUIPC => instruction + case op: JAL => instruction + case op: LUI => instruction } val withOp = opcode(0) diff --git a/src/test/scala/RISCV/printUtils.scala b/src/test/scala/RISCV/printUtils.scala index 4c18a8a..f9d37b9 100644 --- a/src/test/scala/RISCV/printUtils.scala +++ b/src/test/scala/RISCV/printUtils.scala @@ -119,7 +119,7 @@ object PrintUtils { def printBinary(bin: Map[Addr, Int]): String = { - bin.toList.sortBy(_._1.value).map{ case(addr, op) => s"$addr: ${op.hs}" }.mkString("\n","\n","\n") + bin.toList.sortBy(_._1.value).map{ case(addr, op) => s"$addr: ${op.hs}\t--\t${op.binary}" }.mkString("\n","\n","\n") } From 27b7c0556e0168c94f9678e3371d00e3a9cd0175 Mon Sep 17 00:00:00 2001 From: peteraa Date: Thu, 5 Sep 2019 14:09:05 +0200 Subject: [PATCH 08/15] Simplify NOP and bubble logic. --- src/main/scala/IF.scala | 16 +++------------- src/main/scala/ToplevelSignals.scala | 13 ++++++++----- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/main/scala/IF.scala b/src/main/scala/IF.scala index 232442f..fc024ff 100644 --- a/src/main/scala/IF.scala +++ b/src/main/scala/IF.scala @@ -8,7 +8,7 @@ class InstructionFetch extends MultiIOModule { val testHarness = IO( new Bundle { val IMEMsetup = Input(new IMEMsetupSignals) - val PC = Output(UInt()) + val PC = Output(UInt()) } ) @@ -46,21 +46,11 @@ class InstructionFetch extends MultiIOModule { instruction := IMEM.io.instruction.asTypeOf(new Instruction) - - /** - * Setup. - * - * When you have added an instruction signal to this module you - * should ensure that it is set to NOP during program loading. - * - * If not you will end up issuing instructions during program load - * which will start executing before memory, registers and programs - * are fully loaded. + * Setup. You should not change this code. */ 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") + instruction := Instruction.NOP } } diff --git a/src/main/scala/ToplevelSignals.scala b/src/main/scala/ToplevelSignals.scala index 80a630c..fe31613 100644 --- a/src/main/scala/ToplevelSignals.scala +++ b/src/main/scala/ToplevelSignals.scala @@ -22,14 +22,17 @@ class Instruction extends Bundle(){ def immediateJType = Cat(instruction(31), instruction(19, 12), instruction(20), instruction(30, 25), instruction(24, 21), 0.U(1.W)).asSInt def immediateZType = instruction(19, 15).zext + def bubble(): Instruction = { + val bubbled = Wire(new Instruction) + bubbled.instruction := instruction + bubbled.instruction(6, 0) := BitPat.bitPatToUInt(BitPat("b0010011")) + bubbled + } } object Instruction { - def bubble(i: Instruction) = - i.opcode := BitPat.bitPatToUInt(BitPat("b0010011")) - - def default: Instruction = { + def NOP: Instruction = { val w = Wire(new Instruction) - w.instruction := 0.U + w.instruction := BitPat.bitPatToUInt(BitPat("b00000000000000000000000000010011")) w } } From 8bb3c892a10f1342db8f46fff61b2813d3ba8cd2 Mon Sep 17 00:00:00 2001 From: peteraa Date: Thu, 5 Sep 2019 14:37:33 +0200 Subject: [PATCH 09/15] Beef up add walkthrough --- exercise.org | 74 ++++++++++++++++++++++++++++++++--------- src/main/scala/IF.scala | 7 +++- 2 files changed, 65 insertions(+), 16 deletions(-) diff --git a/exercise.org b/exercise.org index c33faad..5b520bd 100644 --- a/exercise.org +++ b/exercise.org @@ -8,12 +8,22 @@ This is done by inserting 4 NOP instructions inbetween each source instruction, enabling us to use the same tests for both exercise 1 and 2. - In the project skeleton files ([[./src/main/scala/][Found here]]) you can see that a lot of code has - already been provided. + already been provided, which can make it difficult to get started. + Hopefully this document can help clear up at least some of the confusion. + First an overview of what you are designing is presented, followed by a walk-through + for getting the most basic instructions to work. + + In order to orient yourself you first need a map, thus a high level overview of the + processor you're going to design is showed underneath: + Keep in mind that this is just a high level sketch, omitting many details as well + entire features (for instance branch logic) + + #+CAPTION: A very high level processor schematic. Registers, Instruction and data memory are already implemented. + [[./Images/FiveStage.png]] - Before going further it is useful to get an overview of what is provided out - of the box. + Now that you have an idea of what you're building it is time to take inventory of + the files included in the skeleton, and what, if anything should be added. + [[./src/main/scala/Tile.scala]] This is the top level module for the system as a whole. This is where the test @@ -26,7 +36,11 @@ should be declared and wired together. Some of these modules have already been declared in order to wire up the debugging logic for your test harness. + This file corresponds to the high-level overview in its entirety. *This module is intended to be further fleshed out by you.* + As you work with this module, try keeping logic to a minimum to help readability. + If you end up with a lot of signal select logic, consider moving that to a separate + module. + [[./src/main/scala/IF.scala]] This is the instruction fetch stage. @@ -94,10 +108,11 @@ of these settings can be quite useful to alter. The main attraction is the test options. By altering the verbosity settings you may change what is output. - The settings are + The settings are: + printIfSuccessful - Enables logging on tests that succeed + Enables logging on tests that succeed. + You typically want this turned off, at least for the full test runner. + printErrors Enables logging of errors. You obviously want this one on, at least on the single @@ -147,6 +162,12 @@ In your sketch you will eventually add a box for registers, IMEM and DMEM, which should make it clear how the already finished modules fit into the grander design, making the skeleton-code less mysterious. + + To give you an idea of how a drill down looks like, here is my sketch of the ID stage: + #+CAPTION: Instruction decode stage, showing the various signals. + [[./Images/IDstage.png]] + + I would generally advice to do these on paper, but don't half-ass them. ** Adding numbers @@ -174,11 +195,11 @@ **** Step ¾: In your console, type ~testOnly FiveStage.SingleTest~ to run only the tests that you - have defined in the [[./src/test/scala/Manifest.scala][test manifest]] (currently set to ~"forward2.s"~). + have defined in the [[./src/test/scala/Manifest.scala][test manifest]] (currently set to ~forward2.s~). As you will first implement addition you should change this to the [[./src/test/resources/tests/basic/immediate/addi.s][add immediate test]]. - Luckily you do not have to deal with file paths, simply changing ~"forward2.s"~ to - ~"addi.s"~ suffices. + Luckily you do not have to deal with file paths, simply changing ~forward2.s~ to + ~addi.s~ suffices. Ensure that the addi test is run by repeating the ~testOnly FiveStage.SingleTest~ command. @@ -188,7 +209,7 @@ In [[./src/test/main/IF.scala]] you can see that the IMEM module is already set to fetch the current program counter address (line 41), however since the current PC is stuck at 0 it will fetch the same instruction over and over. Rectify this by commenting in - ~// PC := PC + 4.U~ at line 43. + ~// PC := PC + 4.U~ at line 48. You can now verify that your design fetches new instructions each cycle by running the test as in the previous step. @@ -207,10 +228,10 @@ Next you need to ensure that the registers and decoder gets the relevant data from the instruction. - This is made more convenient by the fact that `Instruction` is a class, allowing you + This is made more convenient by the fact that ~Instruction~ is a class, allowing you to access methods defined on it. - Keep in mind that it is only a class at compile and synthesis time, it will be - indistinguishable from a regular ~UIint(32.W)~ in your finished circuit. + Keep in mind that it is only a class during compile and build time, it will be + indistinguishable from a regular ~UInt(32.W)~ in your finished circuit. The methods can be accessed like this: #+BEGIN_SRC scala // Drive funct6 of myModule with the 26th to 31st bit of instruction @@ -221,7 +242,21 @@ Your IF should now have an instruction as an OUTPUT, and your ID as an INPUT, however they are not connected. This must be done in the CPU class where both the ID and IF are instantiated. - + In the overview sketch you probably noticed the barriers between IF and ID. + In accordance with the overview, it is incorrect to directly connect the two modules, + instead you must connect them using a *barrier*. + A barrier is responsible for keeping a value inbetween cycles, facilitating pipelining. + There is however one complicating matter: It takes a cycle to get the instruction from the + instruction memory, thus we don't want to delay it in the barrier! + + In order to make code readable I suggest adding a new file for your barriers, containing + four different modules for the barriers your design will need. + + Start with implementing your IF barrier module, which should contain the following: + + An input and output for PC where the output is delayed by a single cycle. + + An input and output for instruction where the output is wired directly to the input with + no delay. + **** Step 4½: You should now verify that the correct control signals are produced. Using printf, ensure that: @@ -250,10 +285,19 @@ // MuxLookup API: https://github.com/freechipsproject/chisel3/wiki/Muxes-and-Input-Selection#muxlookup io.aluResult := MuxLookup(io.aluOp, 0.U(32.W), ALUopMap) #+END_SRC + + As with the ID stage, you will need a barrier between ID and EX stage. + In this case, as the overview sketch indicates, all values should be delayed one cycle. + + When you have finished the barrier, instantiate it and wire ID and EX together with the barrier in the + same fashion as IF and ID. *** Step 6: Your MEM stage does very little when an ADDI instruction is executed, so implementing it should - be easy. All you have to do is forward signals + be easy. All you have to do is forward signals. + + From the overview sketch you can see that the same trick used in the IF/ID barrier is utilized + here, bypassing the data memory read value since it is already delayed by a cycle. *** Step 7: You now need to actually write the result back to your register bank. diff --git a/src/main/scala/IF.scala b/src/main/scala/IF.scala index fc024ff..b4bb4ab 100644 --- a/src/main/scala/IF.scala +++ b/src/main/scala/IF.scala @@ -14,7 +14,12 @@ class InstructionFetch extends MultiIOModule { /** - * TODO: Add signals for handling events such as jumps + * TODO: Add input signals for handling events such as jumps + + * TODO: Add output signal for the instruction. + * The instruction is of type Bundle, which means that you must + * use the same syntax used in the testHarness for IMEM setup signals + * further up. */ val io = IO( new Bundle { From d0b5c15ceca818b53b8f5bf5ccdf79d5a1adf853 Mon Sep 17 00:00:00 2001 From: peteraa Date: Thu, 5 Sep 2019 14:38:38 +0200 Subject: [PATCH 10/15] Add images --- Images/FiveStage.png | Bin 0 -> 87541 bytes Images/IDstage.png | Bin 0 -> 64230 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Images/FiveStage.png create mode 100644 Images/IDstage.png diff --git a/Images/FiveStage.png b/Images/FiveStage.png new file mode 100644 index 0000000000000000000000000000000000000000..cc6b5b0149828efc9b8acb50b9809567f12332f1 GIT binary patch literal 87541 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 u{Ni61{FA%?mywnH=413~*bSeEZ|b#b5!u(Qwr literal 0 HcmV?d00001 From 1e12cb363e839fb9fd12fbbd30309448e47ec17b Mon Sep 17 00:00:00 2001 From: peteraa Date: Thu, 5 Sep 2019 15:09:39 +0200 Subject: [PATCH 11/15] More images and details in add walkthrough. --- Images/IFID.png | Bin 0 -> 6759 bytes exercise.org | 11 +++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 Images/IFID.png diff --git a/Images/IFID.png b/Images/IFID.png new file mode 100644 index 0000000000000000000000000000000000000000..b9fdb57b44976dff00138ff2123ca109917325eb GIT binary patch literal 6759 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 Date: Thu, 5 Sep 2019 17:29:50 +0200 Subject: [PATCH 12/15] Add description for merged trace --- instructions.org | 2 ++ src/test/scala/RISCV/printUtils.scala | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/instructions.org b/instructions.org index e323c7c..c4c9ea0 100644 --- a/instructions.org +++ b/instructions.org @@ -2,6 +2,8 @@ 4.2. Register-Register Arithmetic Instructions -------------------------------------------------------------------------- +These do not render well on github, try using your text editor. + * ADD - Summary : Addition with 3 GPRs, no overflow exception diff --git a/src/test/scala/RISCV/printUtils.scala b/src/test/scala/RISCV/printUtils.scala index f9d37b9..58adefa 100644 --- a/src/test/scala/RISCV/printUtils.scala +++ b/src/test/scala/RISCV/printUtils.scala @@ -347,7 +347,8 @@ object PrintUtils { def printLogSideBySide(trace: List[ExecutionTraceEvent], chiselTrace: List[CircuitTrace], program: Program): String = { import LogParser._ + val header = "ADDRESS -- VM UPDATES --- DEVICE UNDER TEST UPDATES --- CORRESPONDING SOURCE LINE\n" val traces = mergeTraces(trace, chiselTrace).map(x => printMergedTraces((x), program)) - traces.map(_.mkString("\n")).mkString("\n", "\n--------------------------------------------------------------------------+------------------------------------------------------+-------------------------------\n", "\n") + "\n" + header + (traces.map(_.mkString("\n")).mkString("\n", "\n--------------------------------------------------------------------------+------------------------------------------------------+-------------------------------\n", "\n")) } } From c82013581d66ab6e67c58eb124b3fff8bd99d605 Mon Sep 17 00:00:00 2001 From: peteraa Date: Thu, 5 Sep 2019 19:18:40 +0200 Subject: [PATCH 13/15] Add ex2 text. Remove unused file. --- Images/MEMstage.png | Bin 0 -> 25026 bytes exercise.org | 7 ++- exercise2.org | 109 ++++++++++++++++++++++++++++++++++ src/test/scala/testConf.scala | 43 -------------- 4 files changed, 114 insertions(+), 45 deletions(-) create mode 100644 Images/MEMstage.png create mode 100644 exercise2.org delete mode 100644 src/test/scala/testConf.scala diff --git a/Images/MEMstage.png b/Images/MEMstage.png new file mode 100644 index 0000000000000000000000000000000000000000..8abb4431527cb23abb6b5328f6f13f70dfad8006 GIT binary patch literal 25026 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 literal 0 HcmV?d00001 diff --git a/exercise.org b/exercise.org index 3bbd8ed..a5459e3 100644 --- a/exercise.org +++ b/exercise.org @@ -1,4 +1,4 @@ -* Exercise 1 +* Exercise description The task in this exercise is to implement a 5-stage pipelined processor for the [[./instructions.org][RISCV32I instruction set]]. @@ -6,7 +6,10 @@ at a time, whereas in exercise 2 your design will handle multiple instructions at a time. This is done by inserting 4 NOP instructions inbetween each source instruction, - enabling us to use the same tests for both exercise 1 and 2. + enabling us to use the same tests and harness for both exercise 1 and 2. + + Once you are done with exercise 1, you can up the difficulty by setting nopPad + to false and start reading the [[exercise2.org][ex2 guide]]. In the project skeleton files ([[./src/main/scala/][Found here]]) you can see that a lot of code has already been provided, which can make it difficult to get started. diff --git a/exercise2.org b/exercise2.org new file mode 100644 index 0000000..f62c7fb --- /dev/null +++ b/exercise2.org @@ -0,0 +1,109 @@ +* Exercise 2 + Safety wheels are now officially off. + To verify this, set nopPadded to false in Manifest.scala and observe as all hell + breaks loose. + + Let's break down what's going wrong and what we can do about it. + +** RAW Hazards + Consider the following program: + #+begin_src asm + main: + add x1, x1, x2 + add x1, x1, x1 + add x1, x1, x2 + #+end_src + + In your implementation this will give you wrong results since the results + of the first add operation will not be available in the registers before + x1 is fetched for the second and third operation. + + Your first task should therefore be to implement a forwarding unit + + The forwarding unit is located in the EX stage and is responsible for selecting + the ALU input from three possible sources. + These sources are: + + The value received from the register bank + + The ALU result currently in MEM + + The writeback result + + The forwarder prioritizes as follows: + + If the input register address is not the destination in either MEM or WB, select the + register. + + If the input register address is the destination register in WB, but not in MEM, select + the writeback signal. + + If the input register address is the destination register for the operation currently + in MEM, select that operation. + + There is a special case you need take into account, namely load operations. + Considering the following program: + #+begin_src asm + main: + lw x1, 0(x2) + add x1, x1, x1 + add x1, x1, x1 + #+end_src + + When the second operation (~add x1, x1, x1~) is in EX, the third clause in the forwarder + is triggered, however the result is not yet ready since fetching memory costs a cycle. + In order to fix this the forwarder must issue a signal that freezes the pipeline. + This is done by issuing a signal to the barrier registers, telling them to _not_ update + their contents, essentially repeating the last instruction. + + There are many subtleties to consider here. + For instance: What should happen to the instruction currently + in MEM? If it too is repeated the hazard detector will trigger next cycle, effectively + deadlocking your processor. + What about when the write address and read address are similar in the ID stage? + + Designing a forwarder can take very long, or it can be done very quickly, all depending + on how *methodical* you are. My advice is to design the algorithm first, then when you're + satisfied implement it on hardware. + + +** Control hazards + + Consider the following code + + #+begin_src asm + main: + beq zero, zero, target + add x1, x1, x1 + add x1, x1, x1 + j main + target: + sub x1, x2, x2 + sub x2, x2, x2 + #+end_src + + Depending on your design the two add instructions will be fetched before the beq jump happens. + Whenever a branch happens it is necessary to flush the spurious instructions that were fetched + before the branch was noticed. + However, simply waiting until the branch has been decided is not acceptable since that guarantees + lost cycles. + In your first iteration, simply assume branches will not be taken, and if they are taken issue + a warning to the barriers that hold spurious instructions telling them to render them impotent + by setting the control signals to do nothing. + +* Putting the pedal to the metal + Once you have a design that RAW and control hazards you're ready to up the ante and add some + improvements to your design. + Some suggestions: + +** Branch predictor + Instead of assuming branch not taken, use a branch predictor. There are many different schemes, + but I advice you to stick to a simple one, such as 1-bit or 2-bit. + +** Fast branch handling + Certaing branches like BEQ and BNE can be calculated very quickly, wheras size comparison branches + (BGE, BLE and friends) take longer. It is therefore feasible to do these checks in the ID stage. + +** Adding a data cache + Unless you have already done the two suggested improvements, do not attempt to create a cache. + The first thing you need to do is to add a latency for memory fetching, if not you will have + nothing to improve upon. + + If you still insist, start with the BTreeManyO3.s program and analyze the memory access pattern. + What sort of eviction policy and cache size would you choose for this pattern? + You should try writing additional benchmarking programs, it is important to have something measurable, + and the current programs are not made to test cache performance!! diff --git a/src/test/scala/testConf.scala b/src/test/scala/testConf.scala deleted file mode 100644 index 721cc38..0000000 --- a/src/test/scala/testConf.scala +++ /dev/null @@ -1,43 +0,0 @@ -// package FiveStage -// import chisel3._ -// import chisel3.iotesters._ -// import org.scalatest.{Matchers, FlatSpec} -// import spire.math.{UInt => Uint} -// import fileUtils._ -// import cats.implicits._ - -// import RISCVutils._ -// import RISCVasm._ -// import riscala._ - -// import utilz._ - -// class AllTests extends FlatSpec with Matchers { - -// val results = fileUtils.getAllTests.map{f => -// val result = TestRunner.runTest(f.getPath, false) -// (f.getName, result) -// } - -// makeReport(results) -// } - - -// /** -// This is for you to run more verbose testing. -// */ -// class SelectedTests extends FlatSpec with Matchers { - -// val tests = List( -// "matMul.s" -// ) - -// if(!tests.isEmpty){ -// val results = fileUtils.getAllTests.filter(f => tests.contains(f.getName)).map{ f => -// val result = TestRunner.runTest(f.getPath, true) -// (f.getName, result) -// } - -// makeReport(results) -// } -// } From 2f2f20c0753038aa028f02df1e5774153712102a Mon Sep 17 00:00:00 2001 From: peteraa Date: Fri, 6 Sep 2019 13:55:47 +0200 Subject: [PATCH 14/15] Fix AUIPC/LUI opcode mismatch. --- src/test/scala/RISCV/assembler.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/scala/RISCV/assembler.scala b/src/test/scala/RISCV/assembler.scala index 1f7ff49..876ef49 100644 --- a/src/test/scala/RISCV/assembler.scala +++ b/src/test/scala/RISCV/assembler.scala @@ -149,8 +149,8 @@ object assembler { 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 x: AUIPC => setOpCode("0010111".binary) + case x: LUI => setOpCode("0110111".binary) case DONE => setOpCode("0010011".binary) // done is turned into a NOP in the assembler. } From ae995a7b55c0bcc1802669ccdf8451ff3a81238f Mon Sep 17 00:00:00 2001 From: peteraa Date: Fri, 6 Sep 2019 14:44:01 +0200 Subject: [PATCH 15/15] Fix hex | int parse issue. Correctly handle li --- src/test/scala/RISCV/DataTypes.scala | 13 +++++------ src/test/scala/RISCV/Parser.scala | 32 +++++++++++++++------------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/test/scala/RISCV/DataTypes.scala b/src/test/scala/RISCV/DataTypes.scala index 12e91c2..180e854 100644 --- a/src/test/scala/RISCV/DataTypes.scala +++ b/src/test/scala/RISCV/DataTypes.scala @@ -158,12 +158,13 @@ object Data { rightShifted } - def splitLoHi(loBits: Int): (Int, Int) = { - val hiBits = 32 - loBits - val sep = 31 - loBits - val lo = i.field(31, loBits) - val hi = i.field(sep, hiBits) - (lo, hi) + def splitHiLo(hiBits: Int): (Int, Int) = { + val loBits = 32 - hiBits + val sep = 31 - hiBits + val hi = i.field(31, hiBits) + val lo = i.field(sep, loBits) + say(s"split lo hi for $i with $hiBits high bits and got low: $lo, high: $hi") + (hi, lo) } def log2: Int = math.ceil(math.log(i.toDouble)/math.log(2.0)).toInt diff --git a/src/test/scala/RISCV/Parser.scala b/src/test/scala/RISCV/Parser.scala index c00bcd2..50da76d 100644 --- a/src/test/scala/RISCV/Parser.scala +++ b/src/test/scala/RISCV/Parser.scala @@ -98,8 +98,11 @@ object Parser { // seqz rd, rs1 => sltiu rd, rs1, 1 stringWs("seqz") ~> (reg <~ sep, reg, ok(1)).mapN{ArithImm.sltu}, - stringWs("li") ~> (reg ~ sep ~ int).collect{ - case((a, b), c) if (c.nBitsS <= 12) => ArithImm.add(a, 0, c) + stringWs("li") ~> (reg ~ sep ~ (hex | int)).collect{ + case((a, b), c) if (c.nBitsS <= 12) => { + say(s"for c: $c, nBitsS was ${c.nBitsS}") + ArithImm.add(a, 0, c) + } }, @@ -122,16 +125,16 @@ object Parser { //////////////////////////////////////////// //// load/store - stringWs("sw") ~> (reg <~ sep, int <~ char('('), reg <~ char(')')).mapN{case (rs2, offset, rs1) => SW(rs2, rs1, offset)}, - stringWs("lw") ~> (reg <~ sep, int <~ char('('), reg <~ char(')')).mapN{case (rd, offset, rs1) => LW(rd, rs1, offset)}, + stringWs("sw") ~> (reg <~ sep, (hex | int) <~ char('('), reg <~ char(')')).mapN{case (rs2, offset, rs1) => SW(rs2, rs1, offset)}, + stringWs("lw") ~> (reg <~ sep, (hex | int) <~ char('('), reg <~ char(')')).mapN{case (rd, offset, rs1) => LW(rd, rs1, offset)}, //////////////////////////////////////////// //// others - stringWs("auipc") ~> (reg <~ sep, int).mapN{AUIPC.apply}, - stringWs("lui") ~> (reg <~ sep, int).mapN{LUI.apply}, + stringWs("auipc") ~> (reg <~ sep, (hex | int)).mapN{AUIPC.apply}, + stringWs("lui") ~> (reg <~ sep, (hex | int)).mapN{LUI.apply}, many(whitespace) ~> string("nop") ~> ok(Arith.add(0, 0, 0)), many(whitespace) ~> string("done") ~> ok(DONE), @@ -140,19 +143,18 @@ object Parser { ).map(_.widen[Op]).reduce(_|_) - // def getShiftsHalfWord(offset: Int): (Int, Int) = (offset % 4) match { - // case 0 => (16, 16) - // case 1 => ( - // } - val multipleInstructions: Parser[List[Op]] = List( - stringWs("li") ~> (reg <~ sep, int.map(_.splitLoHi(12))).mapN{ case(rd, (lo, hi)) => List( + // stringWs("li") ~> (reg <~ sep, (hex | int).map(_.splitLoHi(20))).mapN{ case(rd, (hi, lo)) => { + stringWs("li") ~> (reg <~ sep, (hex | int).map(_.splitHiLo(20))).mapN{ case(rd, (hi, lo)) => { + say("hello?") + List( + ArithImm.add(rd, rd, lo), LUI(rd, hi), - ArithImm.add(rd, 0, lo) - )}.map(_.widen[Op]), + )}}.map(_.widen[Op]), - // NOTE: THESE ARE NOT PSEUDO-OPS IN RISV32I! + // NOTE: THESE ARE NOT PSEUDO-OPS IN RISC-V32I! // NOTE: USES A SPECIAL REGISTER + // NOTE: PROBABLY BROKEN, NOT EXHAUSTIVELY TESTED!!! stringWs("lh") ~> (reg <~ sep, int <~ char('('), reg <~ char(')')).mapN{ case (rd, offset, rs1) if (offset % 4 == 3) => { val placeHolder = if(rd == Reg("a0").value) Reg("a1").value else Reg("a0").value