Procházet zdrojové kódy

Add a lot of crap

master
peteraa před 6 roky
rodič
revize
8b3d539ee1
89 změnil soubory, kde provedl 810 přidání a 2028 odebrání
  1. +12
    -1
      .gitignore
  2. +3
    -23
      TODOs.org
  3. +15
    -0
      build.sbt
  4. +534
    -77
      oppgavetekst.org
  5. +0
    -56
      ov0/src/main/scala/Tile.scala
  6. +0
    -161
      ov0/src/main/scala/basics.scala
  7. +0
    -47
      ov0/src/main/scala/daisyDot.scala
  8. +0
    -44
      ov0/src/main/scala/daisyGrid.scala
  9. +0
    -127
      ov0/src/main/scala/daisyMatMul.scala
  10. +0
    -55
      ov0/src/main/scala/daisyVec.scala
  11. +0
    -150
      ov0/src/main/scala/daisyVecMat.scala
  12. +0
    -40
      ov0/src/main/scala/daisyVecVec.scala
  13. +0
    -45
      ov0/src/main/scala/utils.scala
  14. +0
    -82
      ov0/src/test/scala/daisyDotTest.scala
  15. +0
    -82
      ov0/src/test/scala/daisyGridTest.scala
  16. +0
    -112
      ov0/src/test/scala/daisyMatMulTest.scala
  17. +0
    -116
      ov0/src/test/scala/daisyVecMatTest.scala
  18. +0
    -84
      ov0/src/test/scala/daisyVecTest.scala
  19. +0
    -74
      ov0/src/test/scala/tests.scala
  20. +0
    -3
      ov0/test_run_dir/Core.CoreMain1039581728/daisyMultiplier.anno.json
  21. +0
    -3
      ov0/test_run_dir/Core.CoreMain1083714348/daisyMultiplier.anno.json
  22. +0
    -3
      ov0/test_run_dir/Core.CoreMain1235086389/daisyMultiplier.anno.json
  23. +0
    -3
      ov0/test_run_dir/Core.CoreMain1237797471/daisyMultiplier.anno.json
  24. +0
    -3
      ov0/test_run_dir/Core.CoreMain1341624143/daisyMultiplier.anno.json
  25. +0
    -3
      ov0/test_run_dir/Core.CoreMain1384621276/daisyMultiplier.anno.json
  26. +0
    -3
      ov0/test_run_dir/Core.CoreMain1414129309/daisyMultiplier.anno.json
  27. +0
    -3
      ov0/test_run_dir/Core.CoreMain1511946949/daisyMultiplier.anno.json
  28. +0
    -3
      ov0/test_run_dir/Core.CoreMain1700476185/daisyMultiplier.anno.json
  29. +0
    -3
      ov0/test_run_dir/Core.CoreMain1803099112/daisyMultiplier.anno.json
  30. +0
    -3
      ov0/test_run_dir/Core.CoreMain1902845525/daisyMultiplier.anno.json
  31. +0
    -3
      ov0/test_run_dir/Core.CoreMain26358827/daisyMultiplier.anno.json
  32. +0
    -3
      ov0/test_run_dir/Core.CoreMain307141193/daisyMultiplier.anno.json
  33. +0
    -3
      ov0/test_run_dir/Core.CoreMain490998982/daisyMultiplier.anno.json
  34. +0
    -3
      ov0/test_run_dir/Core.CoreMain534289158/daisyMultiplier.anno.json
  35. +0
    -3
      ov0/test_run_dir/Core.CoreMain665881311/daisyMultiplier.anno.json
  36. +0
    -3
      ov0/test_run_dir/Core.CoreMain740971381/daisyMultiplier.anno.json
  37. +0
    -3
      ov0/test_run_dir/Core.CoreMain926682035/daisyMultiplier.anno.json
  38. +0
    -3
      ov0/test_run_dir/Core.CoreMain955440956/daisyMultiplier.anno.json
  39. +0
    -52
      ov1/build.sbt
  40. +0
    -1
      ov1/project/build.properties
  41. +0
    -256
      ov1/src/main/scala/Const.scala
  42. +0
    -31
      ov1/src/main/scala/Decoder.scala
  43. +0
    -13
      ov1/src/main/scala/Defs.scala
  44. +0
    -122
      ov1/src/main/scala/Tile.scala
  45. +0
    -3
      ov1/test_run_dir/Core.CoreMain1039581728/daisyMultiplier.anno.json
  46. +0
    -3
      ov1/test_run_dir/Core.CoreMain1083714348/daisyMultiplier.anno.json
  47. +0
    -3
      ov1/test_run_dir/Core.CoreMain1235086389/daisyMultiplier.anno.json
  48. +0
    -3
      ov1/test_run_dir/Core.CoreMain1237797471/daisyMultiplier.anno.json
  49. +0
    -3
      ov1/test_run_dir/Core.CoreMain1341624143/daisyMultiplier.anno.json
  50. +0
    -3
      ov1/test_run_dir/Core.CoreMain1384621276/daisyMultiplier.anno.json
  51. +0
    -3
      ov1/test_run_dir/Core.CoreMain1414129309/daisyMultiplier.anno.json
  52. +0
    -3
      ov1/test_run_dir/Core.CoreMain1511946949/daisyMultiplier.anno.json
  53. +0
    -3
      ov1/test_run_dir/Core.CoreMain1700476185/daisyMultiplier.anno.json
  54. +0
    -3
      ov1/test_run_dir/Core.CoreMain1803099112/daisyMultiplier.anno.json
  55. +0
    -3
      ov1/test_run_dir/Core.CoreMain1902845525/daisyMultiplier.anno.json
  56. +0
    -3
      ov1/test_run_dir/Core.CoreMain26358827/daisyMultiplier.anno.json
  57. +0
    -3
      ov1/test_run_dir/Core.CoreMain307141193/daisyMultiplier.anno.json
  58. +0
    -3
      ov1/test_run_dir/Core.CoreMain490998982/daisyMultiplier.anno.json
  59. +0
    -3
      ov1/test_run_dir/Core.CoreMain534289158/daisyMultiplier.anno.json
  60. +0
    -3
      ov1/test_run_dir/Core.CoreMain665881311/daisyMultiplier.anno.json
  61. +0
    -3
      ov1/test_run_dir/Core.CoreMain740971381/daisyMultiplier.anno.json
  62. +0
    -3
      ov1/test_run_dir/Core.CoreMain926682035/daisyMultiplier.anno.json
  63. +0
    -3
      ov1/test_run_dir/Core.CoreMain955440956/daisyMultiplier.anno.json
  64. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain1236591989/Tile.anno.json
  65. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain1250448684/Tile.anno.json
  66. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain1448190335/Tile.anno.json
  67. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain1540352323/Tile.anno.json
  68. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain1648882666/Tile.anno.json
  69. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain1666748901/Tile.anno.json
  70. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain1679306966/Tile.anno.json
  71. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain176004999/Tile.anno.json
  72. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain1793740547/Tile.anno.json
  73. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain1795497740/Tile.anno.json
  74. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain1891176739/Tile.anno.json
  75. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain2094814482/Tile.anno.json
  76. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain21940405/Tile.anno.json
  77. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain236087905/Tile.anno.json
  78. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain378523536/Tile.anno.json
  79. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain472595777/Tile.anno.json
  80. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain509298891/Tile.anno.json
  81. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain523467091/Tile.anno.json
  82. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain656673641/Tile.anno.json
  83. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain728873685/Tile.anno.json
  84. +0
    -3
      ov1/test_run_dir/Ov1.CoreMain849836610/Tile.anno.json
  85. +40
    -0
      project/Dependencies.scala
  86. +0
    -0
      project/build.properties
  87. +2
    -0
      src/main/scala/Tile.scala
  88. +176
    -0
      src/test/scala/Example.scala
  89. +28
    -0
      src/test/scala/TestUtils.scala

+ 12
- 1
.gitignore Zobrazit soubor

@@ -341,4 +341,15 @@ project/plugins/project/
hs_err_pid*

*.fir
*.json
*.json

# ENSIME, metals and friends
.ensime*
.metals*
.bloop*
.projectile
target/
scratchpad.scala
log/
TODO.org
index.html

+ 3
- 23
TODOs.org Zobrazit soubor

@@ -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


ov0/build.sbt → build.sbt Zobrazit soubor

@@ -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")

+ 534
- 77
oppgavetekst.org Zobrazit soubor

@@ -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
<ul>
<li>Name: Siv Jensen, Affiliation: FrP</li>
<li>Name: Jonas Gahr Støre, Affiliation: AP</li>
<li>Name: Bjørnar Moxnes, Affiliation: Rødt</li>
<li>Name: Malcolm Tucker, Affiliation: DOSAC</li>
</ul>
#+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"<li>Name: $nameString, Affiliation: $affiliationString</li>")
}
"<ul>\n" + inner.mkString("\n") + "</ul>"
}

// Or if you prefer brevity
def generateList2(politicians: List[String], affiliations: Map[String, String]): String = {
val inner = politicians.map(p => s"<li>Name: $p, Affiliation ${affiliations(p)}</li>")
"<ul>\n" + inner.mkString("\n") + "</ul>"
}
#+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 </ul> 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?


+ 0
- 56
ov0/src/main/scala/Tile.scala Zobrazit soubor

@@ -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))
}

+ 0
- 161
ov0/src/main/scala/basics.scala Zobrazit soubor

@@ -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)
}
}

+ 0
- 47
ov0/src/main/scala/daisyDot.scala Zobrazit soubor

@@ -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
}

+ 0
- 44
ov0/src/main/scala/daisyGrid.scala Zobrazit soubor

@@ -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
}
}
}

+ 0
- 127
ov0/src/main/scala/daisyMatMul.scala Zobrazit soubor

@@ -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
}

+ 0
- 55
ov0/src/main/scala/daisyVec.scala Zobrazit soubor

@@ -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)
}
}
}

+ 0
- 150
ov0/src/main/scala/daisyVecMat.scala Zobrazit soubor

@@ -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
}

+ 0
- 40
ov0/src/main/scala/daisyVecVec.scala Zobrazit soubor

@@ -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
}

+ 0
- 45
ov0/src/main/scala/utils.scala Zobrazit soubor

@@ -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)))
}

+ 0
- 82
ov0/src/test/scala/daisyDotTest.scala Zobrazit soubor

@@ -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)
}
}

+ 0
- 82
ov0/src/test/scala/daisyGridTest.scala Zobrazit soubor

@@ -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)
}
}

+ 0
- 112
ov0/src/test/scala/daisyMatMulTest.scala Zobrazit soubor

@@ -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)
}
}

+ 0
- 116
ov0/src/test/scala/daisyVecMatTest.scala Zobrazit soubor

@@ -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)
}
}

+ 0
- 84
ov0/src/test/scala/daisyVecTest.scala Zobrazit soubor

@@ -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)
}
}

+ 0
- 74
ov0/src/test/scala/tests.scala Zobrazit soubor

@@ -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)
}

}

+ 0
- 3
ov0/test_run_dir/Core.CoreMain1039581728/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain1083714348/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain1235086389/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain1237797471/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain1341624143/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain1384621276/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain1414129309/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain1511946949/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain1700476185/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain1803099112/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain1902845525/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain26358827/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain307141193/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain490998982/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain534289158/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain665881311/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain740971381/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain926682035/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov0/test_run_dir/Core.CoreMain955440956/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 52
ov1/build.sbt Zobrazit soubor

@@ -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)

+ 0
- 1
ov1/project/build.properties Zobrazit soubor

@@ -1 +0,0 @@
sbt.version = 1.1.0

+ 0
- 256
ov1/src/main/scala/Const.scala Zobrazit soubor

@@ -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)
}

+ 0
- 31
ov1/src/main/scala/Decoder.scala Zobrazit soubor

@@ -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 {

// }

+ 0
- 13
ov1/src/main/scala/Defs.scala Zobrazit soubor

@@ -1,13 +0,0 @@
package Ov1

import chisel3._
import chisel3.core.Input
import chisel3.iotesters.PeekPokeTester

object Defs {

class RType extends Bundle {

}

}

+ 0
- 122
ov1/src/main/scala/Tile.scala Zobrazit soubor

@@ -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)

}

+ 0
- 3
ov1/test_run_dir/Core.CoreMain1039581728/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain1083714348/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain1235086389/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain1237797471/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain1341624143/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain1384621276/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain1414129309/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain1511946949/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain1700476185/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain1803099112/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain1902845525/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain26358827/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain307141193/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain490998982/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain534289158/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain665881311/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain740971381/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain926682035/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Core.CoreMain955440956/daisyMultiplier.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain1236591989/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain1250448684/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain1448190335/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain1540352323/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain1648882666/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain1666748901/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain1679306966/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain176004999/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain1793740547/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain1795497740/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain1891176739/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain2094814482/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain21940405/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain236087905/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain378523536/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain472595777/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain509298891/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain523467091/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain656673641/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain728873685/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 0
- 3
ov1/test_run_dir/Ov1.CoreMain849836610/Tile.anno.json Zobrazit soubor

@@ -1,3 +0,0 @@
[
]

+ 40
- 0
project/Dependencies.scala Zobrazit soubor

@@ -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"
))
}

ov0/project/build.properties → project/build.properties Zobrazit soubor


+ 2
- 0
src/main/scala/Tile.scala Zobrazit soubor

@@ -0,0 +1,2 @@



+ 176
- 0
src/test/scala/Example.scala Zobrazit soubor

@@ -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)
}
}

+ 28
- 0
src/test/scala/TestUtils.scala Zobrazit soubor

@@ -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
}
}
}

Načítá se…
Zrušit
Uložit