commit e4724c6f4afa134b905ed46dd68af6c7acd99f2e Author: peteraa Date: Thu May 3 18:34:34 2018 +0200 init commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ec34061 --- /dev/null +++ b/.gitignore @@ -0,0 +1,339 @@ +### Project Specific stuff +test_run_dir/* +### XilinxISE template +# intermediate build files +*.bgn +*.bit +*.bld +*.cmd_log +*.drc +*.ll +*.lso +*.msd +*.msk +*.ncd +*.ngc +*.ngd +*.ngr +*.pad +*.par +*.pcf +*.prj +*.ptwx +*.rbb +*.rbd +*.stx +*.syr +*.twr +*.twx +*.unroutes +*.ut +*.xpi +*.xst +*_bitgen.xwbt +*_envsettings.html +*_map.map +*_map.mrp +*_map.ngm +*_map.xrpt +*_ngdbuild.xrpt +*_pad.csv +*_pad.txt +*_par.xrpt +*_summary.html +*_summary.xml +*_usage.xml +*_xst.xrpt + +# project-wide generated files +*.gise +par_usage_statistics.html +usage_statistics_webtalk.html +webtalk.log +webtalk_pn.xml + +# generated folders +iseconfig/ +xlnx_auto_0_xdb/ +xst/ +_ngo/ +_xmsgs/ +### Eclipse template +*.pydevproject +.metadata +.gradle +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Java annotation processor (APT) +.factorypath + +# PDT-specific +.buildpath + +# sbteclipse plugin +.target + +# TeXlipse plugin +.texlipse +### C template +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +### SBT template +# Simple Build Tool +# http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control + +target/ +lib_managed/ +src_managed/ +project/boot/ +.history +.cache +### Emacs template +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +### Vim template +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +*.un~ +Session.vim +.netrwhist +*~ +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio + +*.iml + +## Directory-based project format: +.idea/ +# if you remove the above rule, at least ignore the following: + +# User-specific stuff: +# .idea/workspace.xml +# .idea/tasks.xml +# .idea/dictionaries + +# Sensitive or high-churn files: +# .idea/dataSources.ids +# .idea/dataSources.xml +# .idea/sqlDataSources.xml +# .idea/dynamic.xml +# .idea/uiDesigner.xml + +# Gradle: +# .idea/gradle.xml +# .idea/libraries + +# Mongo Explorer plugin: +# .idea/mongoSettings.xml + +## File-based project format: +*.ipr +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +### C++ template +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +### OSX template +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk +### Xcode template +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate +### Scala template +*.class +*.log + +# sbt specific +.cache +.history +.lib/ +dist/* +target/ +lib_managed/ +src_managed/ +project/boot/ +project/plugins/project/ + +# Scala-IDE specific +.scala_dependencies +.worksheet +### Java template +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* diff --git a/TODOs.org b/TODOs.org new file mode 100644 index 0000000..f95a66b --- /dev/null +++ b/TODOs.org @@ -0,0 +1,42 @@ +* Thoughts + For RISC-V bruk SODOR, finn på chisel sia + +* Now +** TODO 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 + +* Øving 0 + +** Praktisk +** Kombinatorisk +*** Få absolutt enkleste krets (mux) til å fungere +*** TODO Tegn RTL for krets med to multiplexere +*** Sett sammen en krets som bruker to multiplexere + +** Tilstand +*** TODO Tegn RTL for en enkel teller +*** Implementer en enkel teller +*** TODO Implementer en enkel registerAvleser +*** Tegn RTL av registeravleser +*** Implementer daisyVec + +** Sette sammen +*** Lag tre daisyVecs som fylles og leses av i en test. +*** Kombiner egenlagd mux med daisyVecs +*** Kombiner til en parametriserbar matrise, med medfølgende tester. +*** Instansier to matriser +*** Multipliser dem diff --git a/build.sbt b/build.sbt new file mode 100644 index 0000000..26e65d0 --- /dev/null +++ b/build.sbt @@ -0,0 +1,52 @@ +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/src/main/scala/Tile.scala b/src/main/scala/Tile.scala new file mode 100644 index 0000000..6daa0a0 --- /dev/null +++ b/src/main/scala/Tile.scala @@ -0,0 +1,58 @@ +package Core +import chisel3._ +import chisel3.core.Input +import chisel3.iotesters.PeekPokeTester + + +object CoreMain { + def main(args: Array[String]): Unit = { + // chiselMainTest(args, () => Module(new daisyVector(4, 32))) { c => new daisyVectorTest(c) } + // chiselMainTest(args, () => Module(new daisyGrid(4, 3, 32))) { c => new daisyGridTest(c) } + // chiselMainTest(args, () => Module(new daisyMultiplier(3, 2, 2, 3, 32))) { c => new daisyMultiplierTest(c) } + + iotesters.Driver.execute(args, () => new daisyMultiplier(3, 2, 2, 3, 32)) { + c => new daisyMultiplierTest(c) + } + } +} + +class Tile(data_width: Int, cols: Int, rows: Int) extends Module{ + + val io = IO(new Bundle { + val data_in = Input(UInt(data_width.W)) + + val reset = Input(Bool()) + + val data_out = Output(UInt(data_width.W)) + val data_out_delayed = Output(UInt(data_width.W)) + }) + + val data_reg = Reg(init=UInt(0, width = data_width)) + + io.data_out := io.data_in + data_reg := io.data_in + io.data_out_delayed := data_reg +} + +class myTest(c: Tile) extends PeekPokeTester(c) { + + poke(c.io.data_in, 0) + peek(c.io.data_out_delayed) + step(1) + poke(c.io.data_in, 1) + peek(c.io.data_out) + peek(c.io.data_out_delayed) + step(1) + poke(c.io.data_in, 2) + peek(c.io.data_out) + peek(c.io.data_out_delayed) + step(1) + poke(c.io.data_in, 3) + peek(c.io.data_out) + peek(c.io.data_out_delayed) + +} + +object Util { + def somefun(someval: Int) : Unit = {} +} diff --git a/src/main/scala/daisyGrid.scala b/src/main/scala/daisyGrid.scala new file mode 100644 index 0000000..c731ddf --- /dev/null +++ b/src/main/scala/daisyGrid.scala @@ -0,0 +1,55 @@ +package Core +import chisel3._ +import chisel3.core.Input +import chisel3.iotesters.PeekPokeTester + +class daisyGrid(rows: Int, cols: Int, dataWidth: Int) extends Module{ + + val io = IO(new Bundle { + + val readEnable = Input(Bool()) + val dataIn = Input(UInt(dataWidth.W)) + val readRow = Input(UInt(8.W)) + // val reset = Input(Bool()) + + val dataOut = Output(UInt(dataWidth.W)) + }) + + val currentRowIndex = RegInit(UInt(8.W), 0.U) + val currentColIndex = RegInit(UInt(8.W), 0.U) + + val memRows = Array.fill(rows){ Module(new daisyVector(cols, dataWidth)).io } + val elements = rows*cols + + + io.dataOut := 0.U + + for(ii <- 0 until rows){ + + memRows(ii).readEnable := 0.U + memRows(ii).dataIn := io.dataIn + + when(io.readRow === ii.U ){ + memRows(ii).readEnable := io.readEnable + io.dataOut := memRows(ii).dataOut + } + } +} + +class daisyGridTest(c: daisyGrid) extends PeekPokeTester(c) { + + poke(c.io.readEnable, 1) + for(ii <- 0 until 12){ + poke(c.io.dataIn, ii) + poke(c.io.readRow, ii/3) + step(1) + println("////////////////////") + } + poke(c.io.readEnable, 0) + for(ii <- 0 until 12){ + peek(c.io.dataOut) + poke(c.io.readRow, ii/3) + step(1) + println("////////////////////") + } +} diff --git a/src/main/scala/daisyMatMul.scala b/src/main/scala/daisyMatMul.scala new file mode 100644 index 0000000..cfed273 --- /dev/null +++ b/src/main/scala/daisyMatMul.scala @@ -0,0 +1,133 @@ +package Core +import chisel3._ +import chisel3.core.Input +import chisel3.iotesters.PeekPokeTester + +// I use val for the args so I can reference them in the test +class daisyMultiplier(val rowsA: Int, val colsA: Int, val rowsB: Int, val colsB: Int, val dataWidth: Int) extends Module { + + val io = IO(new Bundle { + + val dataInA = Input(UInt(dataWidth.W)) + val readEnableA = Input(Bool()) + + val dataInB = Input(UInt(dataWidth.W)) + val readEnableB = Input(Bool()) + + val dataOut = Output(UInt(dataWidth.W)) + val dataValid = Output(Bool()) + val done = Output(Bool()) + }) + + // How many cycles does it take to fill the matrices with data? + 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) + + println(s"rowsA: $rowsA, colsA: $colsA, rowsB: $rowsB, colsB: $colsB") + + //////////////////////////////////////// + //////////////////////////////////////// + /// We transpose matrix B. This means that if both matrices read the same input + /// stream then they will end up transposed. + val matrixA = Module(new daisyGrid(rowsA, colsA, dataWidth)).io + val matrixB = Module(new daisyGrid(colsB, rowsB, dataWidth)).io + + matrixA.dataIn := io.dataInA + matrixA.readEnable := io.readEnableA + + matrixB.dataIn := io.dataInB + matrixB.readEnable := io.readEnableB + + printf("matrix A data in: %d\n", matrixB.dataIn) + + + //////////////////////////////////////// + //////////////////////////////////////// + /// Set up counter statemachine + io.done := false.B + + when(colCounter === (colsA - 1).U){ + colCounter := 0.U + + when(rowCounter === (rowsA - 1).U){ + rowCounter := 0.U + calculating := true.B + + when(calculating === true.B){ + + when(rowOutputCounter === (rowsA - 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.readRow := rowOutputCounter + }.otherwise{ + matrixA.readRow := rowCounter + } + + matrixB.readRow := 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 === (colsA - 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 +} + + +class daisyMultiplierTest(c: daisyMultiplier) extends PeekPokeTester(c) { + + poke(c.io.readEnableA, 1) + poke(c.io.readEnableB, 1) + for(ii <- 0 until 6){ + println("data in:") + poke(c.io.dataInA, (ii/2) + 1) + poke(c.io.dataInB, (ii/2) + 1) + println("fill counters") + step(1) + println("////////////////////\n") + } +} diff --git a/src/main/scala/daisyVec.scala b/src/main/scala/daisyVec.scala new file mode 100644 index 0000000..a177ccf --- /dev/null +++ b/src/main/scala/daisyVec.scala @@ -0,0 +1,54 @@ +package Core +import chisel3._ +import chisel3.core.Input +import chisel3.iotesters.PeekPokeTester + +class daisyVector(elements: Int, dataWidth: Int) extends Module{ + + val io = IO(new Bundle { + val readEnable = Input(Bool()) + val dataIn = Input(UInt(dataWidth.W)) + + val dataOut = Output(UInt(dataWidth.W)) + }) + + val currentIndex = RegInit(UInt(8.W), 0.U) + + val memory = Array.fill(elements)(Reg(UInt(dataWidth.W))) + + 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.readEnable === true.B){ + memory(ii) := io.dataIn + } + io.dataOut := memory(ii) + } + } +} + +class daisyVectorTest(c: daisyVector) extends PeekPokeTester(c) { + + poke(c.io.readEnable, 1) + step(1) + + for(ii <- 0 until 4){ + poke(c.io.dataIn, ii) + println("////////////////////") + step(1) + } + + poke(c.io.readEnable, 0) + for(ii <- 0 until 4){ + peek(c.io.dataOut) + step(1) + } +}