diff --git a/.gitignore b/.gitignore index 66650aa..b1e1cc2 100644 --- a/.gitignore +++ b/.gitignore @@ -341,4 +341,15 @@ project/plugins/project/ hs_err_pid* *.fir -*.json \ No newline at end of file +*.json + +# ENSIME, metals and friends +.ensime* +.metals* +.bloop* +.projectile +target/ +scratchpad.scala +log/ +TODO.org +index.html \ No newline at end of file diff --git a/TODOs.org b/TODOs.org index 3270ed6..979caf9 100644 --- a/TODOs.org +++ b/TODOs.org @@ -1,26 +1,6 @@ -* Thoughts - For RISC-V bruk SODOR, finn på chisel sia - -* Doing - Finn ut hvordan bundles, defs etc burde fungere. - -* Now -** DONE Port Babby to chisel3 -*** DONE compile and run -*** DONE fix deprecation - -** TODO Software test suite POC - -* Later -** TODO Set up folder structure -** TODO Figure out how to run tests - -* Milestones -** TODO Øving 0 -** TODO Hardware test suite POC -** TODO Finalize Øving 0 -** TODO Øving 1 -** TODO Øving 2 + +* Points +** * Tutorials https://github.com/ucb-bar/generator-bootcamp diff --git a/ov0/build.sbt b/build.sbt similarity index 74% rename from ov0/build.sbt rename to build.sbt index 5113555..2786bc3 100644 --- a/ov0/build.sbt +++ b/build.sbt @@ -46,8 +46,23 @@ val defaultVersions = Map( libraryDependencies ++= (Seq("chisel3","chisel-iotesters").map { dep: String => "edu.berkeley.cs" %% dep % sys.props.getOrElse(dep + "Version", defaultVersions(dep)) }) +val versionOfScala = "2.12.4" + +val fs2Version = "0.10.3" +val catsVersion = "1.1.0" +val catsEffectVersion = "0.10" +libraryDependencies ++= Dependencies.backendDeps.value scalacOptions ++= scalacOptionsVersion(scalaVersion.value) scalacOptions ++= Seq("-language:reflectiveCalls") javacOptions ++= javacOptionsVersion(scalaVersion.value) +// testOptions in Test += Tests.Argument("-oF") + +resolvers += Resolver.sonatypeRepo("releases") +addCompilerPlugin("org.spire-math" %% "kind-projector" % "0.9.7") +addCompilerPlugin("com.olegpy" %% "better-monadic-for" % "0.2.4") +addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full) + + +testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "-eS") diff --git a/oppgavetekst.org b/oppgavetekst.org index bb0d93d..fdcc67e 100644 --- a/oppgavetekst.org +++ b/oppgavetekst.org @@ -4,122 +4,578 @@ In this exercise you will implement a circuit capable of performing matrix matrix multiplication in the chisel hardware description language. - HAND IN YOUR CODE IN AN ARCHIVE WITH YOUR USERNAME (e.g peteraa_ex0). - PLEASE ENSURE THAT WHEN UNZIPPING THE TESTS CAN BE RUN. +* Prerequisites + You should have some idea of how digital logic circuits work. + +* Terms + Before delving into code it's necessary to define some terms. + + + Wire + A wire is a bundle of 1 to N condictive wires (yes, that is a recursive + definition, but I think you get what I mean). These wires are connected + either to ground or a voltage source, corresponding to 0 or 1, which + is useful for representing numbers + + We can define a wire consisting of 4 physical wires in chisel like this + #+begin_src scala + val myWire = Wire(UInt(4.W)) + #+end_src + + + Driving + A wire in on itself is rather pointless since it doesn't do anything. + In order for something to happen we need to connect them. + #+begin_src scala + val wireA = Wire(UInt(4.W)) + val wireB = Wire(UInt(4.W)) + wireA := 2.U + wireB := wireA + #+end_src + Here wireA is driven by the signal 2.U, and wireB is driven by wireA. + + For well behaved circuits it does not make sense to let a wire be driven + by multiple sources which would make the resulting signal undefined + (maybe it makes sense for a javascript processor, I hear they love undefined) + + Similarily a circular dependency is not allowed a la + #+begin_src scala + val wireA = Wire(UInt(4.W)) + val wireB = Wire(UInt(4.W)) + wireA := wireB + wireB := wireA + #+end_src + + + Module + In order to make development easier we separate functionality into modules, + defined by its inputs and outputs. + + + Combinatory circuit + A combinatory circuit is a circuit whose output is based only on its + inputs. + + + Stateful circuit + A circuit that will give different results based on its internal state. + In common parlance, a circuit without registers (or memory) is combinatory + while a circuit with registers is stateful. + + + Chisel Graph + A chisel program is a program whose result is a graph which can be synthesized + to a transistor level schematic of a logic circuit. + When connecting wires wireA and wireB we were actually manipulating a graph + (actually, two subgraphs that were eventually combined into one). + The chisel graph is directed, but it does allow cycles so long as they are not + combinatorial. * Your first component - There are two types of digital components: Combinatorial and stateful. The first component we will consider is a simple combinatorial incrementor: #+begin_src scala - class myIncrement(incrementBy: Int) extends Module { - val io = IO( - new Bundle { - val dataIn = Input(UInt(32.W)) - val dataOut = Output(UInt(32.W)) - } - ) + // These will be omitted in further examples + package Ex0 + import chisel3._ - io.dataOut := io.dataIn + incrementBy.U - #+end_src - - Let's break the code down down. First, myIncrement is a Module, meaning that - this class can be instantiated as a hardware circuit. - Figure [rm3] shows the model that you have just declared. - A 32 bit signal, data_in goes in, and another 32 bit signal goes out. + class myIncrement(incrementBy: Int) extends Module { + val io = IO( + new Bundle { + val dataIn = Input(UInt(32.W)) + val dataOut = Output(UInt(32.W)) + } + ) - Apart from the IO, there is only one statement, assigning dataOut to dataIn + - incrementBy. + io.dataOut := io.dataIn + incrementBy.U + } + #+end_src - In RTL the component looks like fig [rm4] + TODO: Fig Let's see how we can use our module: #+begin_src scala - class myIncrementTwice(incrementBy: Int) extends Module { - val io = IO( - new Bundle { - val dataIn = Input(UInt(32.W)) - val dataOut = Output(UInt(32.W)) - } - ) + class myIncrementTwice(incrementBy: Int) extends Module { + val io = IO( + new Bundle { + val dataIn = Input(UInt(32.W)) + val dataOut = Output(UInt(32.W)) + } + ) + + val first = Module(new myIncrement(incrementBy)) + val second = Module(new myIncrement(incrementBy)) + + first.io.dataIn := io.dataIn + second.io.dataIn := first.io.dataOut + + io.dataOut := second.io.dataOut + } + #+end_src + - val first = Module(new myIncrement(incrementBy)) - val second = Module(new myIncrement(incrementBy)) +* Scala and chisel + The code for these snippets can be found in Example.scala in the test directory. + You can run them using sbt by running ./sbt in your project root which will open + your sbt console. - first.io.dataIn := io.dataIn - second.io.dataIn := first.io.dataOut + A major stumbling block for learning chisel is understanding the difference between scala and chisel. + To highlight the difference between the two consider how HTML is generated. - io.dataOut := second.io.dataOut + When creating a list we could just write the HTML manually + #+begin_src html + + #+end_src + + However this is rather cumbersome, so we generate HTML programatically. + In scala we might do something (sloppy) like this: + #+begin_src scala + def generateList(politicians: List[String], affiliations: Map[String, String]): String = { + val inner = new ArrayBuffer[String]() + for(ii <- 0 until politicians.size){ + val nameString = politicians(ii) + val affiliationString = affiliations(nameString) + inner.add(s"
  • Name: $nameString, Affiliation: $affiliationString
  • ") } + "" + } + + // Or if you prefer brevity + def generateList2(politicians: List[String], affiliations: Map[String, String]): String = { + val inner = politicians.map(p => s"
  • Name: $p, Affiliation ${affiliations(p)}
  • ") + "" + } #+end_src - Fig [rm5] shows the RTL design, as expected it's just two incrementors - chained. + Similarily we can use constructs such as for loops to manipulate the chisel graph: - The following code shows off how you can use for loops to instantiate an - arbitrary amount of modules. #+begin_src scala - class myIncrementN(incrementBy: Int, numIncrementors: Int) extends Module { - val io = IO( - new Bundle { - val dataIn = Input(UInt(32.W)) - val dataOut = Output(UInt(32.W)) - } - ) - - val incrementors = Array.fill(numIncrementors){ Module(new myIncrement(incrementBy)) } - - for(ii <- 1 until numIncrementors){ - incrementors(ii).io.dataIn := incrementors(ii - 1).io.dataOut + class myIncrementN(incrementBy: Int, numIncrementors: Int) extends Module { + val io = IO( + new Bundle { + val dataIn = Input(UInt(32.W)) + val dataOut = Output(UInt(32.W)) } - - incrementors(0).io.dataIn := io.dataIn - io.dataOut := incrementors(numIncrementors).io.dataOut + ) + + val incrementors = Array.fill(numIncrementors){ Module(new myIncrement(incrementBy)) } + + for(ii <- 1 until numIncrementors){ + incrementors(ii).io.dataIn := incrementors(ii - 1).io.dataOut } + + incrementors(0).io.dataIn := io.dataIn + io.dataOut := incrementors(numIncrementors).io.dataOut + } #+end_src Keep in mind that the for-loop only exists at design time, just like a for loop generating a table in HTML will not be part of the finished HTML. - So, what does combinatorial mean? - To answer that, let's create a stateful circuit first. + + *Important!* + In the HTML examples differentiating the HTML and scala was easy because they're + fundamentally very different. However with hardware and software there is a much + larger overlap. + A big pitfall is vector types and indexing, since these make sense both in software + and in hardware. + + Here's a rather silly example highligthing the confusion: + #+begin_src scala + class MyVector() extends Module { + val io = IO( + new Bundle { + val idx = Input(UInt(32.W)) + val out = Output(UInt(32.W)) + } + ) + + val values = List(1, 2, 3, 4) + io.out := values(io.idx) + } + #+end_src + + If you try to compile this you will get an error. + + #+begin_src scala + sbt:chisel-module-template> compile + ... + [error] found : chisel3.core.UInt + [error] required: Int + [error] io.out := values(io.idx) + [error] ^ + #+end_src + + This error tells us that io.idx was of the wrong type, namely a chisel UInt. + The List is a scala construct, it only exists when your design is synthesized, so + attempting to index using a chisel type would be like HTML attempting to index the + generating scala code which is nonsensical. + Let's try again: + + #+begin_src scala + class MyVector() extends Module { + val io = IO( + new Bundle { + val idx = Input(UInt(32.W)) + val out = Output(UInt(32.W)) + } + ) + + // val values: List[Int] = List(1, 2, 3, 4) + val values = Vec(1, 2, 3, 4) + + io.out := values(io.idx) + } + #+end_src + + Egads, now we get this instead + #+begin_src scala + [error] /home/peteraa/datateknikk/TDT4255_EX0/src/main/scala/Tile.scala:30:16: inferred type arguments [Int] do not conform to macro method apply's type parameter bounds [T <: chisel3.Data] + [error] val values = Vec(1, 2, 3, 4) + [error] ^ + [error] /home/peteraa/datateknikk/TDT4255_EX0/src/main/scala/Tile.scala:30:20: type mismatch; + [error] found : Int(1) + [error] required: T + [error] val values = Vec(1, 2, 3, 4) + ... + #+end_src + + What is going wrong here? In the error message we see that the type Int cannot be constrained to a + type T <: chisel3.Data, but what does that mean? + + The <: symbol means subtype, meaning that the compiler expected the Vec to contain a chisel data type + such as chisel3.Data.UInt or chisel3.Data.Boolean, and Int is not one of them! + + A scala int represent 32 bits in memory, whereas a chisel UInt represents a bundle of wires that we + interpret as an unsigned integer, thus they are not interchangeable although they represent roughly + the same thing. + + Let's fix this #+begin_src scala - class myDelay() extends Module { - val io = IO( - new Bundle { - val dataIn = Input(UInt(32.W)) - val dataOut = Output(UInt(32.W)) - } + class MyVector() extends Module { + val io = IO( + new Bundle { + val idx = Input(UInt(32.W)) + val out = Output(UInt(32.W)) + } + ) + + val values = Vec(1.U, 2.U, 3.U, 4.U) + + // Alternatively + // val values = Vec(List(1, 2, 3, 4).map(scalaInt => UInt(scalaInt))) + + io.out := values(io.idx) + } + #+end_src + + This works! + So, it's impossible to access scala collections with chisel types, but can we do it the other way around? + + #+begin_src scala + class MyVector() extends Module { + val io = IO( + new Bundle { + val idx = Input(UInt(32.W)) + val out = Output(UInt(32.W)) + } + ) + + val values = Vec(1.U, 2.U, 3.U, 4.U) + + io.out := values(3) + } + #+end_src + + ...turns out we can? + This is nonsensical, however thanks to behind the scenes magic the 3 is changed + to 3.U, much like [] can be a boolean in javascript. + + + To get acquainted with the (rather barebones) testing environment, let's test this. + #+begin_src scala + class MyVecSpec extends FlatSpec with Matchers { + behavior of "MyVec" + + it should "Output whatever idx points to" in { + wrapTester( + chisel3.iotesters.Driver(() => new MyVector) { c => + new MyVecTester(c) + } should be(true) ) - val delayReg = RegInit(UInt(32.W), 0.U) + } + } + + + class MyVecTester(c: MyVector) extends PeekPokeTester(c) { + for(ii <- 0 until 4){ + poke(c.io.idx, ii) + expect(c.io.out, ii) + } + } + #+end_src + + #+begin_src + sbt:chisel-module-template> testOnly Ex0.MyVecSpec + ... + ... + [info] Compiling 1 Scala source to /home/peteraa/datateknikk/TDT4255_EX0/target/scala-2.12/test-classes ... + ... + ... + MyVecSpec: + MyVec + [info] [0.001] Elaborating design... + ... + Circuit state created + [info] [0.001] SEED 1556197694422 + test MyVector Success: 4 tests passed in 5 cycles taking 0.009254 seconds + [info] [0.002] RAN 0 CYCLES PASSED + - should Output whatever idx points to + Run completed in 605 milliseconds. + Total number of tests run: 1 + Suites: completed 1, aborted 0 + Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0 + All tests passed. + #+end_src + + Great! + +* Compile time and synthesis time + In the HTML example, assume that we omitted the last tag. This would not + create valid HTML, however the code will happily compile. Likewise, we can easily + create invalid chisel: + + #+begin_src scala + class Invalid() extends Module { + val io = IO(new Bundle{}) + + val myVec = Module(new MyVector) + } + #+end_src + + This code will happily compile! + Turns out that when compiling, we're not actually generating any chisel at all! + Let's create a test that builds chisel code for us: + + #+begin_src scala + class InvalidSpec extends FlatSpec with Matchers { + behavior of "Invalid" + + it should "Probably fail in some sort of way" in { + chisel3.iotesters.Driver(() => new Invalid) { c => + + // chisel tester expects a test here, but we can use ??? + // which is shorthand for throw new NotImplementedException. + // + // This is OK, because it will fail during building. + ??? + } should be(true) + } + } + #+end_src + + This gives us the rather scary error: - delayReg := io.dataIn - io.dataOut := delayReg + #+begin_src scala + sbt:chisel-module-template> compile + ... + [success] Total time: 3 s, completed Apr 25, 2019 3:15:15 PM + ... + sbt:chisel-module-template> testOnly Ex0.InvalidSpec + ... + firrtl.passes.CheckInitialization$RefNotInitializedException: @[Example.scala 25:21:@20.4] : [module Invalid] Reference myVec is not fully initialized. + : myVec.io.idx <= VOID + at firrtl.passes.CheckInitialization$.$anonfun$run$6(CheckInitialization.scala:83) + at firrtl.passes.CheckInitialization$.$anonfun$run$6$adapted(CheckInitialization.scala:78) + at scala.collection.TraversableLike$WithFilter.$anonfun$foreach$1(TraversableLike.scala:789) + at scala.collection.mutable.HashMap.$anonfun$foreach$1(HashMap.scala:138) + at scala.collection.mutable.HashTable.foreachEntry(HashTable.scala:236) + at scala.collection.mutable.HashTable.foreachEntry$(HashTable.scala:229) + at scala.collection.mutable.HashMap.foreachEntry(HashMap.scala:40) + at scala.collection.mutable.HashMap.foreach(HashMap.scala:138) + at scala.collection.TraversableLike$WithFilter.foreach(TraversableLike.scala:788) + at firrtl.passes.CheckInitialization$.checkInitM$1(CheckInitialization.scala:78) + #+end_src + + While scary, the actual error is only this line: + #+begin_src scala + firrtl.passes.CheckInitialization$RefNotInitializedException: @[Example.scala 25:21:@20.4] : [module Invalid] Reference myVec is not fully initialized. + : myVec.io.idx <= VOID + #+end_src + + Which tells us that myVec has unInitialized wires! + While our program is correct, it produces an incorrect design, in other words, the scala part + of the code is correct as it compiled, but the chisel part is incorrect because it does not synthesize. + + Let's fix it: + #+begin_src scala + class Invalid() extends Module { + val io = IO(new Bundle{}) + + val myVec = Module(new MyVector) + myVec.io.idx := 0.U + } + #+end_src + + Hooray, now we get `scala.NotImplementedError: an implementation is missing` + as expected, along with an enormous stacktrace.. + + The observant reader may have observed that it is perfectly legal to put chisel types in scala + collection, how does that work? + + A scala collection is just a collection of references, or pointers if you will. + If it happens to contain values of chisel types then these will exist in the design, however the + collection will not, so we cannot index based on the collection. + + This can be seen in `myIncrementN` where an array of incrementors is used. + The array is only used help the scala program wire the components together, and once this is + done the array is not used. + We could do the same with MyVector, but it's not pretty: + + #+begin_src scala + class MyVector2() extends Module { + val io = IO( + new Bundle { + val idx = Input(UInt(32.W)) + val out = Output(UInt(32.W)) + } + ) + + val values = Array(0.U, 1.U, 2.U, 3.U) + + io.out := values(0) + for(ii <- 0 until 3){ + when(io.idx === ii.U){ + io.out := values(ii) + } } + } + #+end_src + + Note that it is nescessary to specify a default for io.out even though it will never be + selected. + While it looks ugly, the generated hardware should, at least in theory, not take up any + more space or run any slower than the Vec based implementation, save for one difference + as we will see in the next section. + + +* Bit Widths + What happens if we attempt to index the 6th element in our 4 element vector? + In MyVector we get 1, and in MyVector2 we get 0, so they're not exactly the same. + In MyVector the Vec has 4 elements, thus only two wires are necessary (00, 01, 10, 11), + thus the remaining 28 wires of io.idx are not used. + + In MyVector2 on the other hand we have specified a default value for io.out, so for any + index higher than 3 the output will be 0. + + What about the values in the Vec? + 0.U can be represented by a single wire, whereas 3.U must be represented by at + least two wires. + In this case it is easy for chisel to see that they must both be of width 32 since they will + be driving the output signal which is specified as 32 bit wide. + + In theory specifying widths should not be necessary other than at the very endpoints of your + design, however this would quickly end up being intractable, so we specify widths at module + endpoints. + +* Stateful circuits + + #+begin_src scala + class SimpleDelay() extends Module { + val io = IO( + new Bundle { + val dataIn = Input(UInt(32.W)) + val dataOut = Output(UInt(32.W)) + } + ) + val delayReg = RegInit(UInt(32.W), 0.U) + + delayReg := io.dataIn + io.dataOut := delayReg + } #+end_src This circuit seems rather pointless, it simply assigns the input to the output. - However, the register has another input, as seen in the RTL: fig [rm6]. - The register can only change value during rising edges on the clock! + However, unlike the previous circuits, the simpleDelay circuit stores its value + in a register, causing a one cycle delay between input and output. + + Lets test this + + + #+begin_src scala + class DelaySpec extends FlatSpec with Matchers { + behavior of "SimpleDelay" + + it should "Delay input by one timestep" in { + chisel3.iotesters.Driver(() => new SimpleDelay) { c => + new DelayTester(c) + } should be(true) + } + } - To examplify, assume at step 0 data in is 0x45. - delayReg will now have 0x45 as its data in, but data out will still be 0. - Only when the clock ticks will delayReg.dataOut take on the value 0x45. + + class DelayTester(c: SimpleDelay) extends PeekPokeTester(c) { + for(ii <- 0 until 10){ + val input = scala.util.Random.nextInt(10) + poke(c.io.dataIn, input) + expect(c.io.dataOut, input) + } + } + #+end_src + + Lets test it + + #+begin_src + sbt:chisel-module-template> testOnly Ex0.DelaySpec + ... + [info] [0.001] Elaborating design... + [info] [0.071] Done elaborating. + Total FIRRTL Compile Time: 144.7 ms + Total FIRRTL Compile Time: 9.4 ms + End of dependency graph + Circuit state created + [info] [0.001] SEED 1556196281084 + [info] [0.002] EXPECT AT 0 io_dataOut got 0 expected 7 FAIL + [info] [0.002] EXPECT AT 0 io_dataOut got 0 expected 6 FAIL + [info] [0.003] EXPECT AT 0 io_dataOut got 0 expected 1 FAIL + [info] [0.003] EXPECT AT 0 io_dataOut got 0 expected 2 FAIL + [info] [0.003] EXPECT AT 0 io_dataOut got 0 expected 7 FAIL + [info] [0.003] EXPECT AT 0 io_dataOut got 0 expected 4 FAIL + [info] [0.003] EXPECT AT 0 io_dataOut got 0 expected 8 FAIL + [info] [0.003] EXPECT AT 0 io_dataOut got 0 expected 8 FAIL + [info] [0.003] EXPECT AT 0 io_dataOut got 0 expected 7 FAIL + #+end_src + + Oops, the tester doesn't advance the clock befor testing output, totally didn't + make an error on purpose to highlight that... + + + #+begin_src scala + class DelayTester(c: SimpleDelay) extends PeekPokeTester(c) { + for(ii <- 0 until 10){ + val input = scala.util.Random.nextInt(10) + poke(c.io.dataIn, input) + step(1) + expect(c.io.dataOut, input) + } + } + #+end_src + + Much better.. You should now be able to implement myDelayN following the same principles as myIncrementN #+begin_src scala - class myDelayN(delay: Int) extends Module { - val io = IO( - new Bundle { - val dataIn = Input(UInt(32.W)) - val dataOut = Output(UInt(32.W)) - } - ) - - ??? - } + class myDelayN(delay: Int) extends Module { + val io = IO( + new Bundle { + val dataIn = Input(UInt(32.W)) + val dataOut = Output(UInt(32.W)) + } + ) + + ??? + } #+end_src This should answer the initial question of combinatorial vs stateful: @@ -274,3 +730,4 @@ matrix multiplier. Why did this happen, and how could this have been avoided? + diff --git a/ov0/src/main/scala/Tile.scala b/ov0/src/main/scala/Tile.scala deleted file mode 100644 index 875f23f..0000000 --- a/ov0/src/main/scala/Tile.scala +++ /dev/null @@ -1,56 +0,0 @@ -package Core -import chisel3._ -import chisel3.core.Input -import chisel3.iotesters.PeekPokeTester - - -object Extras { - def somefun(someval: Int) : Unit = {} - - val vecA = List(1, 2, 4) - val vecB = List(2, -3, 1) - - def dotProductForLoop(vecA: List[Int], vecB: List[Int]) = { - var dotProduct = 0 - for(i <- 0 until vecA.length){ - dotProduct = dotProduct + (vecA(i) * vecB(i)) - } - dotProduct - } - - - // If you prefer a functional style scala has excellent support. - val dotProductFP = (vecA zip vecB) - .map{ case(a, b) => a*b } - .sum - - val fancyDotProduct = (vecA zip vecB) - .foldLeft(0){ case(acc, ab) => acc + (ab._1 * ab._2) } - - - // Scala gives you ample opportunity to write unreadable code. - // This is not good code!!! - val tooFancyDotProduct = - (0 /: (vecA zip vecB)){ case(acc, ab) => acc + (ab._1 * ab._2) } - - - type Matrix[A] = List[List[A]] - def vectorMatrixMultiply(vec: List[Int], matrix: Matrix[Int]): List[Int] = { - val transposed = matrix.transpose - - val outputVector = Array.ofDim[Int](vec.length) - for(ii <- 0 until matrix.length){ - outputVector(ii) = dotProductForLoop(vec, transposed(ii)) - } - outputVector.toList - } - - - val vec = List(1, 0, 1) - val matrix = List( - List(2, 1, 2), - List(3, 2, 3), - List(4, 1, 1) - ) - println(vectorMatrixMultiply(vec, matrix)) -} diff --git a/ov0/src/main/scala/basics.scala b/ov0/src/main/scala/basics.scala deleted file mode 100644 index 13bca02..0000000 --- a/ov0/src/main/scala/basics.scala +++ /dev/null @@ -1,161 +0,0 @@ - -package Core -import chisel3._ -import chisel3.core.Input -import chisel3.iotesters.PeekPokeTester - - -class myIncrement(incrementBy: Int) extends Module { - val io = IO( - new Bundle { - val dataIn = Input(UInt(32.W)) - val dataOut = Output(UInt(32.W)) - } - ) - - io.dataOut := io.dataIn + incrementBy.U -} - - -class myIncrementTwice(incrementBy: Int) extends Module { - val io = IO( - new Bundle { - val dataIn = Input(UInt(32.W)) - val dataOut = Output(UInt(32.W)) - } - ) - - val first = Module(new myIncrement(incrementBy)) - val second = Module(new myIncrement(incrementBy)) - - first.io.dataIn := io.dataIn - second.io.dataIn := first.io.dataOut - - io.dataOut := second.io.dataOut -} - - -class myIncrementN(incrementBy: Int, numIncrementors: Int) extends Module { - val io = IO( - new Bundle { - val dataIn = Input(UInt(32.W)) - val dataOut = Output(UInt(32.W)) - } - ) - - val incrementors = Array.fill(numIncrementors){ Module(new myIncrement(incrementBy)) } - - for(ii <- 1 until numIncrementors){ - incrementors(ii).io.dataIn := incrementors(ii - 1).io.dataOut - } - - incrementors(0).io.dataIn := io.dataIn - io.dataOut := incrementors(numIncrementors).io.dataOut -} - - - - -class myDelay() extends Module { - val io = IO( - new Bundle { - val dataIn = Input(UInt(32.W)) - val dataOut = Output(UInt(32.W)) - } - ) - - val reg = RegInit(UInt(32.W), 0.U) - reg := io.dataIn - io.dataOut := reg -} - - -class myDelayN(steps: Int) extends Module { - val io = IO( - new Bundle { - val dataIn = Input(UInt(32.W)) - val dataOut = Output(UInt(32.W)) - } - ) - - val delayers = Array.fill(steps){ Module(new myDelay()) } - - for(ii <- 1 until steps){ - delayers(ii).io.dataIn := delayers(ii - 1).io.dataOut - } - - delayers(0).io.dataIn := io.dataIn - io.dataOut := delayers(steps).io.dataOut -} - - -class mySelector(numValues: Int) extends Module { - val io = IO( - new Bundle { - val next = Input(Bool()) - val dataOut = Output(UInt(32.W)) - val newOutput = Output(Bool()) - } - ) - - val counter = RegInit(UInt(Chisel.log2Up(numValues).W), 0.U) - val nextOutputIsFresh = RegInit(Bool(), true.B) - - /** - Generate random values. Using the when keyword we choose which random - value should drive the dataOut signal - */ - io.dataOut := 0.U - List.fill(numValues)(scala.util.Random.nextInt(100)).zipWithIndex.foreach { - case(rand, idx) => - when(counter === idx.U){ - if(rand < 50) - io.dataOut := rand.U - else - io.dataOut := (rand + 100).U - } - } - - /** - While chisel comes with an inbuilt Counter, we implement ours the old fashion way - There are far more elegant ways of implementing this, read the chisel docs, discuss - best practice among yourselves and experiment! - */ - nextOutputIsFresh := true.B - when(io.next === true.B){ - when(counter < (numValues - 1).U){ - counter := counter + 1.U - }.otherwise { - counter := 0.U - } - }.otherwise { - nextOutputIsFresh := false.B - } - io.newOutput := nextOutputIsFresh -} - - -class mySelectorTest(c: mySelector) extends PeekPokeTester(c) { - poke(c.io.next, true.B) - for(ii <- 0 until 10){ - val wasStale = peek(c.io.newOutput) == 0 - val output = peek(c.io.dataOut).toString() - println(s"at step $ii:") - println(s"data out is $output") - println(s"was the output fresh? ${!wasStale}") - println() - step(1) - } - - poke(c.io.next, false.B) - - for(ii <- 0 until 3){ - val wasStale = peek(c.io.newOutput) == 0 - val output = peek(c.io.dataOut).toString() - println(s"at step $ii:") - println(s"data out is $output") - println(s"was the output fresh? ${!wasStale}") - println() - step(1) - } -} diff --git a/ov0/src/main/scala/daisyDot.scala b/ov0/src/main/scala/daisyDot.scala deleted file mode 100644 index 700f888..0000000 --- a/ov0/src/main/scala/daisyDot.scala +++ /dev/null @@ -1,47 +0,0 @@ -package Core -import chisel3._ -import chisel3.core.Input -import chisel3.util.Counter - -/** - DaisyVectors are not indexed. They have no control inputs or outputs, only data. - */ -class daisyDot(elements: Int, dataWidth: Int) extends Module{ - - val io = IO(new Bundle { - val dataInA = Input(UInt(dataWidth.W)) - val dataInB = Input(UInt(dataWidth.W)) - - val dataOut = Output(UInt(dataWidth.W)) - val outputValid = Output(Bool()) - }) - - /** - Keep track of how many elements have been accumulated. As the interface has no - indicator that data can be invalid it should always be assumed that data IS valid. - - This in turn means that the counter should tick on every cycle - */ - val counter = Counter(elements) - val accumulator = RegInit(UInt(dataWidth.W), 0.U) - - /** - Your implementation here - */ - // Increment the value of the accumulator with the product of data in A and B - // When the counter reaches elements set output valid to true and flush the accumulator - - /** - LF - */ - val product = io.dataInA * io.dataInB - when(counter.inc()){ - io.outputValid := true.B - accumulator := 0.U - }.otherwise{ - io.outputValid := false.B - accumulator := accumulator + product - } - - io.dataOut := accumulator + product -} diff --git a/ov0/src/main/scala/daisyGrid.scala b/ov0/src/main/scala/daisyGrid.scala deleted file mode 100644 index 1ee9b8c..0000000 --- a/ov0/src/main/scala/daisyGrid.scala +++ /dev/null @@ -1,44 +0,0 @@ -package Core -import chisel3._ -import chisel3.core.Input -import chisel3.iotesters.PeekPokeTester -import utilz._ - -/** - DaisyGrids hold n daisyVecs. Unlike the daisyVecs, daisyGrids have a select signal for selecting - which daisyVec to work on, but these daisyVecs can not be controlled from the outside. - */ -class daisyGrid(dims: Dims, dataWidth: Int) extends Module{ - - val io = IO(new Bundle { - - val writeEnable = Input(Bool()) - val dataIn = Input(UInt(dataWidth.W)) - val rowSelect = Input(UInt(8.W)) - - val dataOut = Output(UInt(dataWidth.W)) - }) - - val rows = Array.fill(dims.rows){ Module(new daisyVector(dims.cols, dataWidth)).io } - - /** - Your implementation here - */ - - - /** - LF - */ - io.dataOut := 0.U - - for(ii <- 0 until dims.rows){ - - rows(ii).writeEnable := 0.U - rows(ii).dataIn := io.dataIn - - when(io.rowSelect === ii.U ){ - rows(ii).writeEnable := io.writeEnable - io.dataOut := rows(ii).dataOut - } - } -} diff --git a/ov0/src/main/scala/daisyMatMul.scala b/ov0/src/main/scala/daisyMatMul.scala deleted file mode 100644 index cfd7fe0..0000000 --- a/ov0/src/main/scala/daisyMatMul.scala +++ /dev/null @@ -1,127 +0,0 @@ -package Core -import chisel3._ -import chisel3.core.Input -import chisel3.iotesters.PeekPokeTester -import utilz._ - -/** - The daisy multiplier creates two daisy grids, one transposed, and multiplies them. - */ -class daisyMultiplier(dims: Dims, dataWidth: Int) extends Module { - - val io = IO(new Bundle { - - val dataInA = Input(UInt(dataWidth.W)) - val writeEnableA = Input(Bool()) - - val dataInB = Input(UInt(dataWidth.W)) - val writeEnableB = Input(Bool()) - - val dataOut = Output(UInt(dataWidth.W)) - val dataValid = Output(Bool()) - val done = Output(Bool()) - }) - - - /** - Your implementation here - */ - val rowCounter = RegInit(UInt(8.W), 0.U) - val colCounter = RegInit(UInt(8.W), 0.U) - - val rowOutputCounter = RegInit(UInt(8.W), 0.U) - - val calculating = RegInit(Bool(), false.B) - val accumulator = RegInit(UInt(8.W), 0.U) - - val resultReady = RegInit(Bool(), false.B) - - - /** - Following the same principle behind the the vector matrix multiplication, by - NOT transposing the dimensions. - - When writing a multiplier for a 3x2 matrix it's implicit that this means a - 3x2 matrix and 2x3, returning a 2x2 matrix. By not transposing the dimensions - we get the same effect as in VecMat - */ - val matrixA = Module(new daisyGrid(dims, dataWidth)).io - val matrixB = Module(new daisyGrid(dims, dataWidth)).io - - - - - matrixA.dataIn := io.dataInA - matrixA.writeEnable := io.writeEnableA - - matrixB.dataIn := io.dataInB - matrixB.writeEnable := io.writeEnableB - - //////////////////////////////////////// - //////////////////////////////////////// - /// Set up counter statemachine - io.done := false.B - - when(colCounter === (dims.cols - 1).U){ - colCounter := 0.U - - when(rowCounter === (dims.rows - 1).U){ - rowCounter := 0.U - calculating := true.B - - when(calculating === true.B){ - - when(rowOutputCounter === (dims.rows - 1).U){ - io.done := true.B - }.otherwise{ - rowOutputCounter := rowOutputCounter + 1.U - } - - } - - }.otherwise{ - rowCounter := rowCounter + 1.U - } - }.otherwise{ - colCounter := colCounter + 1.U - } - - - - //////////////////////////////////////// - //////////////////////////////////////// - /// set up reading patterns depending on if we are in calculating state or not - when(calculating === true.B){ - matrixA.rowSelect := rowOutputCounter - }.otherwise{ - matrixA.rowSelect := rowCounter - } - - matrixB.rowSelect := rowCounter - - - - //////////////////////////////////////// - //////////////////////////////////////// - /// when we're in calculating mode, check if we have valid output - resultReady := false.B - io.dataValid := false.B - when(calculating === true.B){ - when(colCounter === (dims.cols - 1).U){ - resultReady := true.B - } - } - - - //////////////////////////////////////// - //////////////////////////////////////// - /// when we've got a result ready we need to flush the accumulator - when(resultReady === true.B){ - // To flush our accumulator we simply disregard previous state - accumulator := (matrixA.dataOut*matrixB.dataOut) - io.dataValid := true.B - }.otherwise{ - accumulator := accumulator + (matrixA.dataOut*matrixB.dataOut) - } - io.dataOut := accumulator -} diff --git a/ov0/src/main/scala/daisyVec.scala b/ov0/src/main/scala/daisyVec.scala deleted file mode 100644 index 25e0690..0000000 --- a/ov0/src/main/scala/daisyVec.scala +++ /dev/null @@ -1,55 +0,0 @@ -package Core -import chisel3._ -import chisel3.core.Input -import chisel3.iotesters.PeekPokeTester - -/** - DaisyVectors are not indexed externally. They have no control inputs or outputs, only data. - */ -class daisyVector(elements: Int, dataWidth: Int) extends Module{ - - val io = IO(new Bundle { - val writeEnable = Input(Bool()) - val dataIn = Input(UInt(dataWidth.W)) - - val dataOut = Output(UInt(dataWidth.W)) - }) - - /** - although the vector is not accessible by index externally, an internal index is necessary - It is initialized to the value 0 - */ - val currentIndex = RegInit(UInt(8.W), 0.U) - val memory = Array.fill(elements)(RegInit(UInt(dataWidth.W), 0.U)) - - - /** - Your implementation here - */ - // Cycle the currentIndex register, it should be equal to the current (cycle % elements) - - // Connect the selected output to io.dataOut - // Connect writeEnable to the selected memory (selectable with memory(currentIndex)) - /** - LF - */ - - - when(currentIndex === (elements - 1).U ){ - currentIndex := 0.U - }.otherwise{ - currentIndex := currentIndex + 1.U - } - - - io.dataOut := 0.U - - for(ii <- 0 until elements){ - when(currentIndex === ii.U){ - when(io.writeEnable === true.B){ - memory(ii) := io.dataIn - } - io.dataOut := memory(ii) - } - } -} diff --git a/ov0/src/main/scala/daisyVecMat.scala b/ov0/src/main/scala/daisyVecMat.scala deleted file mode 100644 index 0f28de8..0000000 --- a/ov0/src/main/scala/daisyVecMat.scala +++ /dev/null @@ -1,150 +0,0 @@ - -package Core -import Core.daisyVector -import chisel3._ -import chisel3.core.Input -import chisel3.iotesters.PeekPokeTester -import chisel3.util.Counter -import utilz._ - -/** - The daisy multiplier creates two daisy grids, one transposed, and multiplies them. - */ -class daisyVecMat(matrixDims: Dims, dataWidth: Int) extends Module { - - val io = IO( - new Bundle { - - val dataInA = Input(UInt(dataWidth.W)) - val writeEnableA = Input(Bool()) - - val dataInB = Input(UInt(dataWidth.W)) - val writeEnableB = Input(Bool()) - - val dataOut = Output(UInt(dataWidth.W)) - val dataValid = Output(Bool()) - val done = Output(Bool()) - - } - ) - - /** - The dimensions are transposed because this is a vector * matrix multiplication - - [1, 2] - [a, b, c] x [3, 4] - [5, 6] - - Here the vector will output a, b, c, a, b, c, a... - The Matrix is the type you made last exercise, so it is actually just 3 more vectors - of length 2. In cycle 0 the values {1, 3, 5} may be selected, in cycle 1 {2, 4, 6} - can be selected. - - However, you can make up for the impedance mismatch by transposing the matrix, storing - the data in 2 vectors of length 3 instead. - - In memory matrixB will look like [1, 3, 5] - [2, 4, 6] - - For a correct result, it is up to the user to input the data for matrixB in a transposed - manner. This is done in the tests, you don't need to worry about it. - */ - val dims = matrixDims.transposed - - // basic linAlg - val lengthA = dims.cols - - val vecA = Module(new daisyVector(lengthA, dataWidth)).io - val matrixB = Module(new daisyGrid(dims, dataWidth)).io - val dotProductCalculator = Module(new daisyDot(lengthA, dataWidth)).io - val dataIsLoaded = RegInit(Bool(), false.B) - - /** - Your implementation here - */ - // Create counters to keep track of when the matrix and vector has gotten all the data. - // You can assume that writeEnable will be synchronized with the vectors. I.e for a vector - // of length 3 writeEnable can only go from true to false and vice versa at T = 0, 3, 6, 9 etc - - - // Create counters to keep track of how far along the computation is. - - // Set up the correct rowSelect for matrixB - - // Wire up write enables for matrixB and vecA - - /** - In the solution I used the following to keep track of state - You can use these if you want to, or do it however you see fit. - */ - // val currentCol = Counter(dims.cols) - // val rowSel = Counter(dims.rows) - // val aReady = RegInit(Bool(), false.B) - // val bReady = RegInit(Bool(), false.B) - // val isDone = RegInit(Bool(), false.B) - // val (inputCounterB, counterBWrapped) = Counter(io.writeEnableB, (dims.elements) - 1) - // val (numOutputted, numOutputtedWrapped) = Counter(dataValid, lengthA) - // val (inputCounterA, counterAWrapped) = Counter(io.writeEnableA, lengthA - 1) - - /** - LF - */ - val dataValid = Wire(Bool()) - - - //////////////////////////////////////// - //////////////////////////////////////// - /// Wire components - vecA.dataIn := io.dataInA - vecA.writeEnable := io.writeEnableA - - matrixB.dataIn := io.dataInB - matrixB.writeEnable := io.writeEnableB - - io.dataOut := dotProductCalculator.dataOut - - // allows us to use dataValid internally - io.dataValid := dataValid - - dotProductCalculator.dataInA := vecA.dataOut - dotProductCalculator.dataInB := matrixB.dataOut - dataValid := dotProductCalculator.outputValid & dataIsLoaded - - //////////////////////////////////////// - //////////////////////////////////////// - /// Select the correct row - val currentCol = Counter(dims.cols) - val rowSel = Counter(dims.rows) - - when(currentCol.inc()){ - rowSel.inc() - } - - matrixB.rowSelect := rowSel.value - - - //////////////////////////////////////// - //////////////////////////////////////// - /// Check if data is loaded - val aReady = RegInit(Bool(), false.B) - val bReady = RegInit(Bool(), false.B) - - val (inputCounterA, counterAWrapped) = Counter(io.writeEnableA, lengthA - 1) - when(counterAWrapped){ aReady := true.B } - - val (inputCounterB, counterBWrapped) = Counter(io.writeEnableB, (dims.elements) - 1) - when(counterBWrapped){ bReady := true.B } - - dataIsLoaded := aReady & bReady - - - //////////////////////////////////////// - //////////////////////////////////////// - /// Check if we're done - val isDone = RegInit(Bool(), false.B) - val (numOutputted, numOutputtedWrapped) = Counter(dataValid, lengthA) - - when(numOutputtedWrapped){ isDone := true.B } - - io.done := isDone -} diff --git a/ov0/src/main/scala/daisyVecVec.scala b/ov0/src/main/scala/daisyVecVec.scala deleted file mode 100644 index 4096bf0..0000000 --- a/ov0/src/main/scala/daisyVecVec.scala +++ /dev/null @@ -1,40 +0,0 @@ -package Core -import chisel3._ -import chisel3.core.Input -import chisel3.iotesters.PeekPokeTester -import chisel3.util.Counter - -/** - DaisyVectors are not indexed. They have no control inputs or outputs, only data. - */ -class daisyVecVec(elements: Int, dataWidth: Int) extends Module{ - - val io = IO(new Bundle { - val dataInA = Input(UInt(dataWidth.W)) - val dataInB = Input(UInt(dataWidth.W)) - - val dataOut = Output(UInt(dataWidth.W)) - val outputValid = Output(Bool()) - }) - - val counter = Counter(elements) - val accumulator = RegInit(UInt(dataWidth.W), 0.U) - - /** - Your implementation here - */ - - /** - LF - */ - val product = io.dataInA * io.dataInB - when(counter.inc()){ - io.outputValid := true.B - accumulator := 0.U - }.otherwise{ - io.outputValid := false.B - accumulator := accumulator + product - } - - io.dataOut := accumulator + product -} diff --git a/ov0/src/main/scala/utils.scala b/ov0/src/main/scala/utils.scala deleted file mode 100644 index 321f161..0000000 --- a/ov0/src/main/scala/utils.scala +++ /dev/null @@ -1,45 +0,0 @@ -package Core - -object utilz { - - type Matrix = List[List[Int]] - - def genMatrix(dims: Dims): Matrix = - List.fill(dims.rows)( - List.fill(dims.cols)(scala.util.Random.nextInt(5)) - ) - - case class Dims(rows: Int, cols: Int){ - val elements = rows*cols - def transposed = Dims(cols, rows) - } - - def printVector(v: List[Int]): String = - v.mkString("[","\t","]") - - def printMatrix(m: List[List[Int]]): String = - m.map(printVector).mkString("\n") - - /** - Typically I'd fix the signature to Map[A,B] - Prints all the IOs of a Module - ex: - - ``` - CycleTask[daisyVecMat]( - 10, - _ => println(s"at step $n"), - d => println(printModuleIO(d.peek(d.dut.io))), - ) - ``` - */ - def printModuleIO[A,B](m: scala.collection.mutable.LinkedHashMap[A,B]): String = - m.toList.map{ case(x,y) => "" + x.toString() + " -> " + y.toString() }.reverse.mkString("\n") - - - def dotProduct(xs: List[Int], ys: List[Int]): Int = - (for ((x, y) <- xs zip ys) yield x * y).sum - - def matrixMultiply(ma: Matrix, mb: Matrix): Matrix = - ma.map(mav => mb.transpose.map(mbv => dotProduct(mav,mbv))) -} diff --git a/ov0/src/test/scala/daisyDotTest.scala b/ov0/src/test/scala/daisyDotTest.scala deleted file mode 100644 index 8cf24a7..0000000 --- a/ov0/src/test/scala/daisyDotTest.scala +++ /dev/null @@ -1,82 +0,0 @@ -package Core -import chisel3._ -import chisel3.iotesters._ -import org.scalatest.{Matchers, FlatSpec} -import testUtils._ - - -class daisyDotSpec extends FlatSpec with Matchers { - - behavior of "daisy vector" - - - it should "Only signal valid output at end of calculation" in { - - val ins = (0 to 20).map(ii => - CycleTask[daisyDot]( - ii, - d => d.poke(d.dut.io.dataInA, 0), - d => d.poke(d.dut.io.dataInB, 0), - d => d.expect(d.dut.io.outputValid, if((ii % 3) == 2) 1 else 0), - ) - ) - - iotesters.Driver.execute(() => new daisyDot(3, 32), new TesterOptionsManager) { c => - IoSpec[daisyDot](ins, c).myTester - } should be(true) - } - - it should "Be able to count to 3" in { - - val ins = (0 to 20).map(ii => - CycleTask[daisyDot]( - ii, - d => d.poke(d.dut.io.dataInA, 1), - d => d.poke(d.dut.io.dataInB, 1), - d => d.expect(d.dut.io.outputValid, if((ii % 3) == 2) 1 else 0), - d => if(d.peek(d.dut.io.outputValid) == 1) - d.expect(d.dut.io.dataOut, 3) - ) - ) - - iotesters.Driver.execute(() => new daisyDot(3, 32), new TesterOptionsManager) { c => - IoSpec[daisyDot](ins, c).myTester - } should be(true) - } - - - - it should "Be able to calculate dot products" in { - - def createProblem(vecLen: Int): List[CycleTask[daisyDot]] = { - - val in1 = List.fill(vecLen)(scala.util.Random.nextInt(10)) - val in2 = List.fill(vecLen)(scala.util.Random.nextInt(10)) - - val dotProduct = (in1, in2).zipped.map(_*_).sum - - (in1, in2, (0 to vecLen)).zipped.map{ - case(a, b, idx) => - CycleTask[daisyDot]( - idx, - d => d.poke(d.dut.io.dataInA, a), - d => d.poke(d.dut.io.dataInB, b), - d => if(d.peek(d.dut.io.outputValid) == 1) - d.expect(d.dut.io.dataOut, dotProduct) - ) - } - } - - - def createProblems(vecLen: Int): List[CycleTask[daisyDot]] = - List.fill(10)(createProblem(vecLen)).zipWithIndex.map{ case(probs, idx) => - probs.map(_.delay(3*idx)) - }.flatten - - - - iotesters.Driver.execute(() => new daisyDot(3, 32), new TesterOptionsManager) { c => - IoSpec[daisyDot](createProblems(3), c).myTester - } should be(true) - } -} diff --git a/ov0/src/test/scala/daisyGridTest.scala b/ov0/src/test/scala/daisyGridTest.scala deleted file mode 100644 index 8714b59..0000000 --- a/ov0/src/test/scala/daisyGridTest.scala +++ /dev/null @@ -1,82 +0,0 @@ -package Core -import chisel3._ -import chisel3.iotesters._ -import org.scalatest.{Matchers, FlatSpec} -import testUtils._ -import utilz._ - - -class daisyGridSpec extends FlatSpec with Matchers { - - behavior of "daisy grid" - - def writeRowCheck(dims: Dims, rowSel: Int => Int): Seq[CycleTask[daisyGrid]] = { - (0 until dims.cols).map( n => - CycleTask[daisyGrid]( - n, - d => d.poke(d.dut.io.dataIn, n), - d => d.poke(d.dut.io.writeEnable, 1), - d => d.poke(d.dut.io.rowSelect, rowSel(n))) - ) ++ - (0 until dims.cols*2).map( n => - CycleTask[daisyGrid]( - n, - d => d.poke(d.dut.io.dataIn, 0), - d => d.poke(d.dut.io.writeEnable, 0), - d => d.poke(d.dut.io.rowSelect, rowSel(n)), - d => d.expect(d.dut.io.dataOut, n % dims.cols)).delay(dims.cols) - ) - } - - - val dims = Dims(rows = 4, cols = 5) - - it should "work like a regular daisyVec when row select is fixed to 0" in { - - iotesters.Driver.execute(() => new daisyGrid(dims, 32), new TesterOptionsManager) { c => - IoSpec[daisyGrid](writeRowCheck(dims, _ => 0), c).myTester - } should be(true) - } - - - it should "work like a regular daisyVec when row select is fixed to 1" in { - iotesters.Driver.execute(() => new daisyGrid(dims, 32), new TesterOptionsManager) { c => - IoSpec[daisyGrid](writeRowCheck(dims, _ => 1), c).myTester - } should be(true) - } - - - it should "be able to write a matrix and output it" in { - iotesters.Driver.execute(() => new daisyGrid(dims, 32), new TesterOptionsManager) { c => - - def writeMatrix(matrix: Matrix): List[CycleTask[daisyGrid]] = { - (0 until dims.elements).toList.zipWithIndex.map{ case(n, idx) => - val row = n / dims.cols - CycleTask[daisyGrid]( - n, - d => d.poke(d.dut.io.dataIn, n), - d => d.poke(d.dut.io.writeEnable, 1), - d => d.poke(d.dut.io.rowSelect, row)) - } - } - - def readMatrix(matrix: Matrix): List[CycleTask[daisyGrid]] = { - (0 until dims.elements).toList.zipWithIndex.map{ case(n, idx) => - val row = n / dims.cols - CycleTask[daisyGrid]( - n, - d => d.poke(d.dut.io.dataIn, 0), - d => d.poke(d.dut.io.writeEnable, 0), - d => d.poke(d.dut.io.rowSelect, row), - d => d.expect(d.dut.io.dataOut, n)) - } - } - - - val m = genMatrix(Dims(rows = 4, cols = 5)) - val ins = writeMatrix(m) ++ readMatrix(m).map(_.delay(dims.elements)) - - IoSpec[daisyGrid](ins, c).myTester - } should be(true) - } -} diff --git a/ov0/src/test/scala/daisyMatMulTest.scala b/ov0/src/test/scala/daisyMatMulTest.scala deleted file mode 100644 index 14c1c40..0000000 --- a/ov0/src/test/scala/daisyMatMulTest.scala +++ /dev/null @@ -1,112 +0,0 @@ -package Core -import chisel3._ -import chisel3.iotesters._ -import org.scalatest.{Matchers, FlatSpec} -import testUtils._ -import utilz._ - -class daisyMatMulSpec extends FlatSpec with Matchers { - def generateProblem(dims: Dims): List[CycleTask[daisyMultiplier]] = { - - val matrixA = genMatrix(dims) - val matrixB = genMatrix(dims).transpose - - val answers = matrixMultiply(matrixA, matrixB) - - println("Multiplying matrix A") - println(printMatrix(matrixA)) - println("with matrix B") - println(printMatrix(matrixB)) - println("The input order of matrix B is") - println(printMatrix(matrixB.transpose)) - println("Expected output is") - println(printMatrix(answers)) - - - val matrixInputA = matrixA.flatten.zipWithIndex.map{ - case(in, idx) => - CycleTask[daisyMultiplier]( - idx, - d => d.poke(d.dut.io.dataInA, in), - d => d.poke(d.dut.io.writeEnableA, 1) - ) - } - - - val matrixInputB = matrixB.transpose.flatten.zipWithIndex.map{ - case(in, idx) => - CycleTask[daisyMultiplier]( - idx, - d => d.poke(d.dut.io.dataInB, in), - d => d.poke(d.dut.io.writeEnableB, 1) - ) - } - - - val disableInputs = List( - CycleTask[daisyMultiplier]( - dims.elements, - d => d.poke(d.dut.io.writeEnableA, 0) - ), - CycleTask[daisyMultiplier]( - dims.elements, - d => d.poke(d.dut.io.writeEnableB, 0) - ) - ) - - - val checkValid1 = (0 until dims.elements).map( n => - CycleTask[daisyMultiplier]( - n, - d => d.expect(d.dut.io.dataValid, 0, "data valid should not be asserted before data is ready") - ) - ).toList - - - - val checkValid2 = (0 until dims.rows * dims.rows * dims.cols).map{ n => - - val shouldBeValid = (n % dims.cols) == dims.cols - 1 - - val answerRowIndex = n/(dims.rows*dims.cols) - val answerColIndex = ((n-1)/(dims.cols)) % dims.rows - - val expectedOutput = answers(answerRowIndex)(answerColIndex) - - CycleTask[daisyMultiplier]( - n, - d => if(!shouldBeValid) - d.expect(d.dut.io.dataValid, 0) - else { - d.expect(d.dut.io.dataValid, 1) - d.expect(d.dut.io.dataOut, expectedOutput) - } - - ).delay(dims.elements + 1) - }.toList - - - // adds a lot of annoying noise - // val peekDebug = (0 until 20).map(n => - // CycleTask[daisyMultiplier]( - // n, - // _ => println(s"at step $n"), - // d => println(printModuleIO(d.peek(d.dut.io))), - // _ => println(), - // ) - // ).toList - - matrixInputA ::: matrixInputB ::: disableInputs ::: checkValid1 ::: checkValid2 // ::: peekDebug - } - - - behavior of "mat multiplier" - - val dims = Dims(rows = 3, cols = 2) - - it should "work" in { - iotesters.Driver.execute(() => new daisyMultiplier(dims, 32), new TesterOptionsManager) { c => - IoSpec[daisyMultiplier](generateProblem(Dims(rows = 3, cols = 2)), c).myTester - } should be(true) - } -} diff --git a/ov0/src/test/scala/daisyVecMatTest.scala b/ov0/src/test/scala/daisyVecMatTest.scala deleted file mode 100644 index 27415b7..0000000 --- a/ov0/src/test/scala/daisyVecMatTest.scala +++ /dev/null @@ -1,116 +0,0 @@ -package Core -import chisel3._ -import chisel3.iotesters._ -import org.scalatest.{Matchers, FlatSpec} -import testUtils._ -import utilz._ - - -class daisyVecMatSpec extends FlatSpec with Matchers { - - def generateProblem(dims: Dims): List[CycleTask[daisyVecMat]] = { - - // for a vec len A, a matrix must have dims A rows - val matrixB = genMatrix(dims).transpose - val vecA = List.fill(dims.rows)(scala.util.Random.nextInt(5)) - - def answers: List[Int] = matrixB.map( col => - (col, vecA).zipped.map(_*_).sum) - - println("multiplying vector: ") - println(printVector(vecA)) - println("with matrix:") - println(printMatrix(matrixB.transpose)) - println("which should equal") - println(printVector(answers)) - - println("Input order of matrix:") - println(printMatrix(matrixB)) - - - val vecInput = vecA.zipWithIndex.map{ - case(in, idx) => - CycleTask[daisyVecMat]( - idx, - d => d.poke(d.dut.io.dataInA, in), - d => d.poke(d.dut.io.writeEnableA, 1) - ) - } - - - val matrixInput = matrixB.flatten.zipWithIndex.map{ - case(in, idx) => - CycleTask[daisyVecMat]( - idx, - d => d.poke(d.dut.io.dataInB, in), - d => d.poke(d.dut.io.writeEnableB, 1) - ) - } - - - val inputDisablers = List( - CycleTask[daisyVecMat]( - dims.rows, - d => d.poke(d.dut.io.writeEnableA, 0) - ), - CycleTask[daisyVecMat]( - dims.elements, - d => d.poke(d.dut.io.writeEnableB, 0) - ) - ) - - - val checkValid1 = (0 until dims.elements).map( n => - CycleTask[daisyVecMat]( - n, - d => d.expect(d.dut.io.dataValid, 0, "data valid should not be asserted before data is ready") - ) - ).toList - - - - - val checkValid2 = (0 until dims.elements).map{ n => - - val shouldBeValid = (n % dims.rows) == dims.rows - 1 - - val whichOutput = answers( (n/dims.rows) ) - - CycleTask[daisyVecMat]( - n, - d => if(!shouldBeValid) - d.expect(d.dut.io.dataValid, 0) - else { - d.expect(d.dut.io.dataValid, 1) - d.expect(d.dut.io.dataOut, whichOutput) - } - - ).delay(dims.elements) - }.toList - - - // adds a lot of annoying noise - // val peekDebug = (0 until 20).map(n => - // CycleTask[daisyVecMat]( - // n, - // _ => println(s"at step $n"), - // d => println(printModuleIO(d.peek(d.dut.io))), - // _ => println(), - // ) - // ).toList - - vecInput ::: matrixInput ::: inputDisablers ::: checkValid1 ::: checkValid2 // ::: peekDebug - } - - - - behavior of "vec mat multiplier" - - val dims = Dims(rows = 3, cols = 2) - - it should "work" in { - iotesters.Driver.execute(() => new daisyVecMat(dims, 32), new TesterOptionsManager) { c => - IoSpec[daisyVecMat](generateProblem(Dims(rows = 3, cols = 2)), c).myTester - } should be(true) - } -} diff --git a/ov0/src/test/scala/daisyVecTest.scala b/ov0/src/test/scala/daisyVecTest.scala deleted file mode 100644 index 7898b92..0000000 --- a/ov0/src/test/scala/daisyVecTest.scala +++ /dev/null @@ -1,84 +0,0 @@ -package Core -import chisel3._ -import chisel3.iotesters._ -import org.scalatest.{Matchers, FlatSpec} -import testUtils._ - - -class daisyVecSpec extends FlatSpec with Matchers { - - behavior of "daisy vector" - - it should "not write when write enable is low" in { - - val ins = (0 to 10).map(ii => - CycleTask[daisyVector]( - ii, - d => d.poke(d.dut.io.dataIn, 0), - d => d.poke(d.dut.io.writeEnable, 0), - d => d.expect(d.dut.io.dataOut, 0)) - ).toList - - - iotesters.Driver.execute(() => new daisyVector(4, 32), new TesterOptionsManager) { c => - IoSpec[daisyVector](ins, c).myTester - } should be(true) - } - - - - it should "write only when write enable is asserted" in { - - val ins = - (0 until 4).map(ii => - CycleTask[daisyVector]( - ii, - _ => println("inputting 2s'"), - d => d.poke(d.dut.io.dataIn, 2), - d => d.poke(d.dut.io.writeEnable, 1))) ++ - (0 until 6).map(ii => - CycleTask[daisyVector]( - ii + 4, - _ => println("Checking output is 2"), - d => d.poke(d.dut.io.writeEnable, 0), - d => d.expect(d.dut.io.dataOut, 2) - )) - - iotesters.Driver.execute(() => new daisyVector(4, 32), new TesterOptionsManager) { c => - IoSpec[daisyVector](ins, c).myTester - } should be(true) - } - - - - it should "Work in general" in { - - - val ins = { - val inputs = List.fill(10)(scala.util.Random.nextInt(10000)) - - println(inputs) - - val in = inputs.zipWithIndex.map{ case(in,idx) => - CycleTask[daisyVector]( - idx, - d => d.poke(d.dut.io.dataIn, in), - d => d.poke(d.dut.io.writeEnable, 1) - ) - } - - val out = inputs.zipWithIndex.map{ case(expected, idx) => - CycleTask[daisyVector]( - idx + 4, - d => d.expect(d.dut.io.dataOut, expected) - ) - } - - in ::: out - } - - iotesters.Driver.execute(() => new daisyVector(4, 32), new TesterOptionsManager) { c => - IoSpec[daisyVector](ins, c).myTester - } should be(true) - } -} diff --git a/ov0/src/test/scala/tests.scala b/ov0/src/test/scala/tests.scala deleted file mode 100644 index b661565..0000000 --- a/ov0/src/test/scala/tests.scala +++ /dev/null @@ -1,74 +0,0 @@ -package Core -import chisel3._ -import chisel3.iotesters._ -import org.scalatest.{Matchers, FlatSpec} - - -object testUtils { - - /** - Somewhat unintuitively named, a cycle task is a list test tasks at some time step. - In order to not have to supply a list the scala varargs syntax (*) is used. - As an example, at step 13 we want to input a value to a signal in: (PeekPokeTester[T] => Unit) - and check an output out: ((PeekPokeTester[T] => Unit) with the possibility of test failure exception) - Thanks to varargs syntax this would be - CycleTask[MyModule](13, in, out) - - Sometimes it is convenient to delay a bunch of checks by some set amount of cycles. - For instance, assume a component needs 10 cycles to set up, but it's more convenient - to write tests from T = 0, we do that and then call .delay(10) to ensure the T0 for the - tasks is actually T = 10 - */ - case class CycleTask[T <: Module](step: Int, run: PeekPokeTester[T] => Unit*){ - - // :_* is necessary for calling var args with explicit list - def delay(by: Int) = CycleTask[T](step + by, run:_*) - } - - - /** - Takes in a list of cycle tasks, sorts them by timestep to execute and runs until all cycletasks are done - */ - case class IoSpec[T <: Module]( - instructions: Seq[CycleTask[T]], - component: T - ){ - val lastStep = instructions.maxBy(_.step).step - val instructionsMap = instructions.groupBy(_.step) - - class tester(c: T) extends PeekPokeTester(c) - val myTester: PeekPokeTester[T] = new tester(component) { - for(ii <- 0 to lastStep){ - instructionsMap.getOrElse(ii, Nil).foreach(_.run.foreach(t => t(this))) - step(1) - } - } - } - - -} - -class testUtilSpec extends FlatSpec with Matchers { - import testUtils._ - - val ins = List[CycleTask[daisyVector]]( - CycleTask( - 1, - d => d.poke(d.dut.io.dataIn, 1), - d => d.expect(d.dut.io.dataOut, 0, s"fail at step ${d.t}") - ) - ) - - - behavior of "my simple test harness attempt" - it should "not NPE" in { - iotesters.Driver.execute(() => new daisyVector(4, 32), new TesterOptionsManager) { c => - - val myTest = IoSpec[daisyVector](ins, c) - - myTest.myTester - - } should be(true) - } - -} diff --git a/ov0/test_run_dir/Core.CoreMain1039581728/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain1039581728/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain1039581728/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain1083714348/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain1083714348/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain1083714348/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain1235086389/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain1235086389/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain1235086389/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain1237797471/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain1237797471/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain1237797471/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain1341624143/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain1341624143/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain1341624143/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain1384621276/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain1384621276/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain1384621276/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain1414129309/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain1414129309/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain1414129309/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain1511946949/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain1511946949/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain1511946949/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain1700476185/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain1700476185/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain1700476185/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain1803099112/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain1803099112/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain1803099112/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain1902845525/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain1902845525/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain1902845525/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain26358827/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain26358827/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain26358827/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain307141193/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain307141193/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain307141193/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain490998982/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain490998982/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain490998982/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain534289158/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain534289158/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain534289158/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain665881311/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain665881311/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain665881311/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain740971381/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain740971381/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain740971381/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain926682035/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain926682035/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain926682035/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov0/test_run_dir/Core.CoreMain955440956/daisyMultiplier.anno.json b/ov0/test_run_dir/Core.CoreMain955440956/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov0/test_run_dir/Core.CoreMain955440956/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/build.sbt b/ov1/build.sbt deleted file mode 100644 index 26e65d0..0000000 --- a/ov1/build.sbt +++ /dev/null @@ -1,52 +0,0 @@ -def scalacOptionsVersion(scalaVersion: String): Seq[String] = { - Seq() ++ { - // If we're building with Scala > 2.11, enable the compile option - // switch to support our anonymous Bundle definitions: - // https://github.com/scala/bug/issues/10047 - CrossVersion.partialVersion(scalaVersion) match { - case Some((2, scalaMajor: Long)) if scalaMajor < 12 => Seq() - case _ => Seq("-Xsource:2.11") - } - } -} - -def javacOptionsVersion(scalaVersion: String): Seq[String] = { - Seq() ++ { - // Scala 2.12 requires Java 8. We continue to generate - // Java 7 compatible code for Scala 2.11 - // for compatibility with old clients. - CrossVersion.partialVersion(scalaVersion) match { - case Some((2, scalaMajor: Long)) if scalaMajor < 12 => - Seq("-source", "1.7", "-target", "1.7") - case _ => - Seq("-source", "1.8", "-target", "1.8") - } - } -} - -name := "chisel-module-template" - -version := "3.1.0" - -scalaVersion := "2.12.4" - -crossScalaVersions := Seq("2.11.12", "2.12.4") - -resolvers ++= Seq( - Resolver.sonatypeRepo("snapshots"), - Resolver.sonatypeRepo("releases") -) - -// Provide a managed dependency on X if -DXVersion="" is supplied on the command line. -val defaultVersions = Map( - "chisel3" -> "3.1.+", - "chisel-iotesters" -> "1.2.+" - ) - -libraryDependencies ++= (Seq("chisel3","chisel-iotesters").map { - dep: String => "edu.berkeley.cs" %% dep % sys.props.getOrElse(dep + "Version", defaultVersions(dep)) }) - -scalacOptions ++= scalacOptionsVersion(scalaVersion.value) -scalacOptions ++= Seq("-language:reflectiveCalls") - -javacOptions ++= javacOptionsVersion(scalaVersion.value) diff --git a/ov1/project/build.properties b/ov1/project/build.properties deleted file mode 100644 index c4dc11b..0000000 --- a/ov1/project/build.properties +++ /dev/null @@ -1 +0,0 @@ -sbt.version = 1.1.0 diff --git a/ov1/src/main/scala/Const.scala b/ov1/src/main/scala/Const.scala deleted file mode 100644 index 751332e..0000000 --- a/ov1/src/main/scala/Const.scala +++ /dev/null @@ -1,256 +0,0 @@ -package Ov1 - -import chisel3._ -import chisel3.util._ -import chisel3.core.Input -import chisel3.iotesters.PeekPokeTester - - -object Instructions { - def BEQ = BitPat("b?????????????????000?????1100011") - def BNE = BitPat("b?????????????????001?????1100011") - def BLT = BitPat("b?????????????????100?????1100011") - def BGE = BitPat("b?????????????????101?????1100011") - def BLTU = BitPat("b?????????????????110?????1100011") - def BGEU = BitPat("b?????????????????111?????1100011") - def JALR = BitPat("b?????????????????000?????1100111") - def JAL = BitPat("b?????????????????????????1101111") - def LUI = BitPat("b?????????????????????????0110111") - def AUIPC = BitPat("b?????????????????????????0010111") - def ADDI = BitPat("b?????????????????000?????0010011") - def SLLI = BitPat("b000000???????????001?????0010011") - def SLTI = BitPat("b?????????????????010?????0010011") - def SLTIU = BitPat("b?????????????????011?????0010011") - def XORI = BitPat("b?????????????????100?????0010011") - def SRLI = BitPat("b000000???????????101?????0010011") - def SRAI = BitPat("b010000???????????101?????0010011") - def ORI = BitPat("b?????????????????110?????0010011") - def ANDI = BitPat("b?????????????????111?????0010011") - def ADD = BitPat("b0000000??????????000?????0110011") - def SUB = BitPat("b0100000??????????000?????0110011") - def SLL = BitPat("b0000000??????????001?????0110011") - def SLT = BitPat("b0000000??????????010?????0110011") - def SLTU = BitPat("b0000000??????????011?????0110011") - def XOR = BitPat("b0000000??????????100?????0110011") - def SRL = BitPat("b0000000??????????101?????0110011") - def SRA = BitPat("b0100000??????????101?????0110011") - def OR = BitPat("b0000000??????????110?????0110011") - def AND = BitPat("b0000000??????????111?????0110011") - def ADDIW = BitPat("b?????????????????000?????0011011") - def SLLIW = BitPat("b0000000??????????001?????0011011") - def SRLIW = BitPat("b0000000??????????101?????0011011") - def SRAIW = BitPat("b0100000??????????101?????0011011") - def ADDW = BitPat("b0000000??????????000?????0111011") - def SUBW = BitPat("b0100000??????????000?????0111011") - def SLLW = BitPat("b0000000??????????001?????0111011") - def SRLW = BitPat("b0000000??????????101?????0111011") - def SRAW = BitPat("b0100000??????????101?????0111011") - def LB = BitPat("b?????????????????000?????0000011") - def LH = BitPat("b?????????????????001?????0000011") - def LW = BitPat("b?????????????????010?????0000011") - def LD = BitPat("b?????????????????011?????0000011") - def LBU = BitPat("b?????????????????100?????0000011") - def LHU = BitPat("b?????????????????101?????0000011") - def LWU = BitPat("b?????????????????110?????0000011") - def SB = BitPat("b?????????????????000?????0100011") - def SH = BitPat("b?????????????????001?????0100011") - def SW = BitPat("b?????????????????010?????0100011") - def SD = BitPat("b?????????????????011?????0100011") - def FENCE = BitPat("b?????????????????000?????0001111") - def FENCE_I = BitPat("b?????????????????001?????0001111") - def MUL = BitPat("b0000001??????????000?????0110011") - def MULH = BitPat("b0000001??????????001?????0110011") - def MULHSU = BitPat("b0000001??????????010?????0110011") - def MULHU = BitPat("b0000001??????????011?????0110011") - def DIV = BitPat("b0000001??????????100?????0110011") - def DIVU = BitPat("b0000001??????????101?????0110011") - def REM = BitPat("b0000001??????????110?????0110011") - def REMU = BitPat("b0000001??????????111?????0110011") - def MULW = BitPat("b0000001??????????000?????0111011") - def DIVW = BitPat("b0000001??????????100?????0111011") - def DIVUW = BitPat("b0000001??????????101?????0111011") - def REMW = BitPat("b0000001??????????110?????0111011") - def REMUW = BitPat("b0000001??????????111?????0111011") - def LR_W = BitPat("b00010??00000?????010?????0101111") - def SC_W = BitPat("b00011????????????010?????0101111") - def LR_D = BitPat("b00010??00000?????011?????0101111") - def SC_D = BitPat("b00011????????????011?????0101111") - def ECALL = BitPat("b00000000000000000000000001110011") - def EBREAK = BitPat("b00000000000100000000000001110011") - def URET = BitPat("b00000000001000000000000001110011") - def MRET = BitPat("b00110000001000000000000001110011") - def DRET = BitPat("b01111011001000000000000001110011") - def SFENCE_VMA = BitPat("b0001001??????????000000001110011") - def WFI = BitPat("b00010000010100000000000001110011") - def CSRRW = BitPat("b?????????????????001?????1110011") - def CSRRS = BitPat("b?????????????????010?????1110011") - def CSRRC = BitPat("b?????????????????011?????1110011") - def CSRRWI = BitPat("b?????????????????101?????1110011") - def CSRRSI = BitPat("b?????????????????110?????1110011") - def CSRRCI = BitPat("b?????????????????111?????1110011") - def CUSTOM0 = BitPat("b?????????????????000?????0001011") - def CUSTOM0_RS1 = BitPat("b?????????????????010?????0001011") - def CUSTOM0_RS1_RS2 = BitPat("b?????????????????011?????0001011") - def CUSTOM0_RD = BitPat("b?????????????????100?????0001011") - def CUSTOM0_RD_RS1 = BitPat("b?????????????????110?????0001011") - def CUSTOM0_RD_RS1_RS2 = BitPat("b?????????????????111?????0001011") - def CUSTOM1 = BitPat("b?????????????????000?????0101011") - def CUSTOM1_RS1 = BitPat("b?????????????????010?????0101011") - def CUSTOM1_RS1_RS2 = BitPat("b?????????????????011?????0101011") - def CUSTOM1_RD = BitPat("b?????????????????100?????0101011") - def CUSTOM1_RD_RS1 = BitPat("b?????????????????110?????0101011") - def CUSTOM1_RD_RS1_RS2 = BitPat("b?????????????????111?????0101011") - def CUSTOM2 = BitPat("b?????????????????000?????1011011") - def CUSTOM2_RS1 = BitPat("b?????????????????010?????1011011") - def CUSTOM2_RS1_RS2 = BitPat("b?????????????????011?????1011011") - def CUSTOM2_RD = BitPat("b?????????????????100?????1011011") - def CUSTOM2_RD_RS1 = BitPat("b?????????????????110?????1011011") - def CUSTOM2_RD_RS1_RS2 = BitPat("b?????????????????111?????1011011") - def CUSTOM3 = BitPat("b?????????????????000?????1111011") - def CUSTOM3_RS1 = BitPat("b?????????????????010?????1111011") - def CUSTOM3_RS1_RS2 = BitPat("b?????????????????011?????1111011") - def CUSTOM3_RD = BitPat("b?????????????????100?????1111011") - def CUSTOM3_RD_RS1 = BitPat("b?????????????????110?????1111011") - def CUSTOM3_RD_RS1_RS2 = BitPat("b?????????????????111?????1111011") - def SLLI_RV32 = BitPat("b0000000??????????001?????0010011") - def SRLI_RV32 = BitPat("b0000000??????????101?????0010011") - def SRAI_RV32 = BitPat("b0100000??????????101?????0010011") - def RDCYCLE = BitPat("b11000000000000000010?????1110011") - def RDTIME = BitPat("b11000000000100000010?????1110011") - def RDINSTRET = BitPat("b11000000001000000010?????1110011") - def RDCYCLEH = BitPat("b11001000000000000010?????1110011") - def RDTIMEH = BitPat("b11001000000100000010?????1110011") - def RDINSTRETH = BitPat("b11001000001000000010?????1110011") -} - - -object ScalarOpConstants -{ - //************************************ - // Control Signals - - val Y = true.B - val N = false.B - - // PC Select Signal - val PC_4 = 0.asUInt(3.W) // PC + 4 - val PC_BR = 1.asUInt(3.W) // branch_target - val PC_J = 2.asUInt(3.W) // jump_target - val PC_JR = 3.asUInt(3.W) // jump_reg_target - val PC_EXC = 4.asUInt(3.W) // exception - - // Branch Type - val BR_N = 0.asUInt(4.W) // Next - val BR_NE = 1.asUInt(4.W) // Branch on NotEqual - val BR_EQ = 2.asUInt(4.W) // Branch on Equal - val BR_GE = 3.asUInt(4.W) // Branch on Greater/Equal - val BR_GEU = 4.asUInt(4.W) // Branch on Greater/Equal Unsigned - val BR_LT = 5.asUInt(4.W) // Branch on Less Than - val BR_LTU = 6.asUInt(4.W) // Branch on Less Than Unsigned - val BR_J = 7.asUInt(4.W) // Jump - val BR_JR = 8.asUInt(4.W) // Jump Register - - // RS1 Operand Select Signal - val OP1_RS1 = 0.asUInt(2.W) // Register Source #1 - val OP1_IMU = 1.asUInt(2.W) // immediate, U-type - val OP1_IMZ = 2.asUInt(2.W) // Zero-extended rs1 field of inst, for CSRI instructions - val OP1_X = 0.asUInt(2.W) - - // RS2 Operand Select Signal - val OP2_RS2 = 0.asUInt(2.W) // Register Source #2 - val OP2_IMI = 1.asUInt(2.W) // immediate, I-type - val OP2_IMS = 2.asUInt(2.W) // immediate, S-type - val OP2_PC = 3.asUInt(2.W) // PC - val OP2_X = 0.asUInt(2.W) - - // Register File Write Enable Signal - val REN_0 = false.B - val REN_1 = true.B - val REN_X = false.B - - // ALU Operation Signal - val ALU_ADD = 1.asUInt(4.W) - val ALU_SUB = 2.asUInt(4.W) - val ALU_SLL = 3.asUInt(4.W) - val ALU_SRL = 4.asUInt(4.W) - val ALU_SRA = 5.asUInt(4.W) - val ALU_AND = 6.asUInt(4.W) - val ALU_OR = 7.asUInt(4.W) - val ALU_XOR = 8.asUInt(4.W) - val ALU_SLT = 9.asUInt(4.W) - val ALU_SLTU= 10.asUInt(4.W) - val ALU_COPY1= 11.asUInt(4.W) - val ALU_X = 0.asUInt(4.W) - - // Writeback Select Signal - val WB_ALU = 0.asUInt(2.W) - val WB_MEM = 1.asUInt(2.W) - val WB_PC4 = 2.asUInt(2.W) - val WB_CSR = 3.asUInt(2.W) - val WB_X = 0.asUInt(2.W) - - // Memory Function Type (Read,Write,Fence) Signal - val MWR_R = 0.asUInt(2.W) - val MWR_W = 1.asUInt(2.W) - val MWR_F = 2.asUInt(2.W) - val MWR_X = 0.asUInt(2.W) - - // Memory Enable Signal - val MEN_0 = Bool(false) - val MEN_1 = Bool(true) - val MEN_X = Bool(false) - - // Memory Mask Type Signal - val MSK_B = 0.asUInt(3.W) - val MSK_BU = 1.asUInt(3.W) - val MSK_H = 2.asUInt(3.W) - val MSK_HU = 3.asUInt(3.W) - val MSK_W = 4.asUInt(3.W) - val MSK_X = 4.asUInt(3.W) - - - // Cache Flushes & Sync Primitives - val M_N = 0.asUInt(3.W) - val M_SI = 1.asUInt(3.W) // synch instruction stream - val M_SD = 2.asUInt(3.W) // synch data stream - val M_FA = 3.asUInt(3.W) // flush all caches - val M_FD = 4.asUInt(3.W) // flush data cache - - // Memory Functions (read, write, fence) - val MT_READ = 0.asUInt(2.W) - val MT_WRITE = 1.asUInt(2.W) - val MT_FENCE = 2.asUInt(2.W) - -} - -object MemoryOpConstants -{ - val MT_X = 0.asUInt(3.W) - val MT_B = 1.asUInt(3.W) - val MT_H = 2.asUInt(3.W) - val MT_W = 3.asUInt(3.W) - val MT_D = 4.asUInt(3.W) - val MT_BU = 5.asUInt(3.W) - val MT_HU = 6.asUInt(3.W) - val MT_WU = 7.asUInt(3.W) - - val M_X = "b0".asUInt(1.W) - val M_XRD = "b0".asUInt(1.W) // int load - val M_XWR = "b1".asUInt(1.W) // int store - - val DPORT = 0 - val IPORT = 1 -} - -object CSR -{ - // commands - val SZ = 3.W - val X = 0.asUInt(SZ) - val Nc = 0.asUInt(SZ) - val W = 1.asUInt(SZ) - val S = 2.asUInt(SZ) - val C = 3.asUInt(SZ) - val I = 4.asUInt(SZ) - val R = 5.asUInt(SZ) -} diff --git a/ov1/src/main/scala/Decoder.scala b/ov1/src/main/scala/Decoder.scala deleted file mode 100644 index c2fa0d4..0000000 --- a/ov1/src/main/scala/Decoder.scala +++ /dev/null @@ -1,31 +0,0 @@ -package Ov1 - -import chisel3._ -import chisel3.core.Input -import chisel3.iotesters.PeekPokeTester - -/** - Decoder should read the top 6 bits and output - - Branch - MemRead - MemtoReg - ALUOp - memWrite - ALUSrc - RegWrite - */ - -class ControlSignals extends Bundle(){ - val Branch = Output(Bool()) - val MemRead = Output(Bool()) - val MemtoReg = Output(Bool()) - val MemWrite = Output(Bool()) - val ALUSrc = Output(Bool()) - val RegWrite = Output(Bool()) - -} - -// class myDecoder(val hurr: Int) extends Module { - -// } diff --git a/ov1/src/main/scala/Defs.scala b/ov1/src/main/scala/Defs.scala deleted file mode 100644 index 7faf837..0000000 --- a/ov1/src/main/scala/Defs.scala +++ /dev/null @@ -1,13 +0,0 @@ -package Ov1 - -import chisel3._ -import chisel3.core.Input -import chisel3.iotesters.PeekPokeTester - -object Defs { - - class RType extends Bundle { - - } - -} diff --git a/ov1/src/main/scala/Tile.scala b/ov1/src/main/scala/Tile.scala deleted file mode 100644 index e37fa01..0000000 --- a/ov1/src/main/scala/Tile.scala +++ /dev/null @@ -1,122 +0,0 @@ -package Ov1 - -import chisel3._ -import chisel3.util._ -import chisel3.core.Input -import chisel3.iotesters.PeekPokeTester - - -object CoreMain { - def main(args: Array[String]): Unit = { - - iotesters.Driver.execute(args, () => new Tile()) { - c => new TileTest(c) - } - } -} - -class Tile() extends Module{ - - val io = IO( - new Bundle { - val instruction = Input(UInt(32.W)) - val opcode = Output(UInt(7.W)) - val immediate = Output(UInt(12.W)) - }) - - class Itype extends Bundle { - val opcode = UInt(7.W) - val rd = UInt(5.W) - val funct3 = UInt(3.W) - val rs1 = UInt(5.W) - val immediate = UInt(12.W) - } - - import Instructions._ - import ScalarOpConstants._ - import MemoryOpConstants._ - import CSR._ - - val memes = io.instruction.asTypeOf(new Itype) - io.opcode := memes.opcode - io.immediate := memes.immediate - - val defaultSignals = List(N, BR_N , OP1_X , OP2_X , ALU_X , WB_X , REN_0, MEN_0, M_X , MT_X, CSR.Nc) - - val ControlSignals = ListLookup(io.instruction, - defaultSignals, - Array( /* val | BR | op1 | op2 | ALU | wb | rf | mem | mem | mask | csr */ - /* inst | type | sel | sel | fcn | sel | wen | en | wr | type | cmd */ - LW -> List(Y, BR_N , OP1_RS1, OP2_IMI , ALU_ADD , WB_MEM, REN_1, MEN_1, M_XRD, MT_W, CSR.Nc), - LB -> List(Y, BR_N , OP1_RS1, OP2_IMI , ALU_ADD , WB_MEM, REN_1, MEN_1, M_XRD, MT_B, CSR.Nc), - LBU -> List(Y, BR_N , OP1_RS1, OP2_IMI , ALU_ADD , WB_MEM, REN_1, MEN_1, M_XRD, MT_BU, CSR.Nc), - LH -> List(Y, BR_N , OP1_RS1, OP2_IMI , ALU_ADD , WB_MEM, REN_1, MEN_1, M_XRD, MT_H, CSR.Nc), - LHU -> List(Y, BR_N , OP1_RS1, OP2_IMI , ALU_ADD , WB_MEM, REN_1, MEN_1, M_XRD, MT_HU, CSR.Nc), - SW -> List(Y, BR_N , OP1_RS1, OP2_IMS , ALU_ADD , WB_X , REN_0, MEN_1, M_XWR, MT_W, CSR.Nc), - SB -> List(Y, BR_N , OP1_RS1, OP2_IMS , ALU_ADD , WB_X , REN_0, MEN_1, M_XWR, MT_B, CSR.Nc), - SH -> List(Y, BR_N , OP1_RS1, OP2_IMS , ALU_ADD , WB_X , REN_0, MEN_1, M_XWR, MT_H, CSR.Nc), - - AUIPC -> List(Y, BR_N , OP1_IMU, OP2_PC , ALU_ADD , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - LUI -> List(Y, BR_N , OP1_IMU, OP2_X , ALU_COPY1, WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - - ADDI -> List(Y, BR_N , OP1_RS1, OP2_IMI , ALU_ADD , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - ANDI -> List(Y, BR_N , OP1_RS1, OP2_IMI , ALU_AND , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - ORI -> List(Y, BR_N , OP1_RS1, OP2_IMI , ALU_OR , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - XORI -> List(Y, BR_N , OP1_RS1, OP2_IMI , ALU_XOR , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - SLTI -> List(Y, BR_N , OP1_RS1, OP2_IMI , ALU_SLT , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - SLTIU -> List(Y, BR_N , OP1_RS1, OP2_IMI , ALU_SLTU, WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - SLLI -> List(Y, BR_N , OP1_RS1, OP2_IMI , ALU_SLL , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - SRAI -> List(Y, BR_N , OP1_RS1, OP2_IMI , ALU_SRA , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - SRLI -> List(Y, BR_N , OP1_RS1, OP2_IMI , ALU_SRL , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - - SLL -> List(Y, BR_N , OP1_RS1, OP2_RS2 , ALU_SLL , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - ADD -> List(Y, BR_N , OP1_RS1, OP2_RS2 , ALU_ADD , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - SUB -> List(Y, BR_N , OP1_RS1, OP2_RS2 , ALU_SUB , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - SLT -> List(Y, BR_N , OP1_RS1, OP2_RS2 , ALU_SLT , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - SLTU -> List(Y, BR_N , OP1_RS1, OP2_RS2 , ALU_SLTU, WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - AND -> List(Y, BR_N , OP1_RS1, OP2_RS2 , ALU_AND , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - OR -> List(Y, BR_N , OP1_RS1, OP2_RS2 , ALU_OR , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - XOR -> List(Y, BR_N , OP1_RS1, OP2_RS2 , ALU_XOR , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - SRA -> List(Y, BR_N , OP1_RS1, OP2_RS2 , ALU_SRA , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - SRL -> List(Y, BR_N , OP1_RS1, OP2_RS2 , ALU_SRL , WB_ALU, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - - JAL -> List(Y, BR_J , OP1_X , OP2_X , ALU_X , WB_PC4, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - JALR -> List(Y, BR_JR , OP1_RS1, OP2_IMI , ALU_X , WB_PC4, REN_1, MEN_0, M_X , MT_X, CSR.Nc), - BEQ -> List(Y, BR_EQ , OP1_X , OP2_X , ALU_X , WB_X , REN_0, MEN_0, M_X , MT_X, CSR.Nc), - BNE -> List(Y, BR_NE , OP1_X , OP2_X , ALU_X , WB_X , REN_0, MEN_0, M_X , MT_X, CSR.Nc), - BGE -> List(Y, BR_GE , OP1_X , OP2_X , ALU_X , WB_X , REN_0, MEN_0, M_X , MT_X, CSR.Nc), - BGEU -> List(Y, BR_GEU, OP1_X , OP2_X , ALU_X , WB_X , REN_0, MEN_0, M_X , MT_X, CSR.Nc), - BLT -> List(Y, BR_LT , OP1_X , OP2_X , ALU_X , WB_X , REN_0, MEN_0, M_X , MT_X, CSR.Nc), - BLTU -> List(Y, BR_LTU, OP1_X , OP2_X , ALU_X , WB_X , REN_0, MEN_0, M_X , MT_X, CSR.Nc), - - CSRRWI -> List(Y, BR_N , OP1_IMZ, OP2_X , ALU_COPY1, WB_CSR, REN_1, MEN_0, M_X , MT_X, CSR.W), - CSRRSI -> List(Y, BR_N , OP1_IMZ, OP2_X , ALU_COPY1, WB_CSR, REN_1, MEN_0, M_X , MT_X, CSR.S), - CSRRCI -> List(Y, BR_N , OP1_IMZ, OP2_X , ALU_COPY1, WB_CSR, REN_1, MEN_0, M_X , MT_X, CSR.C), - CSRRW -> List(Y, BR_N , OP1_RS1, OP2_X , ALU_COPY1, WB_CSR, REN_1, MEN_0, M_X , MT_X, CSR.W), - CSRRS -> List(Y, BR_N , OP1_RS1, OP2_X , ALU_COPY1, WB_CSR, REN_1, MEN_0, M_X , MT_X, CSR.S), - CSRRC -> List(Y, BR_N , OP1_RS1, OP2_X , ALU_COPY1, WB_CSR, REN_1, MEN_0, M_X , MT_X, CSR.C), - - ECALL -> List(Y, BR_N , OP1_X , OP2_X , ALU_X , WB_X , REN_0, MEN_0, M_X , MT_X, CSR.I), - MRET -> List(Y, BR_N , OP1_X , OP2_X , ALU_X , WB_X , REN_0, MEN_0, M_X , MT_X, CSR.I), - DRET -> List(Y, BR_N , OP1_X , OP2_X , ALU_X , WB_X , REN_0, MEN_0, M_X , MT_X, CSR.I), - EBREAK -> List(Y, BR_N , OP1_X , OP2_X , ALU_X , WB_X , REN_0, MEN_0, M_X , MT_X, CSR.I), - WFI -> List(Y, BR_N , OP1_X , OP2_X , ALU_X , WB_X , REN_0, MEN_0, M_X , MT_X, CSR.Nc), // implemented as a NOP - - FENCE_I -> List(Y, BR_N , OP1_X , OP2_X , ALU_X , WB_X , REN_0, MEN_0, M_X , MT_X, CSR.Nc), - FENCE -> List(Y, BR_N , OP1_X , OP2_X , ALU_X , WB_X , REN_0, MEN_1, M_X , MT_X, CSR.Nc) - // we are already sequentially consistent, so no need to honor the fence instruction - )) -} - -class TileTest(c: Tile) extends PeekPokeTester(c) { - - println("yo") - step(1) - poke(c.io.instruction, 0xAABB) - val hurr = peek(c.io.opcode) - val durr = peek(c.io.immediate) - println(hurr.toString) - println(durr.toString) - step(1) - -} diff --git a/ov1/test_run_dir/Core.CoreMain1039581728/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain1039581728/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain1039581728/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain1083714348/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain1083714348/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain1083714348/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain1235086389/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain1235086389/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain1235086389/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain1237797471/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain1237797471/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain1237797471/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain1341624143/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain1341624143/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain1341624143/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain1384621276/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain1384621276/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain1384621276/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain1414129309/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain1414129309/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain1414129309/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain1511946949/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain1511946949/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain1511946949/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain1700476185/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain1700476185/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain1700476185/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain1803099112/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain1803099112/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain1803099112/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain1902845525/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain1902845525/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain1902845525/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain26358827/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain26358827/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain26358827/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain307141193/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain307141193/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain307141193/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain490998982/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain490998982/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain490998982/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain534289158/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain534289158/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain534289158/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain665881311/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain665881311/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain665881311/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain740971381/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain740971381/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain740971381/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain926682035/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain926682035/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain926682035/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Core.CoreMain955440956/daisyMultiplier.anno.json b/ov1/test_run_dir/Core.CoreMain955440956/daisyMultiplier.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Core.CoreMain955440956/daisyMultiplier.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain1236591989/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain1236591989/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain1236591989/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain1250448684/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain1250448684/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain1250448684/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain1448190335/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain1448190335/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain1448190335/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain1540352323/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain1540352323/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain1540352323/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain1648882666/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain1648882666/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain1648882666/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain1666748901/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain1666748901/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain1666748901/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain1679306966/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain1679306966/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain1679306966/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain176004999/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain176004999/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain176004999/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain1793740547/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain1793740547/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain1793740547/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain1795497740/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain1795497740/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain1795497740/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain1891176739/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain1891176739/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain1891176739/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain2094814482/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain2094814482/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain2094814482/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain21940405/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain21940405/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain21940405/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain236087905/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain236087905/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain236087905/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain378523536/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain378523536/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain378523536/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain472595777/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain472595777/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain472595777/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain509298891/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain509298891/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain509298891/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain523467091/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain523467091/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain523467091/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain656673641/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain656673641/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain656673641/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain728873685/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain728873685/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain728873685/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/ov1/test_run_dir/Ov1.CoreMain849836610/Tile.anno.json b/ov1/test_run_dir/Ov1.CoreMain849836610/Tile.anno.json deleted file mode 100644 index c9c513b..0000000 --- a/ov1/test_run_dir/Ov1.CoreMain849836610/Tile.anno.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - -] \ No newline at end of file diff --git a/project/Dependencies.scala b/project/Dependencies.scala new file mode 100644 index 0000000..15d339e --- /dev/null +++ b/project/Dependencies.scala @@ -0,0 +1,40 @@ +import sbt._ + +object Dependencies { + + val fs2Version = "1.0.0" + val catsVersion = "1.4.0" + val catsEffectVersion = "1.0.0" + + // Dependencies for JVM part of code + val backendDeps = Def.setting( + Seq( + "com.lihaoyi" %% "sourcecode" % "0.1.4", // expert println debugging + "com.lihaoyi" %% "pprint" % "0.5.3", // pretty print for types and case classes + "org.typelevel" %% "cats-core" % catsVersion, // abstract category dork stuff + + "com.chuusai" %% "shapeless" % "2.3.2", // Abstract level category dork stuff + + "joda-time" % "joda-time" % "2.9.9", + "org.joda" % "joda-convert" % "2.0.1", + + "org.typelevel" %% "cats-effect" % catsEffectVersion, // IO monad category wank + + "co.fs2" %% "fs2-core" % fs2Version, // The best library + "co.fs2" %% "fs2-io" % fs2Version, // The best library + + "com.beachape" %% "enumeratum" % "1.5.13", + "com.github.nscala-time" %% "nscala-time" % "2.16.0", // Time + + "org.tpolecat" %% "atto-core" % "0.6.3", + "org.tpolecat" %% "atto-refined" % "0.6.3", + + "org.typelevel" %% "spire" % "0.14.1", + + "io.estatico" %% "newtype" % "0.4.2", + + "com.github.pathikrit" %% "better-files" % "3.7.0", + + "org.atnos" %% "eff" % "5.2.0" + )) +} diff --git a/ov0/project/build.properties b/project/build.properties similarity index 100% rename from ov0/project/build.properties rename to project/build.properties diff --git a/src/main/scala/Tile.scala b/src/main/scala/Tile.scala new file mode 100644 index 0000000..139597f --- /dev/null +++ b/src/main/scala/Tile.scala @@ -0,0 +1,2 @@ + + diff --git a/src/test/scala/Example.scala b/src/test/scala/Example.scala new file mode 100644 index 0000000..6be2e1e --- /dev/null +++ b/src/test/scala/Example.scala @@ -0,0 +1,176 @@ +/** + * This code supplements instructions.org + * Once you've gone through the instructions you can do + * whatever you want with it. + */ +package Ex0 + +import chisel3._ +import chisel3.iotesters.PeekPokeTester +import org.scalatest.{Matchers, FlatSpec} +import TestUtils._ + +// class MyVector() extends Module { +// val io = IO( +// new Bundle { +// val idx = Input(UInt(32.W)) +// val out = Output(UInt(32.W)) +// } +// ) + +// val values = List(1, 2, 3, 4) + +// io.out := values(io.idx) +// } + +// class MyVector() extends Module { +// val io = IO( +// new Bundle { +// val idx = Input(UInt(32.W)) +// val out = Output(UInt(32.W)) +// } +// ) + +// // val values: List[Int] = List(1, 2, 3, 4) +// val values = Vec(1, 2, 3, 4) + +// io.out := values(io.idx) +// } + +class MyVector() extends Module { + val io = IO( + new Bundle { + val idx = Input(UInt(32.W)) + val out = Output(UInt(32.W)) + } + ) + + val values = Vec(0.U, 1.U, 2.U, 3.U) + + io.out := values(io.idx) +} + + +class MyVector2() extends Module { + val io = IO( + new Bundle { + val idx = Input(UInt(2.W)) + val out = Output(UInt(32.W)) + } + ) + + val values = Array(0.U, 1.U, 2.U, 3.U) + + val myWire = Wire(UInt(4.W)) + io.out := values(0) + for(ii <- 0 until 4){ + when(io.idx === ii.U){ + io.out := values(ii) + } + } +} + + +class MyVecSpec extends FlatSpec with Matchers { + behavior of "MyVec" + + it should "Output whatever idx points to" in { + wrapTester( + chisel3.iotesters.Driver(() => new MyVector2) { c => + new MyVecTester(c) + } should be(true) + ) + } +} + + +class MyVecTester(c: MyVector2) extends PeekPokeTester(c) { + for(ii <- 0 until 4){ + poke(c.io.idx, ii) + expect(c.io.out, ii) + } +} + + +class Invalid() extends Module { + val io = IO(new Bundle{}) + + val myVec = Module(new MyVector) + + // Uncomment line below to make the circuit valid + // myVec.io.idx := 0.U +} + + +/** + * This goes a little beyond the example in exercise.org. + * WrapTest is a simple wrapper that catches Unconnected wires + * and prints them with a less scary stacktrace. + * Additionally, we throw a RunTimeException instead of ??? for + * similar reasons + * + */ +class InvalidSpec extends FlatSpec with Matchers { + behavior of "Invalid" + + it should "Fail with a RefNotInitializedException" in { + try { + wrapTester( + chisel3.iotesters.Driver(() => new Invalid) { c => + + // Just a placeholder so it compiles + throw new RuntimeException with scala.util.control.NoStackTrace + } should be(true) + ) + } + catch { + case e: RuntimeException => println("all good!") + case e: Exception => throw e + } + } +} + + +class SimpleDelay() extends Module { + val io = IO( + new Bundle { + val dataIn = Input(UInt(32.W)) + val dataOut = Output(UInt(32.W)) + } + ) + val delayReg = RegInit(UInt(32.W), 0.U) + + delayReg := io.dataIn + io.dataOut := delayReg +} + + +class DelaySpec extends FlatSpec with Matchers { + behavior of "SimpleDelay" + + it should "Delay input by one timestep" in { + wrapTester( + chisel3.iotesters.Driver(() => new SimpleDelay) { c => + new DelayTester(c) + } should be(true) + ) + } +} + + +// class DelayTester(c: SimpleDelay) extends PeekPokeTester(c) { +// for(ii <- 0 until 10){ +// val input = scala.util.Random.nextInt(10) +// poke(c.io.dataIn, input) +// expect(c.io.dataOut, input) +// } +// } + +class DelayTester(c: SimpleDelay) extends PeekPokeTester(c) { + for(ii <- 0 until 10){ + val input = scala.util.Random.nextInt(10) + poke(c.io.dataIn, input) + step(1) + expect(c.io.dataOut, input) + } +} diff --git a/src/test/scala/TestUtils.scala b/src/test/scala/TestUtils.scala new file mode 100644 index 0000000..b26d032 --- /dev/null +++ b/src/test/scala/TestUtils.scala @@ -0,0 +1,28 @@ +package Ex0 + +import chisel3._ +import chisel3.iotesters.PeekPokeTester +import org.scalatest.{Matchers, FlatSpec} + +object TestUtils { + + def wrapTester(test: => Unit): Unit = { + try { test } + catch { + case e: firrtl.passes.CheckInitialization.RefNotInitializedException => { + println("##########################################################") + println("##########################################################") + println("##########################################################") + println("Your design has unconnected wires!") + println("error:\n") + println(e.getMessage) + println("") + println("") + println("##########################################################") + println("##########################################################") + println("##########################################################") + } + case e: Exception => throw e + } + } +}