├── README.md ├── benchmarks ├── 16x16 │ ├── ct.txt │ └── ppa.txt └── 25x18 │ ├── ct.txt │ └── ppa.txt ├── build.sbt ├── run-basemac.sh └── src └── main └── scala ├── base-adder ├── baseadder.scala └── sklansky.scala ├── base-mac └── basemac.scala ├── base-multiplier └── basemulti.scala ├── basic ├── Compressor32.scala ├── Compressor42.scala ├── Compressor43.scala ├── Compressor53.scala ├── Compressor63.scala ├── Compressor73.scala ├── FullAdder.scala └── HalfAdder.scala ├── examples ├── GCD.scala └── Hello.scala ├── io ├── readppa.scala └── readwallace.scala ├── mac └── mac.scala ├── partialprod ├── partialprod.scala └── radix4encoder.scala ├── ppadder ├── pg.scala └── ppadder.scala ├── wallace ├── comp.scala └── wallace.scala └── wtmultiplier └── wtmultiplier.scala /README.md: -------------------------------------------------------------------------------- 1 | # easymac 2 | A chisel-based multiplier-accumulator generator. 3 | 4 | ## Environment Setup 5 | 6 | ### Install JDK 7 | ``` 8 | sudo apt install openjdk-8-jdk 9 | # or sudo apt install openjdk-11-jdk 10 | ``` 11 | 12 | ### Install Scala 13 | The following is for Ubuntu 18.04; for other OS, please refer to [here](https://www.scala-sbt.org/1.x/docs/Setup.html). 14 | ``` 15 | sudo apt-get update 16 | sudo apt-get install apt-transport-https curl gnupg -yqq 17 | echo "deb https://repo.scala-sbt.org/scalasbt/debian all main" | sudo tee /etc/apt/sources.list.d/sbt.list 18 | echo "deb https://repo.scala-sbt.org/scalasbt/debian /" | sudo tee /etc/apt/sources.list.d/sbt_old.list 19 | curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | sudo -H gpg --no-default-keyring --keyring gnupg-ring:/etc/apt/trusted.gpg.d/scalasbt-release.gpg --import 20 | sudo chmod 644 /etc/apt/trusted.gpg.d/scalasbt-release.gpg 21 | sudo apt-get update 22 | sudo apt-get install sbt 23 | ``` 24 | 25 | ### Install Chisel 26 | Chisel will be installed automatically according to [`build.sbt`](build.sbt) the first time you run sbt. 27 | 28 | ### Install Verilator 29 | You should install Verilator for simulation. 30 | ``` 31 | sudo apt-get install verilator 32 | ``` 33 | 34 | ## Run 35 | Run `sbt "Test/runMain mac.test --compressor-file --prefix-adder-file --accumulator-file "`. 36 | Sample representation files are under [`benchmarks/`](benchmarks/). 37 | For example, 38 | ``` 39 | sbt "Test/runMain mac.test --compressor-file benchmarks/16x16/ct.txt --prefix-adder-file benchmarks/16x16/ppa.txt --accumulator-file benchmarks/16x16/ppa.txt" 40 | ``` 41 | -------------------------------------------------------------------------------- /benchmarks/16x16/ct.txt: -------------------------------------------------------------------------------- 1 | 16 16 2 | 210 3 | 28 1 4 | 27 1 5 | 26 1 6 | 25 1 7 | 25 1 8 | 24 1 9 | 24 1 10 | 23 1 11 | 23 1 12 | 22 1 13 | 22 1 14 | 22 1 15 | 21 1 16 | 21 1 17 | 21 1 18 | 20 1 19 | 20 1 20 | 20 1 21 | 19 1 22 | 19 1 23 | 19 1 24 | 19 1 25 | 18 1 26 | 18 1 27 | 18 1 28 | 18 1 29 | 17 1 30 | 17 1 31 | 17 1 32 | 17 1 33 | 16 1 34 | 16 1 35 | 16 1 36 | 16 1 37 | 16 1 38 | 15 1 39 | 15 1 40 | 15 1 41 | 15 1 42 | 15 1 43 | 14 1 44 | 14 1 45 | 14 1 46 | 14 1 47 | 14 1 48 | 13 1 49 | 13 1 50 | 13 1 51 | 13 1 52 | 12 1 53 | 12 1 54 | 12 1 55 | 12 1 56 | 11 1 57 | 11 1 58 | 11 1 59 | 11 1 60 | 10 1 61 | 10 1 62 | 10 1 63 | 9 1 64 | 9 1 65 | 9 1 66 | 8 1 67 | 8 1 68 | 8 1 69 | 7 1 70 | 7 1 71 | 6 1 72 | 6 1 73 | 5 1 74 | 5 1 75 | 4 1 76 | 3 1 77 | 2 1 78 | 29 1 79 | 27 1 80 | 26 1 81 | 25 1 82 | 24 1 83 | 23 1 84 | 23 1 85 | 22 1 86 | 22 1 87 | 21 1 88 | 21 1 89 | 20 1 90 | 20 1 91 | 20 1 92 | 19 1 93 | 19 1 94 | 18 1 95 | 18 1 96 | 18 1 97 | 17 1 98 | 17 1 99 | 17 1 100 | 16 1 101 | 16 1 102 | 16 1 103 | 15 1 104 | 15 1 105 | 15 1 106 | 14 1 107 | 14 1 108 | 14 1 109 | 13 1 110 | 13 1 111 | 13 1 112 | 12 1 113 | 12 1 114 | 12 1 115 | 11 1 116 | 11 1 117 | 10 1 118 | 10 1 119 | 9 1 120 | 9 1 121 | 8 1 122 | 7 1 123 | 7 1 124 | 6 1 125 | 5 1 126 | 4 1 127 | 3 1 128 | 28 1 129 | 26 1 130 | 25 1 131 | 24 1 132 | 23 1 133 | 22 1 134 | 21 1 135 | 21 1 136 | 20 1 137 | 19 1 138 | 19 1 139 | 18 1 140 | 18 1 141 | 17 1 142 | 17 1 143 | 16 1 144 | 16 1 145 | 15 1 146 | 15 1 147 | 14 1 148 | 14 1 149 | 13 1 150 | 13 1 151 | 12 1 152 | 11 1 153 | 10 1 154 | 10 1 155 | 9 1 156 | 8 1 157 | 8 0 158 | 7 1 159 | 6 1 160 | 4 1 161 | 27 1 162 | 26 1 163 | 24 1 164 | 23 1 165 | 22 1 166 | 21 1 167 | 20 1 168 | 19 1 169 | 18 1 170 | 17 1 171 | 17 1 172 | 16 1 173 | 15 1 174 | 15 1 175 | 14 1 176 | 13 1 177 | 12 1 178 | 11 1 179 | 11 0 180 | 10 1 181 | 9 1 182 | 8 1 183 | 5 1 184 | 25 1 185 | 24 1 186 | 23 1 187 | 22 1 188 | 20 1 189 | 19 1 190 | 18 1 191 | 17 1 192 | 16 1 193 | 16 0 194 | 15 1 195 | 14 1 196 | 13 1 197 | 12 1 198 | 11 1 199 | 9 1 200 | 6 1 201 | 21 1 202 | 20 1 203 | 19 1 204 | 18 1 205 | 17 1 206 | 16 1 207 | 15 0 208 | 14 0 209 | 13 0 210 | 12 1 211 | 10 1 212 | 7 1 213 | -------------------------------------------------------------------------------- /benchmarks/16x16/ppa.txt: -------------------------------------------------------------------------------- 1 | 31 2 | 62 3 | 27 28 29 30 23 24 25 21 18 19 21 25 30 29 28 27 26 24 23 22 20 13 14 15 16 11 8 9 11 6 6 3 1 3 6 11 16 30 29 28 27 26 25 24 23 22 21 20 19 18 17 15 14 13 12 9 10 8 7 4 5 2 -------------------------------------------------------------------------------- /benchmarks/25x18/ct.txt: -------------------------------------------------------------------------------- 1 | 25 18 2 | 384 3 | 39 1 4 | 38 1 5 | 37 1 6 | 36 1 7 | 36 1 8 | 35 1 9 | 35 1 10 | 34 1 11 | 34 1 12 | 33 1 13 | 33 1 14 | 33 1 15 | 32 1 16 | 32 1 17 | 32 1 18 | 31 1 19 | 31 1 20 | 31 1 21 | 30 1 22 | 30 1 23 | 30 1 24 | 30 1 25 | 29 1 26 | 29 1 27 | 29 1 28 | 29 1 29 | 28 1 30 | 28 1 31 | 28 1 32 | 28 1 33 | 27 1 34 | 27 1 35 | 27 1 36 | 27 1 37 | 27 1 38 | 26 1 39 | 26 1 40 | 26 1 41 | 26 1 42 | 26 1 43 | 25 1 44 | 25 1 45 | 25 1 46 | 25 1 47 | 25 1 48 | 24 1 49 | 24 1 50 | 24 1 51 | 24 1 52 | 24 1 53 | 24 1 54 | 23 1 55 | 23 1 56 | 23 1 57 | 23 1 58 | 23 1 59 | 23 1 60 | 22 1 61 | 22 1 62 | 22 1 63 | 22 1 64 | 22 1 65 | 22 1 66 | 21 1 67 | 21 1 68 | 21 1 69 | 21 1 70 | 21 1 71 | 21 1 72 | 20 1 73 | 20 1 74 | 20 1 75 | 20 1 76 | 20 1 77 | 20 1 78 | 19 1 79 | 19 1 80 | 19 1 81 | 19 1 82 | 19 1 83 | 19 1 84 | 18 1 85 | 18 1 86 | 18 1 87 | 18 1 88 | 18 1 89 | 18 1 90 | 17 1 91 | 17 1 92 | 17 1 93 | 17 1 94 | 17 1 95 | 17 1 96 | 16 1 97 | 16 1 98 | 16 1 99 | 16 1 100 | 16 1 101 | 15 1 102 | 15 1 103 | 15 1 104 | 15 1 105 | 15 1 106 | 14 1 107 | 14 1 108 | 14 1 109 | 14 1 110 | 14 1 111 | 13 1 112 | 13 1 113 | 13 1 114 | 13 1 115 | 12 1 116 | 12 1 117 | 12 1 118 | 12 1 119 | 11 1 120 | 11 1 121 | 11 1 122 | 11 1 123 | 10 1 124 | 10 1 125 | 10 1 126 | 9 1 127 | 9 1 128 | 9 1 129 | 8 1 130 | 8 1 131 | 8 1 132 | 7 1 133 | 7 1 134 | 6 1 135 | 6 1 136 | 5 1 137 | 5 1 138 | 4 1 139 | 3 1 140 | 2 1 141 | 40 1 142 | 38 1 143 | 37 1 144 | 36 1 145 | 35 1 146 | 34 1 147 | 34 1 148 | 33 1 149 | 33 1 150 | 32 1 151 | 32 1 152 | 31 1 153 | 31 1 154 | 31 1 155 | 30 1 156 | 30 1 157 | 29 1 158 | 29 1 159 | 29 1 160 | 28 1 161 | 28 1 162 | 28 1 163 | 27 1 164 | 27 1 165 | 27 1 166 | 26 1 167 | 26 1 168 | 26 1 169 | 25 1 170 | 25 1 171 | 25 1 172 | 25 1 173 | 24 1 174 | 24 1 175 | 24 1 176 | 24 1 177 | 23 1 178 | 23 1 179 | 23 1 180 | 23 1 181 | 22 1 182 | 22 1 183 | 22 1 184 | 22 1 185 | 21 1 186 | 21 1 187 | 21 1 188 | 21 1 189 | 20 1 190 | 20 1 191 | 20 1 192 | 20 1 193 | 19 1 194 | 19 1 195 | 19 1 196 | 19 1 197 | 18 1 198 | 18 1 199 | 18 1 200 | 18 1 201 | 17 1 202 | 17 1 203 | 17 1 204 | 16 1 205 | 16 1 206 | 16 1 207 | 16 1 208 | 15 1 209 | 15 1 210 | 15 1 211 | 14 1 212 | 14 1 213 | 14 1 214 | 13 1 215 | 13 1 216 | 13 1 217 | 12 1 218 | 12 1 219 | 12 1 220 | 11 1 221 | 11 1 222 | 10 1 223 | 10 1 224 | 9 1 225 | 9 1 226 | 8 1 227 | 7 1 228 | 7 1 229 | 6 1 230 | 5 1 231 | 4 1 232 | 3 1 233 | 39 1 234 | 37 1 235 | 36 1 236 | 35 1 237 | 34 1 238 | 33 1 239 | 32 1 240 | 32 1 241 | 31 1 242 | 30 1 243 | 30 1 244 | 29 1 245 | 29 1 246 | 28 1 247 | 28 1 248 | 27 1 249 | 27 1 250 | 26 1 251 | 26 1 252 | 26 1 253 | 25 1 254 | 25 1 255 | 25 1 256 | 24 1 257 | 24 1 258 | 23 1 259 | 23 1 260 | 22 1 261 | 22 1 262 | 21 1 263 | 21 1 264 | 20 1 265 | 20 1 266 | 19 1 267 | 19 1 268 | 18 1 269 | 18 1 270 | 17 1 271 | 17 1 272 | 17 1 273 | 16 1 274 | 16 1 275 | 15 1 276 | 15 1 277 | 14 1 278 | 14 1 279 | 13 1 280 | 13 1 281 | 12 1 282 | 11 1 283 | 10 1 284 | 10 1 285 | 9 1 286 | 8 1 287 | 8 0 288 | 7 1 289 | 6 1 290 | 4 1 291 | 38 1 292 | 37 1 293 | 35 1 294 | 34 1 295 | 33 1 296 | 32 1 297 | 31 1 298 | 30 1 299 | 29 1 300 | 28 1 301 | 28 1 302 | 27 1 303 | 27 1 304 | 26 1 305 | 26 1 306 | 25 1 307 | 24 1 308 | 24 1 309 | 23 1 310 | 23 1 311 | 22 1 312 | 22 1 313 | 21 1 314 | 21 1 315 | 20 1 316 | 20 1 317 | 19 1 318 | 19 1 319 | 18 1 320 | 18 1 321 | 17 1 322 | 17 0 323 | 16 1 324 | 15 1 325 | 15 1 326 | 14 1 327 | 13 1 328 | 12 1 329 | 11 1 330 | 11 0 331 | 10 1 332 | 9 1 333 | 8 1 334 | 5 1 335 | 36 1 336 | 35 1 337 | 34 1 338 | 33 1 339 | 31 1 340 | 30 1 341 | 29 1 342 | 28 1 343 | 27 1 344 | 26 1 345 | 25 1 346 | 25 0 347 | 24 1 348 | 23 1 349 | 22 1 350 | 21 1 351 | 20 1 352 | 19 1 353 | 18 1 354 | 17 1 355 | 16 1 356 | 16 0 357 | 15 1 358 | 14 1 359 | 13 1 360 | 12 1 361 | 11 1 362 | 9 1 363 | 6 1 364 | 32 1 365 | 31 1 366 | 30 1 367 | 29 1 368 | 28 1 369 | 27 1 370 | 26 1 371 | 25 1 372 | 24 1 373 | 23 1 374 | 22 1 375 | 21 1 376 | 20 1 377 | 19 1 378 | 18 1 379 | 17 1 380 | 16 1 381 | 15 0 382 | 14 0 383 | 13 0 384 | 12 1 385 | 10 1 386 | 7 1 387 | -------------------------------------------------------------------------------- /benchmarks/25x18/ppa.txt: -------------------------------------------------------------------------------- 1 | 42 2 | 103 3 | 40 38 40 41 39 36 36 33 31 33 36 41 40 39 38 37 34 35 32 28 29 26 24 26 29 21 22 18 19 22 29 41 40 39 38 37 36 35 34 33 32 31 30 26 28 27 24 25 23 21 20 13 14 15 16 11 8 9 11 6 6 3 1 3 6 11 16 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 15 14 13 12 9 10 8 7 4 5 2 -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | def scalacOptionsVersion(scalaVersion: String): Seq[String] = { 2 | Seq() ++ { 3 | // If we're building with Scala > 2.11, enable the compile option 4 | // switch to support our anonymous Bundle definitions: 5 | // https://github.com/scala/bug/issues/10047 6 | CrossVersion.partialVersion(scalaVersion) match { 7 | case Some((2, scalaMajor: Long)) if scalaMajor < 12 => Seq() 8 | case _ => Seq("-Xsource:2.11") 9 | } 10 | } 11 | } 12 | 13 | def javacOptionsVersion(scalaVersion: String): Seq[String] = { 14 | Seq() ++ { 15 | // Scala 2.12 requires Java 8. We continue to generate 16 | // Java 7 compatible code for Scala 2.11 17 | // for compatibility with old clients. 18 | CrossVersion.partialVersion(scalaVersion) match { 19 | case Some((2, scalaMajor: Long)) if scalaMajor < 12 => 20 | Seq("-source", "1.7", "-target", "1.7") 21 | case _ => 22 | Seq("-source", "1.8", "-target", "1.8") 23 | } 24 | } 25 | } 26 | 27 | organization := "cn.edu.pku.ceca" 28 | 29 | version := "0.0.1" 30 | 31 | name := "easymac" 32 | 33 | scalaVersion := "2.12.15" 34 | 35 | scalacOptions ++= Seq("-deprecation", "-feature", "-unchecked", "-language:reflectiveCalls") 36 | 37 | // Provide a managed dependency on X if -DXVersion="" is supplied on the command line. 38 | // The following are the current "release" versions. 39 | val defaultVersions = Seq( 40 | "chisel-iotesters" -> "1.4.1+" 41 | ) 42 | 43 | libraryDependencies ++= defaultVersions.map { case (dep, ver) => 44 | "edu.berkeley.cs" %% dep % sys.props.getOrElse(dep + "Version", ver) } 45 | 46 | resolvers ++= Seq( 47 | Resolver.sonatypeRepo("snapshots"), 48 | Resolver.sonatypeRepo("releases") 49 | ) 50 | 51 | // Recommendations from http://www.scalatest.org/user_guide/using_scalatest_with_sbt 52 | Test/logBuffered := false 53 | 54 | // Disable parallel execution when running tests. 55 | // Running tests in parallel on Jenkins currently fails. 56 | Test/parallelExecution := false 57 | 58 | scalacOptions ++= scalacOptionsVersion(scalaVersion.value) 59 | 60 | javacOptions ++= javacOptionsVersion(scalaVersion.value) 61 | 62 | trapExit := false 63 | -------------------------------------------------------------------------------- /run-basemac.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #sbt "test:runMain multiplier.test" 3 | sbt "Test/runMain basemac.test --input1-bit 25 --input2-bit 18" 4 | -------------------------------------------------------------------------------- /src/main/scala/base-adder/baseadder.scala: -------------------------------------------------------------------------------- 1 | package adder 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | class BasicAdder(m: Int) extends Module { 8 | val io = IO(new Bundle { 9 | val sumand = Input(UInt(m.W)) 10 | val addend = Input(UInt(m.W)) 11 | 12 | val res = Output(UInt(m.W)) 13 | }) 14 | io.res := io.sumand + io.addend 15 | } -------------------------------------------------------------------------------- /src/main/scala/base-adder/sklansky.scala: -------------------------------------------------------------------------------- 1 | package adder 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | class BlackCell extends Module { 8 | val io = IO(new Bundle { 9 | val currentG = Input(UInt(1.W)) 10 | val currentP = Input(UInt(1.W)) 11 | val preG = Input(UInt(1.W)) 12 | val preP = Input(UInt(1.W)) 13 | 14 | val outG = Output(UInt(1.W)) 15 | val outP = Output(UInt(1.W)) 16 | }) 17 | 18 | io.outG := (io.currentP & io.preG) | io.currentG 19 | io.outP := io.currentP & io.preP 20 | } 21 | 22 | class GrayCell extends Module { 23 | val io = IO(new Bundle { 24 | val currentG = Input(UInt(1.W)) 25 | val currentP = Input(UInt(1.W)) 26 | val preG = Input(UInt(1.W)) 27 | 28 | val outG = Output(UInt(1.W)) 29 | }) 30 | io.outG := (io.currentP & io.preG) | io.currentG 31 | } 32 | 33 | class Buffer extends Module { 34 | val io = IO(new Bundle { 35 | val currentG = Input(UInt(1.W)) 36 | val currentP = Input(UInt(1.W)) 37 | 38 | val outG = Output(UInt(1.W)) 39 | val outP = Output(UInt(1.W)) 40 | }) 41 | 42 | io.outG := io.currentG 43 | io.outP := io.currentP 44 | } 45 | 46 | /** High quality adder: Sklansky 47 | * 48 | * @param w the data width which should be power of 2 49 | */ 50 | class HighQualityAdder(w: Int) extends Module { 51 | val io = IO(new Bundle { 52 | val inputs = Input(MixedVec(Seq(UInt(w.W), UInt(w.W)))) 53 | val outs = Output(MixedVec(Seq(UInt(w.W)))) 54 | }) 55 | 56 | def getWidth(): Int = { 57 | w 58 | } 59 | 60 | if (w % 2 != 0) { 61 | throw new Exception("The data width is not power of 2!") 62 | } 63 | val depth = log2Ceil(w) 64 | 65 | val gArray = (0 until w).map(i => io.inputs(0)(i, i) & io.inputs(1)(i, i)) 66 | val pArray = (0 until w).map(i => io.inputs(0)(i, i) ^ io.inputs(1)(i, i)) 67 | 68 | var GMap = Map[List[Int], Data]() 69 | var PMap = Map[List[Int], Data]() 70 | 71 | for (i <- 0 until w) { 72 | GMap += List(-1, i) -> gArray(i) 73 | PMap += List(-1, i) -> pArray(i) 74 | } 75 | 76 | for (row <- 0 until depth) { 77 | val groupModuleNum = 2 << row 78 | val halfGroup = groupModuleNum / 2 79 | for (col <- 0 until w) { 80 | val pos = List(row, col) 81 | val groupIndex = col % groupModuleNum 82 | if (groupIndex < halfGroup) { 83 | if (groupIndex < halfGroup / 2) { 84 | GMap += pos -> GMap(List(row - 1, col)) 85 | PMap += pos -> PMap(List(row - 1, col)) 86 | } else { 87 | val module = Module(new Buffer) 88 | module.io.currentG := GMap(List(row - 1, col)) 89 | module.io.currentP := PMap(List(row - 1, col)) 90 | GMap += pos -> module.io.outG 91 | PMap += pos -> module.io.outP 92 | } 93 | } else { 94 | if (col < groupModuleNum) { 95 | val module = Module(new GrayCell) 96 | module.io.currentG := GMap(List(row - 1, col)) 97 | module.io.currentP := PMap(List(row - 1, col)) 98 | module.io.preG := GMap(List(row - 1, col - (col % halfGroup) - 1)) 99 | 100 | GMap += pos -> module.io.outG 101 | PMap += pos -> PMap(List(row - 1, col)) 102 | } else { 103 | val module = Module(new BlackCell) 104 | module.io.currentG := GMap(List(row - 1, col)) 105 | module.io.currentP := PMap(List(row - 1, col)) 106 | module.io.preG := GMap(List(row - 1, col - (col % halfGroup) - 1)) 107 | module.io.preP := PMap(List(row - 1, col - (col % halfGroup) - 1)) 108 | 109 | GMap += pos -> module.io.outG 110 | PMap += pos -> module.io.outP 111 | } 112 | } 113 | } 114 | } 115 | 116 | var sum = (1 until w).map(i => pArray(w - i) ^ GMap(List(depth - 1, w - i - 1)).asUInt()) 117 | .reduce(Cat(_, _)) 118 | sum = Cat(sum, pArray(0)) 119 | 120 | io.outs(0) := sum 121 | } 122 | 123 | object test { 124 | def main(args: Array[String]): Unit = { 125 | (new chisel3.stage.ChiselStage).emitVerilog(new HighQualityAdder(4), Array("-td", "./RTL/")) 126 | 127 | iotesters.Driver.execute(Array("-tgvo", "on", "-tbn", "verilator"), () => new HighQualityAdder(4)) { 128 | c => new HighQualityAdderTester(c) 129 | } 130 | iotesters.Driver.execute(Array("-tgvo", "on", "-tbn", "verilator"), () => new HighQualityAdder(8)) { 131 | c => new HighQualityAdderTester(c) 132 | } 133 | } 134 | } 135 | 136 | class HighQualityAdderTester(c: HighQualityAdder) 137 | extends PeekPokeTester(c) { 138 | poke(c.io.inputs(0), 14) 139 | poke(c.io.inputs(1), 13) 140 | 141 | println("The result of 13 + 14 with " + c.getWidth().toString 142 | + "-bit adder is: " + peek(c.io.outs(0)).toString()) 143 | 144 | expect(c.io.outs(0), 27) 145 | } 146 | -------------------------------------------------------------------------------- /src/main/scala/base-mac/basemac.scala: -------------------------------------------------------------------------------- 1 | package basemac 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | class BasicMAC(m: Int, n: Int) extends Module { 8 | val io = IO(new Bundle { 9 | val multiplicand = Input(UInt(m.W)) 10 | val multiplier = Input(UInt(n.W)) 11 | val addend = Input(UInt((m + n).W)) 12 | 13 | val res = Output(UInt((m + n).W)) 14 | }) 15 | 16 | io.res := io.multiplicand * io.multiplier + io.addend 17 | } 18 | 19 | object test { 20 | val usage = 21 | """ 22 | Usage: generate [--input1-bit input1] [--input2-bit input2] 23 | """ 24 | 25 | def main(args: Array[String]): Unit = { 26 | if (args.length == 0) println(usage) 27 | 28 | val arglist = args.toList 29 | val optionnames = arglist.filter(s => s.contains('-')) 30 | 31 | val argmap = (0 until arglist.size / 2).map(i => arglist(i * 2) -> arglist(i * 2 + 1)).toMap 32 | 33 | val input1 = argmap("--input1-bit").toInt 34 | val input2 = argmap("--input2-bit").toInt 35 | 36 | val topDesign = () => new BasicMAC(input1, input2) 37 | (new chisel3.stage.ChiselStage).emitVerilog(topDesign(), Array("-td", "./RTL/basicmac")) 38 | iotesters.Driver.execute(Array("-tgvo", "on", "-tbn", "verilator"), topDesign) { 39 | c => new BasicMACTester(c) 40 | } 41 | } 42 | } 43 | 44 | class BasicMACTester(c: BasicMAC) extends PeekPokeTester(c) { 45 | poke(c.io.multiplicand, 15) 46 | poke(c.io.multiplier, 8) 47 | poke(c.io.addend, 10) 48 | 49 | println("The result of 15 * 8 + 10 is: " + peek(c.io.res).toString()) 50 | 51 | expect(c.io.res, 130) 52 | } 53 | -------------------------------------------------------------------------------- /src/main/scala/base-multiplier/basemulti.scala: -------------------------------------------------------------------------------- 1 | package basemulti 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | class BasicMultiplier(m: Int, n: Int) extends Module { 8 | val io = IO(new Bundle { 9 | val multiplicand = Input(UInt(m.W)) 10 | val multiplier = Input(UInt(n.W)) 11 | 12 | val res = Output(UInt((m + n).W)) 13 | }) 14 | io.res := io.multiplicand * io.multiplier 15 | } 16 | 17 | object test { 18 | def main(args: Array[String]): Unit = { 19 | val topDesign = () => new BasicMultiplier(16, 16) 20 | (new chisel3.stage.ChiselStage).emitVerilog(topDesign(), Array("-td", "./RTL/basicmulti")) 21 | iotesters.Driver.execute(Array("-tgvo", "on", "-tbn", "verilator"), topDesign) { 22 | c => new BasicMultiplierTester(c) 23 | } 24 | } 25 | } 26 | 27 | class BasicMultiplierTester(c: BasicMultiplier) extends PeekPokeTester(c) { 28 | poke(c.io.multiplicand, 15) 29 | poke(c.io.multiplier, 8) 30 | 31 | println("The result of 15 * 8 with is: " + peek(c.io.res).toString()) 32 | 33 | expect(c.io.res, 120) 34 | } 35 | -------------------------------------------------------------------------------- /src/main/scala/basic/Compressor32.scala: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | class Compressor32 extends Module { 8 | val io = IO(new Bundle { 9 | val I = Input(UInt(3.W)) 10 | val O = Output(UInt(2.W)) 11 | }) 12 | 13 | val xor1 = io.I(0) ^ io.I(1) 14 | io.O(0) := Mux(xor1, io.I(0), io.I(1)) 15 | //val mux1 = Module(new Mux(xor1, io.io.I(0), io.I(1))) 16 | io.O(1) := xor1 ^ io.I(2) 17 | 18 | } -------------------------------------------------------------------------------- /src/main/scala/basic/Compressor42.scala: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | class Compressor42 extends Module { 8 | val io = IO(new Bundle { 9 | val I = Input(UInt(5.W)) 10 | val O = Output(UInt(3.W)) 11 | }) 12 | 13 | val xor1 = io.I(0) ^ io.I(1) 14 | val xor2 = io.I(2) ^ io.I(3) 15 | val xor3 = xor1 ^ xor2 16 | io.O(0) := Mux(xor1, io.I(0), io.I(2)) 17 | io.O(1) := xor3 ^ io.I(4) 18 | io.O(2) := Mux(xor3, io.I(3), io.I(4)) 19 | } -------------------------------------------------------------------------------- /src/main/scala/basic/Compressor43.scala: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | 8 | class Compressor43 extends Module { 9 | val io = IO(new Bundle { 10 | val I = Input(UInt(4.W)) 11 | val O = Output(UInt(3.W)) 12 | }) 13 | 14 | val fa1 = Module(new FullAdder()) 15 | fa1.io.A := io.I(1) 16 | fa1.io.B := io.I(2) 17 | fa1.io.Cin := io.I(3) 18 | val fs1 = fa1.io.Sum 19 | val fc1 = fa1.io.Cout 20 | 21 | val ha1 = Module(new HalfAdder()) 22 | ha1.io.A := io.I(0) 23 | ha1.io.B := fs1 24 | io.O(0) := ha1.io.Sum 25 | val hc1 = ha1.io.Cout 26 | 27 | val ha2 = Module(new HalfAdder()) 28 | ha2.io.A := hc1 29 | ha2.io.B := fc1 30 | io.O(1) := ha2.io.Sum 31 | io.O(2) := ha2.io.Cout 32 | 33 | } -------------------------------------------------------------------------------- /src/main/scala/basic/Compressor53.scala: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | class Compressor53 extends Module { 8 | val io = IO(new Bundle { 9 | val I = Input(UInt(5.W)) 10 | val O = Output(UInt(3.W)) 11 | }) 12 | 13 | val fa1 = Module(new FullAdder()) 14 | fa1.io.A := io.I(0) 15 | fa1.io.B := io.I(1) 16 | fa1.io.Cin := io.I(2) 17 | io.O(0) := fa1.io.Sum 18 | val fc1 = fa1.io.Cout 19 | 20 | val fa2 = Module(new FullAdder()) 21 | fa2.io.A := fc1 22 | fa2.io.B := io.I(3) 23 | fa2.io.Cin := io.I(4) 24 | io.O(1) := fa2.io.Sum 25 | io.O(2) := fa2.io.Cout 26 | 27 | } -------------------------------------------------------------------------------- /src/main/scala/basic/Compressor63.scala: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | class Compressor63 extends Module { 8 | val io = IO(new Bundle { 9 | val I = Input(UInt(6.W)) 10 | val O = Output(UInt(3.W)) 11 | }) 12 | 13 | val fa1 = Module(new FullAdder()) 14 | fa1.io.A := io.I(1) 15 | fa1.io.B := io.I(2) 16 | fa1.io.Cin := io.I(3) 17 | val fs1 = fa1.io.Sum 18 | val fc1 = fa1.io.Cout 19 | 20 | val ha1 = Module(new HalfAdder()) 21 | ha1.io.A := io.I(4) 22 | ha1.io.B := io.I(5) 23 | val hs1 = ha1.io.Sum 24 | val hc1 = ha1.io.Cout 25 | 26 | val fa2 = Module(new FullAdder()) 27 | fa2.io.A := io.I(0) 28 | fa2.io.B := fs1 29 | fa2.io.Cin := hs1 30 | io.O(0) := fa2.io.Sum 31 | val fc2 = fa2.io.Cout 32 | 33 | val fa3 = Module(new FullAdder()) 34 | fa3.io.A := fc2 35 | fa3.io.B := fc1 36 | fa3.io.Cin := hc1 37 | io.O(1) := fa3.io.Sum 38 | io.O(2) := fa3.io.Cout 39 | 40 | } -------------------------------------------------------------------------------- /src/main/scala/basic/Compressor73.scala: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | class Compressor73 extends Module { 8 | val io = IO(new Bundle { 9 | val I = Input(UInt(7.W)) 10 | val O = Output(UInt(3.W)) 11 | }) 12 | 13 | val fa1 = Module(new FullAdder()) 14 | fa1.io.A := io.I(1) 15 | fa1.io.B := io.I(2) 16 | fa1.io.Cin := io.I(3) 17 | val fs1 = fa1.io.Sum 18 | val fc1 = fa1.io.Cout 19 | 20 | val fa2 = Module(new FullAdder()) 21 | fa2.io.A := io.I(4) 22 | fa2.io.B := io.I(5) 23 | fa2.io.Cin := io.I(6) 24 | val fs2 = fa2.io.Sum 25 | val fc2 = fa2.io.Cout 26 | 27 | val fa3 = Module(new FullAdder()) 28 | fa3.io.A := io.I(0) 29 | fa3.io.B := fs1 30 | fa3.io.Cin := fs2 31 | io.O(0) := fa3.io.Sum 32 | val fc3 = fa3.io.Cout 33 | 34 | val fa4 = Module(new FullAdder()) 35 | fa4.io.A := fc3 36 | fa4.io.B := fc1 37 | fa4.io.Cin := fc2 38 | io.O(1) := fa4.io.Sum 39 | io.O(2) := fa4.io.Cout 40 | 41 | } -------------------------------------------------------------------------------- /src/main/scala/basic/FullAdder.scala: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | class FullAdder extends Module { 8 | val io = IO(new Bundle { 9 | val A = Input(UInt(1.W)) 10 | val B = Input(UInt(1.W)) 11 | val Cin = Input(UInt(1.W)) 12 | val Sum = Output(UInt(1.W)) 13 | val Cout = Output(UInt(1.W)) 14 | }) 15 | 16 | val a_xor_b = io.A ^ io.B 17 | io.Sum := a_xor_b ^ io.Cin 18 | 19 | val a_and_b = io.A & io.B 20 | val a_and_cin = io.A & io.Cin 21 | val b_and_cin = io.B & io.Cin 22 | io.Cout := a_and_b | b_and_cin | a_and_cin 23 | } 24 | -------------------------------------------------------------------------------- /src/main/scala/basic/HalfAdder.scala: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | class HalfAdder extends Module { 8 | val io = IO(new Bundle { 9 | val A = Input(UInt(1.W)) 10 | val B = Input(UInt(1.W)) 11 | val Sum = Output(UInt(1.W)) 12 | val Cout = Output(UInt(1.W)) 13 | }) 14 | 15 | io.Sum := io.A ^ io.B 16 | io.Cout := io.A & io.B 17 | } 18 | -------------------------------------------------------------------------------- /src/main/scala/examples/GCD.scala: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import chisel3._ 4 | 5 | /** 6 | * Compute the GCD of 'a' and 'b' using Euclid's algorithm. 7 | * To start a computation, load the values into 'a' and 'b' and toggle 'load' 8 | * high. 9 | * The GCD will be returned in 'out' when 'valid' is high. 10 | */ 11 | class GCD extends Module { 12 | val io = IO(new Bundle { 13 | val a = Input(UInt(16.W)) 14 | val b = Input(UInt(16.W)) 15 | val load = Input(Bool()) 16 | val out = Output(UInt(16.W)) 17 | val valid = Output(Bool()) 18 | }) 19 | val x = Reg(UInt()) 20 | val y = Reg(UInt()) 21 | 22 | when(io.load) { 23 | x := io.a; 24 | y := io.b 25 | }.otherwise { 26 | when(x > y) { 27 | x := x - y 28 | }.elsewhen(x <= y) { 29 | y := y - x 30 | } 31 | } 32 | 33 | io.out := x 34 | io.valid := y === 0.U 35 | } -------------------------------------------------------------------------------- /src/main/scala/examples/Hello.scala: -------------------------------------------------------------------------------- 1 | /* 2 | This is an example for chisel 3 | */ 4 | package hello 5 | 6 | import chisel3._ 7 | import chisel3.iotesters.{PeekPokeTester, Driver} 8 | 9 | class Hello extends Module { 10 | val io = IO(new Bundle { 11 | val out = Output(UInt(8.W)) 12 | }) 13 | io.out := 42.U 14 | } 15 | 16 | class HelloTests(c: Hello) extends PeekPokeTester(c) { 17 | step(1) 18 | expect(c.io.out, 42) 19 | } 20 | 21 | object Hello { 22 | def main(args: Array[String]): Unit = { 23 | if (!Driver(() => new Hello())(c => new HelloTests(c))) System.exit(1) 24 | } 25 | } -------------------------------------------------------------------------------- /src/main/scala/io/readppa.scala: -------------------------------------------------------------------------------- 1 | package io 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | import scala.io.Source 8 | import scala.util.control._ 9 | 10 | object ReadPPA { 11 | def readFromPPATxt(filePath: String) = { 12 | val source = Source.fromFile(filePath, "UTF-8") 13 | 14 | val lines = source.getLines().toArray 15 | source.close 16 | lines 17 | } 18 | 19 | // get bits of an adder 20 | def getBits(array: Array[String]): List[Int] = { 21 | val inputbits = array(0).trim.split(" ") 22 | val res = inputbits(0).toInt :: Nil 23 | res 24 | } 25 | 26 | // get the number of prefix cells 27 | def getNumCells(array: Array[String]): List[Int] = { 28 | val numcells = array(1).trim.split(" ") 29 | val res = numcells(0).toInt :: Nil 30 | res 31 | } 32 | 33 | // get arch description sequence 34 | def getArch(array: Array[String]): List[Int] = { 35 | val arraywithoutbits = array.takeRight(array.length - 2) 36 | val res = arraywithoutbits.map(s => s.trim.split(" ").map(i => i.toInt).toList).reduce(_ ::: _) 37 | res 38 | } 39 | 40 | // get depth of a prefix graph 41 | def getDepth(myarch: List[Int]): Int = { 42 | val len = myarch.length 43 | var dep = 1 44 | var ind = 500 45 | for (i <- 0 until len) { 46 | if (myarch(i) >= ind) { 47 | dep = dep + 1 48 | } 49 | ind = myarch(i) 50 | } 51 | dep 52 | } 53 | 54 | 55 | def genPEdge(n: Int, dep: Int, myarch: List[Int]): Map[List[Int], List[Int]] = { 56 | val len = myarch.length 57 | var pedge = Map[List[Int], List[Int]]() 58 | 59 | var tmpl = Map[Int, Int]() 60 | var tmplev = Map[Int, Int]() 61 | 62 | // initialize 63 | for (i <- 0 until n) { 64 | tmpl += i -> i 65 | tmplev += i -> -1 66 | } 67 | 68 | for (i <- 0 until len) { 69 | var x = myarch(i) 70 | var y = tmpl(myarch(i)) - 1 71 | var d1 = tmplev(x) 72 | var d2 = tmplev(y) 73 | var d3 = 0 74 | if (d1 > d2) { 75 | d3 = d1 + 1 76 | } else { 77 | d3 = d2 + 1 78 | } 79 | tmplev += myarch(i) -> d3 80 | tmpl += myarch(i) -> tmpl(y) 81 | pedge += List(d3, x) -> List(d2, y) 82 | } 83 | pedge 84 | } 85 | 86 | def genGEdge(n: Int, dep: Int, myarch: List[Int]): Map[List[Int], List[Int]] = { 87 | val len = myarch.length 88 | var gedge = Map[List[Int], List[Int]]() 89 | var isprefix = Map[List[Int], Int]() 90 | 91 | var tmpl = Map[Int, Int]() 92 | var tmplev = Map[Int, Int]() 93 | 94 | // initialize 95 | for (i <- 0 until n) { 96 | tmpl += i -> i 97 | tmplev += i -> -1 98 | } 99 | for (i <- 0 until dep) { 100 | for (j <- -1 until n) { 101 | isprefix += List(i, j) -> 0 102 | } 103 | } 104 | 105 | for (i <- 0 until len) { 106 | var x = myarch(i) 107 | var y = tmpl(myarch(i)) - 1 108 | var d1 = tmplev(x) 109 | var d2 = tmplev(y) 110 | var d3 = 0 111 | if (d1 > d2) { 112 | d3 = d1 + 1 113 | } else { 114 | d3 = d2 + 1 115 | } 116 | tmplev += myarch(i) -> d3 117 | tmpl += myarch(i) -> tmpl(y) 118 | gedge += List(d3, x) -> List(d1, x) 119 | } 120 | gedge 121 | } 122 | 123 | def genFinal(n: Int, myarch: List[Int]): Map[Int, Int] = { 124 | val len = myarch.length 125 | var res = Map[Int, Int]() 126 | for (i <- 0 until n) { 127 | res += i -> -1 128 | } 129 | 130 | var tmpl = Map[Int, Int]() 131 | var tmplev = Map[Int, Int]() 132 | 133 | // initialize 134 | for (i <- 0 until n) { 135 | tmpl += i -> i 136 | tmplev += i -> -1 137 | } 138 | 139 | for (i <- 0 until len) { 140 | var x = myarch(i) 141 | var y = tmpl(myarch(i)) - 1 142 | var d1 = tmplev(x) 143 | var d2 = tmplev(y) 144 | var d3 = 0 145 | if (d1 > d2) { 146 | d3 = d1 + 1 147 | } else { 148 | d3 = d2 + 1 149 | } 150 | tmplev += myarch(i) -> d3 151 | tmpl += myarch(i) -> tmpl(y) 152 | res += x -> d3 153 | } 154 | res 155 | } 156 | 157 | } -------------------------------------------------------------------------------- /src/main/scala/io/readwallace.scala: -------------------------------------------------------------------------------- 1 | package io 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | import scala.io.Source 8 | import scala.util.control._ 9 | 10 | object ReadWT { 11 | def readFromWTTxt(filePath: String) = { 12 | val source = Source.fromFile(filePath, "UTF-8") 13 | val lines = source.getLines().toArray 14 | source.close 15 | lines 16 | } 17 | 18 | // get bits of an multiplier 19 | def getBits(array: Array[String]): List[Int] = { 20 | val inputbits = array(0).trim.split(" ") 21 | val res = inputbits(0).toInt :: inputbits(1).toInt :: Nil 22 | res 23 | } 24 | 25 | // get the number of compressors 26 | def getNumCells(array: Array[String]): List[Int] = { 27 | val numcells = array(1).trim.split(" ") 28 | val res = numcells(0).toInt :: Nil 29 | res 30 | } 31 | 32 | // get arch description sequence 33 | def getArch(array: Array[String]): List[Int] = { 34 | val arraywithoutbits = array.takeRight(array.length - 2) 35 | val res = arraywithoutbits.map(s => s.trim.split(" ").map(i => i.toInt).toList).reduce(_ ::: _) 36 | res 37 | } 38 | 39 | // get depth of a compressor network 40 | def getDepth(myarch: List[Int]): Int = { 41 | val len = myarch.length 42 | var dep = 1 43 | var ind = 500 44 | var i = 0 45 | while (i < len) { 46 | if (myarch(i) > ind) { 47 | dep += 1 48 | } 49 | ind = myarch(i) 50 | i += 2 51 | } 52 | dep 53 | } 54 | 55 | 56 | def getIn(m: Int, n: Int, myarch: List[Int]): Map[List[Int], List[Int]] = { 57 | val len = myarch.length 58 | var edgesin = Map[List[Int], List[Int]]() 59 | 60 | var pos = Map[Int, Int]() 61 | 62 | var cnt = new Array[Int](256) 63 | 64 | for (i <- 0 until (n + m)) { 65 | pos += i -> 0 66 | cnt(i) = 0 67 | } 68 | 69 | var depth = 0 70 | var ind = 500 71 | var i = 0 72 | while (i < len) { 73 | if (myarch(i) > ind) { 74 | depth += 1 75 | for (j <- 0 until (n + m)) { 76 | cnt(j) = 0 77 | } 78 | } 79 | ind = myarch(i) 80 | cnt(myarch(i)) += 1 81 | var tmp = pos(myarch(i)) 82 | edgesin += List(myarch(i), depth, cnt(myarch(i))) -> List(tmp, myarch(i)) 83 | if (myarch(i + 1) == 0) { 84 | pos += myarch(i) -> (tmp + 2) 85 | } 86 | else if (myarch(i + 1) == 1) { 87 | pos += myarch(i) -> (tmp + 3) 88 | } else { 89 | println("Wrong compressor types!") 90 | } 91 | i += 2 92 | } 93 | edgesin 94 | } 95 | 96 | def getIn1(m: Int, n: Int, myarch: List[Int]): Map[List[Int], List[Int]] = { 97 | val len = myarch.length 98 | var edgesin = Map[List[Int], List[Int]]() 99 | 100 | var pos = Map[Int, Int]() 101 | 102 | var cnt = new Array[Int](256) 103 | 104 | for (i <- 0 until (n + m)) { 105 | pos += i -> 0 106 | cnt(i) = 0 107 | } 108 | 109 | var depth = 0 110 | var ind = 500 111 | var i = 0 112 | while (i < len) { 113 | if (myarch(i) > ind) { 114 | depth += 1 115 | for (j <- 0 until (n + m)) { 116 | cnt(j) = 0 117 | } 118 | } 119 | ind = myarch(i) 120 | cnt(myarch(i)) += 1 121 | var tmp = pos(myarch(i)) 122 | edgesin += List(myarch(i), depth, cnt(myarch(i))) -> List(tmp, myarch(i)) 123 | if (myarch(i + 1) == 0) { 124 | pos += myarch(i) -> (tmp + 2) 125 | } 126 | else if (myarch(i + 1) == 1) { 127 | pos += myarch(i) -> (tmp + 3) 128 | } else { 129 | println("Wrong compressor types!") 130 | } 131 | i += 2 132 | } 133 | edgesin 134 | } 135 | 136 | 137 | def getOut1(m: Int, n: Int, myarch: List[Int]): Map[List[Int], List[Int]] = { 138 | val len = myarch.length 139 | var edgesout = Map[List[Int], List[Int]]() 140 | 141 | var pos = Map[Int, Int]() 142 | 143 | var cnt = new Array[Int](256) 144 | 145 | var abs = 0 146 | var min = 0 147 | if (m > n) { 148 | abs = m - n 149 | min = n 150 | } else { 151 | abs = n - m 152 | min = m 153 | } 154 | 155 | for (i <- 0 until (n + m - 1)) { 156 | if (i < min) { 157 | var ttmp = i + 1 + 1 158 | pos += i -> ttmp 159 | } 160 | else if (i >= min && i < (min + abs)) { 161 | var ttmp = (1 + min) + 1 162 | pos += i -> ttmp 163 | } else { 164 | var ttmp = (n + m - i - 1) + 1 165 | pos += i -> ttmp 166 | } 167 | } 168 | pos += (n + m - 1) -> 0 169 | 170 | var depth = 0 171 | var ind = 500 172 | var i = 0 173 | while (i < len) { 174 | if (myarch(i) > ind) { 175 | depth += 1 176 | for (j <- 0 until (n + m)) { 177 | cnt(j) = 0 178 | } 179 | } 180 | ind = myarch(i) 181 | cnt(myarch(i)) += 1 182 | var tmp = pos(myarch(i)) 183 | var tmp1 = pos(myarch(i) + 1) 184 | edgesout += List(myarch(i), depth, cnt(myarch(i))) -> List(tmp, myarch(i), tmp1, myarch(i) + 1) 185 | pos += myarch(i) -> (tmp + 1) 186 | pos += (myarch(i) + 1) -> (tmp1 + 1) 187 | i += 2 188 | } 189 | edgesout 190 | } 191 | 192 | def getOut(m: Int, n: Int, myarch: List[Int]): Map[List[Int], List[Int]] = { 193 | val len = myarch.length 194 | var edgesout = Map[List[Int], List[Int]]() 195 | 196 | var pos = Map[Int, Int]() 197 | 198 | var cnt = new Array[Int](256) 199 | 200 | var abs = 0 201 | var min = 0 202 | if (m > n) { 203 | abs = m - n 204 | min = n 205 | } else { 206 | abs = n - m 207 | min = m 208 | } 209 | 210 | for (i <- 0 until (n + m)) { 211 | if (i < min) { 212 | pos += i -> (i + 1) 213 | } 214 | else if (i >= min && i < (min + abs)) { 215 | pos += i -> min 216 | } else { 217 | pos += i -> (m + n - i - 1) 218 | } 219 | } 220 | 221 | var depth = 0 222 | var ind = 500 223 | var i = 0 224 | while (i < len) { 225 | if (myarch(i) > ind) { 226 | depth += 1 227 | for (j <- 0 until (n + m)) { 228 | cnt(j) = 0 229 | } 230 | } 231 | ind = myarch(i) 232 | cnt(myarch(i)) += 1 233 | var tmp = pos(myarch(i)) 234 | var tmp1 = pos(myarch(i) + 1) 235 | edgesout += List(myarch(i), depth, cnt(myarch(i))) -> List(tmp, myarch(i), tmp1, myarch(i) + 1) 236 | pos += myarch(i) -> (tmp + 1) 237 | pos += (myarch(i) + 1) -> (tmp1 + 1) 238 | i += 2 239 | } 240 | edgesout 241 | } 242 | 243 | 244 | /** 245 | * A procedure to help generate a compressor network for a multiplication unit. 246 | * 247 | * An `m`-bit multiplicand multiplying an `n`-bit multiplier generates `m*n`-bit partial products. 248 | * The bits in the partial products are represented by dots, initially in a trapezoidal shape. 249 | * In the code, we simulate the dot compression process using the compressors in `myarch`. 250 | * During compression, any new bit is stacked in a higher row number in the corresponding column. 251 | * The row numbers of the remaining dots in each column are returned to the generator. 252 | * 253 | * @param m The bit width of the multiplicand. 254 | * @param n The bit width of the multiplier. 255 | * @param myarch The (reversed) sequence representation of the compressor network. 256 | * @return The count and row number of remaining dots in each column. 257 | */ 258 | def getRes(m: Int, n: Int, myarch: List[Int]): Map[Int, List[Int]] = { 259 | var res = Map[Int, List[Int]]() // column number -> a list of row numbers with -1 padding 260 | 261 | val len = myarch.length / 2 // the number of compressors 262 | 263 | var compressorCount = Map[List[Int], Int]() // compressor code -> the number of compressors 264 | var rowNumber = Map[Int, Int]() // column number -> current row number 265 | 266 | var initDots = new Array[Int](m + n) // the initial dots in a trapezoidal shape 267 | var compDots = new Array[Int](m + n) // the remaining dots after compression 268 | 269 | val diff = Math.abs(m - n) 270 | val min = Math.min(m, n) 271 | 272 | // generate the dots in the initial partial products 273 | for (col <- 0 until (n + m - 1)) { 274 | if (col < min) { 275 | initDots(col) = col + 1 276 | rowNumber += col -> initDots(col) 277 | } 278 | else if (col >= min && col < (min + diff)) { 279 | initDots(col) = min 280 | rowNumber += col -> initDots(col) 281 | } else { 282 | initDots(col) = n + m - 1 - col 283 | rowNumber += col -> initDots(col) 284 | } 285 | compressorCount += List(col, 0) -> 0 286 | compressorCount += List(col, 1) -> 0 287 | } 288 | 289 | // count the compressors in `myarch` 290 | for (i <- 0 until len) { 291 | val idx = 2 * i 292 | val code = List(myarch(idx), myarch(idx + 1)) 293 | val count = compressorCount(code) 294 | compressorCount += code -> (count + 1) 295 | } 296 | 297 | // update the row numbers in the columns by scanning `myarch` 298 | for (i <- 0 until len) { 299 | val idx = 2 * i 300 | val currColNum = myarch(idx) 301 | val nextColNum = currColNum + 1 302 | val currRowNum = rowNumber(currColNum) 303 | val nextRowNum = rowNumber(nextColNum) 304 | rowNumber += currColNum -> (currRowNum + 1) 305 | rowNumber += nextColNum -> (nextRowNum + 1) 306 | } 307 | 308 | // check for over-compression and lack-of-compression 309 | compDots(0) = 1 310 | for (col <- 1 until (n + m - 1)) { 311 | var currC22Count = compressorCount(List(col, 0)) 312 | var currC32Count = compressorCount(List(col, 1)) 313 | var prevC22Count = compressorCount(List(col - 1, 0)) 314 | var prevC32Count = compressorCount(List(col - 1, 1)) 315 | compDots(col) = initDots(col) + prevC22Count + prevC32Count + (1 - 2) * currC22Count + (1 - 3) * currC32Count 316 | if (compDots(col) < 0 || compDots(col) > 2) { 317 | println("Wrong Compressors Structure! At column = " + col + " and res=" + compDots(col)) 318 | } 319 | } 320 | 321 | // collect the row numbers of the one or two remaining dots in each column 322 | for (col <- 0 until (n + m - 1)) { 323 | if (compDots(col) == 1) { 324 | res += col -> List(rowNumber(col) - 1, -1) // padding with -1 for a single remaining dot 325 | } 326 | else if (compDots(col) == 2) { 327 | res += col -> List(rowNumber(col) - 2, rowNumber(col) - 1) // two remaining dots 328 | } else { 329 | println("Wrong Compressors Results! At column = " + col) 330 | } 331 | } 332 | res 333 | } 334 | 335 | } 336 | -------------------------------------------------------------------------------- /src/main/scala/mac/mac.scala: -------------------------------------------------------------------------------- 1 | package mac 2 | 3 | import io._ 4 | import ppadder._ 5 | import partialprod._ 6 | import wallace._ 7 | import wtmultiplier._ 8 | 9 | import chisel3.iotesters.PeekPokeTester 10 | import chisel3.util._ 11 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 12 | 13 | import java.io.PrintWriter 14 | import java.io.File 15 | 16 | import scala.io.Source 17 | 18 | class MAC(m: Int, n: Int, myarchw: List[Int], inedges: Map[List[Int], List[Int]], outedges: Map[List[Int], List[Int]], res: Map[Int, List[Int]], 19 | myarcha: List[Int], pedge: Map[List[Int], List[Int]], gedge: Map[List[Int], List[Int]], post: Map[Int, Int], 20 | myarcha2: List[Int], pedge2: Map[List[Int], List[Int]], gedge2: Map[List[Int], List[Int]], post2: Map[Int, Int]) extends Module { 21 | val io = IO(new Bundle { 22 | val multiplicand = Input(UInt(m.W)) 23 | val multiplier = Input(UInt(n.W)) 24 | val addend = Input(UInt((m + n - 1).W)) 25 | val outs = Output(UInt((m + n - 1).W)) 26 | }) 27 | 28 | val pp = Module(new PartialProd(m, n)) 29 | pp.io.multiplicand := io.multiplicand 30 | pp.io.multiplier := io.multiplier 31 | 32 | val wt = Module(new Wallace(m, n, myarchw, inedges, outedges, res)) 33 | wt.io.pp := pp.io.outs 34 | 35 | val ppa1 = Module(new PPAdder((m + n - 1), myarcha, pedge, gedge, post)) 36 | ppa1.io.augend := wt.io.augend 37 | ppa1.io.addend := wt.io.addend 38 | 39 | val ppa2 = Module(new PPAdder((m + n - 1), myarcha2, pedge2, gedge2, post2)) 40 | ppa2.io.augend := ppa1.io.outs 41 | ppa2.io.addend := io.addend 42 | 43 | io.outs := ppa2.io.outs 44 | } 45 | 46 | class MAC1(m: Int, n: Int, myarchw: List[Int], inedges: Map[List[Int], List[Int]], outedges: Map[List[Int], List[Int]], res: Map[Int, List[Int]], 47 | myarcha: List[Int], pedge: Map[List[Int], List[Int]], gedge: Map[List[Int], List[Int]], post: Map[Int, Int], 48 | myarcha2: List[Int], pedge2: Map[List[Int], List[Int]], gedge2: Map[List[Int], List[Int]], post2: Map[Int, Int]) extends Module { 49 | val io = IO(new Bundle { 50 | val multiplicand = Input(UInt(m.W)) 51 | val multiplier = Input(UInt(n.W)) 52 | val addend = Input(UInt((m + n - 1).W)) 53 | val outs = Output(UInt((m + n - 1).W)) 54 | }) 55 | 56 | val wtm = Module(new WTMultiplier(m, n, myarchw, inedges, outedges, res, myarcha, pedge, gedge, post)) 57 | wtm.io.multiplicand := io.multiplicand 58 | wtm.io.multiplier := io.multiplier 59 | 60 | val ppa = Module(new PPAdder((m + n - 1), myarcha2, pedge2, gedge2, post2)) 61 | ppa.io.augend := wtm.io.outs 62 | ppa.io.addend := io.addend 63 | 64 | io.outs := ppa.io.outs 65 | } 66 | 67 | object test { 68 | val usage = 69 | """ 70 | Usage: generate [--compressor-file filename1] [--prefix-adder-file filename2] [--accumulator-file filename3] 71 | """ 72 | 73 | def main(args: Array[String]): Unit = { 74 | 75 | if (args.length == 0) println(usage) 76 | 77 | val arglist = args.toList 78 | 79 | //type OptionMap = Map[Symbol, Any] 80 | 81 | val argmap = (0 until arglist.size / 2).map(i => arglist(i * 2) -> arglist(i * 2 + 1)).toMap 82 | 83 | val filename1 = argmap("--compressor-file") 84 | val filename2 = argmap("--prefix-adder-file") 85 | val filename3 = argmap("--accumulator-file") 86 | 87 | val filecontent = ReadWT.readFromWTTxt(filename1) 88 | 89 | val m = ReadWT.getBits(filecontent)(0) 90 | val n = ReadWT.getBits(filecontent)(1) 91 | 92 | // wallace tree 93 | val numcompressors = ReadWT.getNumCells(filecontent)(0) 94 | 95 | val myarchw = ReadWT.getArch(filecontent) 96 | 97 | val depthw = ReadWT.getDepth(myarchw) 98 | 99 | val inedges = ReadWT.getIn(m, n, myarchw) 100 | 101 | val outedges = ReadWT.getOut(m, n, myarchw) 102 | 103 | val res = ReadWT.getRes(m, n, myarchw) 104 | 105 | //final adder 106 | val filecontent1 = ReadPPA.readFromPPATxt(filename2) 107 | 108 | val l = ReadPPA.getBits(filecontent1)(0) 109 | 110 | val numpgcells = ReadPPA.getNumCells(filecontent1)(0) 111 | 112 | val myarcha = ReadPPA.getArch(filecontent1) 113 | 114 | val deptha = ReadPPA.getDepth(myarcha) 115 | 116 | val pedge = ReadPPA.genPEdge(l, deptha, myarcha) 117 | 118 | val gedge = ReadPPA.genGEdge(l, deptha, myarcha) 119 | 120 | val pos = ReadPPA.genFinal(l, myarcha) 121 | 122 | //accumulate adder 123 | val filecontent2 = ReadPPA.readFromPPATxt(filename2) 124 | 125 | val l2 = ReadPPA.getBits(filecontent2)(0) 126 | 127 | val numpgcells2 = ReadPPA.getNumCells(filecontent1)(0) 128 | 129 | val myarcha2 = ReadPPA.getArch(filecontent1) 130 | 131 | val deptha2 = ReadPPA.getDepth(myarcha) 132 | 133 | val pedge2 = ReadPPA.genPEdge(l, deptha, myarcha) 134 | 135 | val gedge2 = ReadPPA.genGEdge(l, deptha, myarcha) 136 | 137 | val pos2 = ReadPPA.genFinal(l, myarcha) 138 | 139 | val topDesign = () => new MAC(m, n, myarchw, inedges, outedges, res, myarcha, pedge, gedge, pos, myarcha2, pedge2, gedge2, pos2) 140 | (new chisel3.stage.ChiselStage).emitVerilog(topDesign(), Array("-td", "./RTL/mac")) 141 | iotesters.Driver.execute(Array("-tgvo", "on", "-tbn", "verilator"), topDesign) { 142 | c => new MACTester(c) 143 | } 144 | } 145 | } 146 | 147 | class MACTester(c: MAC) extends PeekPokeTester(c) { 148 | poke(c.io.multiplicand, 7) 149 | poke(c.io.multiplier, 2) 150 | poke(c.io.addend, 1) 151 | 152 | step(1) 153 | 154 | println("The result of 7 * 2 + 1 is: " + peek(c.io.outs).toString()) 155 | 156 | expect(c.io.outs, 15) 157 | } 158 | -------------------------------------------------------------------------------- /src/main/scala/partialprod/partialprod.scala: -------------------------------------------------------------------------------- 1 | package partialprod 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | class PartialProd(m: Int, n: Int) extends Module { 8 | val io = IO(new Bundle { 9 | val multiplicand = Input(UInt(m.W)) 10 | val multiplier = Input(UInt(n.W)) 11 | val outs = Output(Vec(n, UInt(m.W))) 12 | }) 13 | for (i <- 0 until n) { 14 | val tmp = (0 until m).map(j => Wire(UInt(1.W))) 15 | for (j <- 0 until m) { 16 | tmp(j) := io.multiplicand(j) & io.multiplier(i) 17 | } 18 | io.outs(i) := tmp.reverse.reduce(Cat(_, _)) 19 | } 20 | } 21 | 22 | /* 23 | object test{ 24 | def main(args: Array[String]): Unit = { 25 | 26 | val topDesign = () => new PartialProd(4,3) 27 | chisel3.Driver.execute(Array("-td", "./RTL/partial"), topDesign) 28 | 29 | iotesters.Driver.execute(Array("-tgvo", "on", "-tbn", "verilator"), topDesign) { 30 | c => new PartialProdTester(c) 31 | } 32 | 33 | iotesters.Driver.execute(Array("-tgvo", "on", "-tbn", "verilator"), () => new PartialProd(4,3)) { 34 | c => new PartialProdTester(c) 35 | } 36 | } 37 | } 38 | 39 | class PartialProdTester(c: PartialProd) extends PeekPokeTester(c) { 40 | poke(c.io.multiplicand, 5) 41 | poke(c.io.multiplier, 2) 42 | 43 | step(1) 44 | println("The multiplicand is: " + peek(c.io.multiplicand).toString()) 45 | 46 | println("The result of 5 * 2 with is: " + peek(c.io.outs(0)).toString()) 47 | 48 | expect(c.io.outs(0), 0) 49 | expect(c.io.outs(1), 5) 50 | expect(c.io.outs(2), 0) 51 | }*/ -------------------------------------------------------------------------------- /src/main/scala/partialprod/radix4encoder.scala: -------------------------------------------------------------------------------- 1 | package booth 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | class Radix4Enc extends Module { 8 | val io = IO(new Bundle { 9 | val I = Input(UInt(3.W)) 10 | val Neg = Output(UInt(1.W)) 11 | val One = Output(UInt(1.W)) 12 | val Two = Output(UInt(1.W)) 13 | val Zero = Output(UInt(1.W)) 14 | }) 15 | 16 | io.Neg := io.I(2) 17 | val con1 = (io.I === 0.U(3.W)) || (io.I === 5.U(3.W)) 18 | val con2 = (io.I === 4.U(3.W)) || (io.I === 3.U(3.W)) 19 | io.Zero := con1 20 | io.Two := con2 21 | io.One := !io.Zero & !io.Two 22 | 23 | } 24 | 25 | /** Radix-4 Partial Product Generator 26 | * 27 | * @param w the data width 28 | */ 29 | /* 30 | class Radix4Gen(w: Int) extends Module { 31 | val io = IO(new Bundle { 32 | val inputs = Input(UInt(w.W)) 33 | val neg = Input(UInt(1.W)) 34 | val zero = Input(UInt(1.W)) 35 | val one = Input(UInt(1.W)) 36 | val two = Input(UInt(1.W)) 37 | val outs = Output(MixedVec(Seq(UInt(w.W)))) 38 | }) 39 | */ -------------------------------------------------------------------------------- /src/main/scala/ppadder/pg.scala: -------------------------------------------------------------------------------- 1 | package ppadder 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | class Grey extends Module { 8 | val io = IO(new Bundle { 9 | val i_gj = Input(UInt(1.W)) 10 | val i_pk = Input(UInt(1.W)) 11 | val i_gk = Input(UInt(1.W)) 12 | val o_g = Output(UInt(1.W)) 13 | }) 14 | io.o_g := io.i_gk | (io.i_gj & io.i_pk); 15 | } 16 | 17 | class Black extends Module { 18 | val io = IO(new Bundle { 19 | val i_pj = Input(UInt(1.W)) 20 | val i_gj = Input(UInt(1.W)) 21 | val i_pk = Input(UInt(1.W)) 22 | val i_gk = Input(UInt(1.W)) 23 | val o_g = Output(UInt(1.W)) 24 | val o_p = Output(UInt(1.W)) 25 | }) 26 | io.o_g := io.i_gk | (io.i_gj & io.i_pk) 27 | io.o_p := io.i_pk & io.i_pj 28 | } 29 | 30 | class Buffer extends Module { 31 | val io = IO(new Bundle { 32 | val i_p = Input(UInt(1.W)) 33 | val i_g = Input(UInt(1.W)) 34 | val o_p = Output(UInt(1.W)) 35 | val o_g = Output(UInt(1.W)) 36 | }) 37 | io.o_p := io.i_p 38 | io.o_g := io.i_g 39 | } 40 | 41 | class PG extends Module { 42 | val io = IO(new Bundle { 43 | val i_a = Input(UInt(1.W)) 44 | val i_b = Input(UInt(1.W)) 45 | val o_p = Output(UInt(1.W)) 46 | val o_g = Output(UInt(1.W)) 47 | }) 48 | io.o_p := io.i_a ^ io.i_b 49 | io.o_g := io.i_a & io.i_b 50 | } -------------------------------------------------------------------------------- /src/main/scala/ppadder/ppadder.scala: -------------------------------------------------------------------------------- 1 | package ppadder 2 | 3 | import io._ 4 | import chisel3.iotesters.PeekPokeTester 5 | import chisel3.util._ 6 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 7 | //import chisel3.{Bundle, _} 8 | 9 | import java.io.PrintWriter 10 | import java.io.File 11 | 12 | import scala.io.Source 13 | 14 | 15 | class PPAdder(n: Int, myarch: List[Int], pedge: Map[List[Int], List[Int]], gedge: Map[List[Int], List[Int]], post: Map[Int, Int]) extends Module { 16 | val io = IO(new Bundle { 17 | val augend = Input(UInt(n.W)) 18 | val addend = Input(UInt(n.W)) 19 | val outs = Output(UInt(n.W)) 20 | }) 21 | 22 | // pre-computations 23 | var tmpl = Map[Int, Int]() 24 | var tmplev = Map[Int, Int]() 25 | 26 | // initialize 27 | for (i <- 0 until n) { 28 | tmpl += i -> i 29 | tmplev += i -> -1 30 | } 31 | 32 | var GMap = Map[List[Int], Data]() 33 | var PMap = Map[List[Int], Data]() 34 | for (i <- 0 until n) { 35 | val pg = Module(new PG) 36 | pg.io.i_a := io.augend(i) 37 | pg.io.i_b := io.addend(i) 38 | GMap += List(-1, i) -> pg.io.o_g 39 | PMap += List(-1, i) -> pg.io.o_p 40 | } 41 | // prefix graph 42 | val len = myarch.length 43 | val len1 = pedge.size 44 | val len2 = gedge.size 45 | assert(len == len1, "Wrong Parse Results") 46 | assert(len == len2, "Wrong Parse Results") 47 | assert(len1 == len2, "Wrong Parse Results") 48 | 49 | for (i <- 0 until len1) { 50 | var x = myarch(i) 51 | var y = tmpl(myarch(i)) - 1 52 | var d1 = tmplev(x) 53 | var d2 = tmplev(y) 54 | var d3 = 0 55 | if (d1 > d2) { 56 | d3 = d1 + 1 57 | } else { 58 | d3 = d2 + 1 59 | } 60 | tmplev += myarch(i) -> d3 61 | tmpl += myarch(i) -> tmpl(y) 62 | val black = Module(new Black) 63 | black.io.i_gk := GMap(gedge(List(d3, x))) 64 | black.io.i_pk := PMap(gedge(List(d3, x))) 65 | black.io.i_gj := GMap(pedge(List(d3, x))) 66 | black.io.i_pj := PMap(pedge(List(d3, x))) 67 | 68 | GMap += List(d3, x) -> black.io.o_g 69 | PMap += List(d3, x) -> black.io.o_p 70 | } 71 | 72 | // post computation 73 | val carry = (0 until n).map(i => GMap(List(post(i), i)).asUInt()) 74 | 75 | val res = (0 until n).map(i => Wire(UInt(1.W))) 76 | res(0) := PMap(List(-1, 0)).asUInt() ^ 0.U 77 | printf(p"res(0) = ${res(0)}\n") 78 | 79 | for (i <- 1 until n) { 80 | val resi = PMap(List(-1, i)).asUInt() ^ carry(i - 1).asUInt() 81 | res(i) := resi.asUInt() 82 | } 83 | 84 | io.outs := res.reverse.reduce(Cat(_, _)) 85 | } 86 | 87 | /* 88 | object test{ 89 | val usage = """ 90 | Usage: generate [--input1-bit input1] [--input2-bit input2] [--compressor-file filename1] [--prefix-adder-file filename2] 91 | """ 92 | def main(args: Array[String]): Unit = { 93 | 94 | if (args.length == 0) println(usage) 95 | 96 | val arglist = args.toList 97 | val optionNames = arglist.filter(s => s.contains('-')) 98 | 99 | //type OptionMap = Map[Symbol, Any] 100 | 101 | val argmap = (0 until arglist.size / 2).map(i => arglist(i * 2) -> arglist(i * 2 + 1)).toMap 102 | 103 | val filename1 = argmap("--prefix-adder-file") 104 | 105 | val filecontent = ReadPPA.readFromPPATxt(filename1) 106 | 107 | val n = ReadPPA.getBits(filecontent)(0) 108 | 109 | val numcells = ReadPPA.getNumCells(filecontent)(0) 110 | 111 | val myarch = ReadPPA.getArch(filecontent) 112 | 113 | val dep = ReadPPA.getDepth(myarch) 114 | 115 | val pedge = ReadPPA.genPEdge(n, dep, myarch) 116 | 117 | val gedge = ReadPPA.genGEdge(n, dep, myarch) 118 | 119 | val pos = ReadPPA.genFinal(n, myarch) 120 | 121 | val topDesign = () => new PPAdder(n, myarch, pedge, gedge, pos) 122 | chisel3.Driver.execute(Array("-td", "./RTL/ppadder"), topDesign) 123 | iotesters.Driver.execute(Array("-tgvo", "on", "-tbn", "verilator"), topDesign) { 124 | c => new PPAdderTester(c) 125 | } 126 | 127 | iotesters.Driver.execute(Array("-tgvo", "on", "-tbn", "verilator"), () => new PPAdder(n, myarch, pedge, gedge, pos)) { 128 | c => new PPAdderTester(c) 129 | } 130 | } 131 | } 132 | 133 | class PPAdderTester(c: PPAdder) extends PeekPokeTester(c) { 134 | poke(c.io.augend, 12) 135 | poke(c.io.addend, 54) 136 | 137 | step(1) 138 | println("The addend of parallel prefix adder is: " + peek(c.io.addend).toString()) 139 | println("The result of parallel prefix adder is: " + peek(c.io.outs).toString()) 140 | 141 | println("The result of 12 + 54 with is: " + peek(c.io.outs).toString()) 142 | 143 | expect(c.io.outs, 66) 144 | }*/ 145 | -------------------------------------------------------------------------------- /src/main/scala/wallace/comp.scala: -------------------------------------------------------------------------------- 1 | package wallace 2 | 3 | import chisel3.iotesters.PeekPokeTester 4 | import chisel3.util._ 5 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 6 | 7 | class HalfAdder extends Module { 8 | val io = IO(new Bundle { 9 | val a = Input(UInt(1.W)) 10 | val b = Input(UInt(1.W)) 11 | val s = Output(UInt(1.W)) 12 | val co = Output(UInt(1.W)) 13 | }) 14 | 15 | io.s := io.a ^ io.b 16 | io.co := io.a & io.b 17 | } 18 | 19 | class FullAdder extends Module { 20 | val io = IO(new Bundle { 21 | val a = Input(UInt(1.W)) 22 | val b = Input(UInt(1.W)) 23 | val ci = Input(UInt(1.W)) 24 | val s = Output(UInt(1.W)) 25 | val co = Output(UInt(1.W)) 26 | }) 27 | 28 | val a_xor_b = io.a ^ io.b 29 | io.s := a_xor_b ^ io.ci 30 | 31 | val a_and_b = io.a & io.b 32 | val a_and_cin = io.a & io.ci 33 | val b_and_cin = io.b & io.ci 34 | io.co := a_and_b | b_and_cin | a_and_cin 35 | } 36 | -------------------------------------------------------------------------------- /src/main/scala/wallace/wallace.scala: -------------------------------------------------------------------------------- 1 | package wallace 2 | 3 | import io._ 4 | import chisel3.iotesters.PeekPokeTester 5 | import chisel3.util._ 6 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 7 | 8 | import java.io.PrintWriter 9 | import java.io.File 10 | 11 | import scala.io.Source 12 | 13 | class Wallace(m: Int, n: Int, myarch: List[Int], inedges: Map[List[Int], List[Int]], outedges: Map[List[Int], List[Int]], res: Map[Int, List[Int]]) extends Module { 14 | val io = IO(new Bundle { 15 | val pp = Input(Vec(n, UInt(m.W))) 16 | val augend = Output(UInt((n + m).W)) 17 | val addend = Output(UInt((n + m).W)) 18 | }) 19 | 20 | var ValueMap = Map[List[Int], Data]() 21 | 22 | for (i <- 0 until n) { 23 | for (j <- 0 until m) { 24 | var tmpx = i 25 | var tmpy = i + j 26 | var fy = tmpy 27 | var fx = 0 28 | if (tmpy >= m) { 29 | var move = tmpy - m + 1 30 | fx = tmpx - move 31 | } else { 32 | fx = tmpx 33 | } 34 | ValueMap += List(fx, fy) -> io.pp(i)(j) 35 | } 36 | } 37 | 38 | val len = myarch.length 39 | var depth = 0 40 | var ind = 500 41 | var i = 0 42 | var cnt = new Array[Int](256) 43 | while (i < len) { 44 | if (myarch(i) > ind) { 45 | depth += 1 46 | for (j <- 0 until (n + m)) { 47 | cnt(j) = 0 48 | } 49 | } 50 | ind = myarch(i) 51 | cnt(myarch(i)) += 1 52 | 53 | if (myarch(i + 1) == 0) { 54 | val cmp22 = Module(new HalfAdder) 55 | val tmpin = inedges(List(myarch(i), depth, cnt(myarch(i)))) 56 | cmp22.io.a := ValueMap(List(tmpin(0), tmpin(1))) 57 | cmp22.io.b := ValueMap(List(tmpin(0) + 1, tmpin(1))) 58 | val tmpout = outedges(List(myarch(i), depth, cnt(myarch(i)))) 59 | ValueMap += List(tmpout(0), tmpout(1)) -> cmp22.io.s 60 | ValueMap += List(tmpout(2), tmpout(3)) -> cmp22.io.co 61 | } 62 | else if (myarch(i + 1) == 1) { 63 | val cmp32 = Module(new FullAdder) 64 | val tmpin = inedges(List(myarch(i), depth, cnt(myarch(i)))) 65 | cmp32.io.a := ValueMap(List(tmpin(0), tmpin(1))) 66 | cmp32.io.b := ValueMap(List(tmpin(0) + 1, tmpin(1))) 67 | cmp32.io.ci := ValueMap(List(tmpin(0) + 2, tmpin(1))) 68 | val tmpout = outedges(List(myarch(i), depth, cnt(myarch(i)))) 69 | ValueMap += List(tmpout(0), tmpout(1)) -> cmp32.io.s 70 | ValueMap += List(tmpout(2), tmpout(3)) -> cmp32.io.co 71 | } 72 | i += 2 73 | } 74 | val res0 = (0 until (m + n - 1)).map(i => Wire(UInt(1.W))) 75 | val res1 = (0 until (m + n - 1)).map(i => Wire(UInt(1.W))) 76 | 77 | 78 | for (j <- 0 until (m + n - 1)) { 79 | res0(j) := ValueMap(List(res(j)(0), j)) 80 | if (res(j)(1) == -1) { 81 | res1(j) := 0.asUInt() 82 | } else { 83 | res1(j) := ValueMap(List(res(j)(1), j)) 84 | } 85 | } 86 | io.augend := res0.reverse.reduce(Cat(_, _)) 87 | io.addend := res1.reverse.reduce(Cat(_, _)) 88 | } 89 | 90 | class Wallace1(m: Int, n: Int, myarch: List[Int], inedges: Map[List[Int], List[Int]], outedges: Map[List[Int], List[Int]], res: Map[Int, List[Int]]) extends Module { 91 | val io = IO(new Bundle { 92 | val pp = Input(Vec(n, UInt(m.W))) 93 | val accmulatend = Input(UInt((n + m - 1).W)) 94 | val augend = Output(UInt((n + m).W)) 95 | val addend = Output(UInt((n + m).W)) 96 | }) 97 | 98 | var ValueMap = Map[List[Int], Data]() 99 | 100 | for (i <- 0 until n) { 101 | for (j <- 0 until m) { 102 | var tmpx = i 103 | var tmpy = i + j 104 | var fy = tmpy 105 | var fx = 0 106 | if (tmpy >= m) { 107 | var move = tmpy - m + 1 108 | fx = tmpx - move 109 | } else { 110 | fx = tmpx 111 | } 112 | ValueMap += List(fx, fy) -> io.pp(i)(j) 113 | } 114 | } 115 | 116 | for (i <- 0 until (n + m - 1)) { 117 | var move = 0; 118 | if (m >= n) { 119 | if (i < n - 1) { 120 | move = n - 1 - i; 121 | } 122 | else if (i >= m) { 123 | move = i - m + 1; 124 | } 125 | else { 126 | move = 0; 127 | } 128 | } 129 | else { 130 | var min = n - m; 131 | if (i < m - 1) { 132 | move = m - 1 - i + min; 133 | } 134 | else if (i > n - 1) { 135 | move = i - n + 1 + min; 136 | } 137 | else { 138 | move = min; 139 | } 140 | } 141 | ValueMap += List(n - move, i) -> io.accmulatend(i) 142 | } 143 | 144 | val len = myarch.length 145 | var depth = 0 146 | var ind = 500 147 | var i = 0 148 | var cnt = new Array[Int](256) 149 | while (i < len) { 150 | if (myarch(i) > ind) { 151 | depth += 1 152 | for (j <- 0 until (n + m)) { 153 | cnt(j) = 0 154 | } 155 | } 156 | ind = myarch(i) 157 | cnt(myarch(i)) += 1 158 | 159 | if (myarch(i + 1) == 0) { 160 | val cmp22 = Module(new HalfAdder) 161 | val tmpin = inedges(List(myarch(i), depth, cnt(myarch(i)))) 162 | cmp22.io.a := ValueMap(List(tmpin(0), tmpin(1))) 163 | cmp22.io.b := ValueMap(List(tmpin(0) + 1, tmpin(1))) 164 | val tmpout = outedges(List(myarch(i), depth, cnt(myarch(i)))) 165 | ValueMap += List(tmpout(0), tmpout(1)) -> cmp22.io.s 166 | ValueMap += List(tmpout(2), tmpout(3)) -> cmp22.io.co 167 | } 168 | else if (myarch(i + 1) == 1) { 169 | val cmp32 = Module(new FullAdder) 170 | val tmpin = inedges(List(myarch(i), depth, cnt(myarch(i)))) 171 | cmp32.io.a := ValueMap(List(tmpin(0), tmpin(1))) 172 | cmp32.io.b := ValueMap(List(tmpin(0) + 1, tmpin(1))) 173 | cmp32.io.ci := ValueMap(List(tmpin(0) + 2, tmpin(1))) 174 | val tmpout = outedges(List(myarch(i), depth, cnt(myarch(i)))) 175 | ValueMap += List(tmpout(0), tmpout(1)) -> cmp32.io.s 176 | ValueMap += List(tmpout(2), tmpout(3)) -> cmp32.io.co 177 | } 178 | i += 2 179 | } 180 | val res0 = (0 until (m + n)).map(i => Wire(UInt(1.W))) 181 | val res1 = (0 until (m + n)).map(i => Wire(UInt(1.W))) 182 | 183 | 184 | for (j <- 0 until (m + n)) { 185 | res0(j) := ValueMap(List(res(j)(0), j)) 186 | if (res(j)(1) == -1) { 187 | res1(j) := 0.asUInt() 188 | } else { 189 | res1(j) := ValueMap(List(res(j)(1), j)) 190 | } 191 | } 192 | io.augend := res0.reverse.reduce(Cat(_, _)) 193 | io.addend := res1.reverse.reduce(Cat(_, _)) 194 | } 195 | 196 | /* 197 | object test{ 198 | val usage = """ 199 | Usage: readwt [--wallace-file filename1] 200 | """ 201 | def main(args: Array[String]): Unit = { 202 | 203 | if (args.length == 0) println(usage) 204 | 205 | val arglist = args.toList 206 | val optionNames = arglist.filter(s => s.contains('-')) 207 | 208 | val argmap = (0 until arglist.size / 2).map(i => arglist(i * 2) -> arglist(i * 2 + 1)).toMap 209 | 210 | val filename1 = argmap("--wallace-file") 211 | 212 | val filecontent = ReadWT.readFromWTTxt(filename1) 213 | 214 | val m = ReadWT.getBits(filecontent)(0) 215 | val n = ReadWT.getBits(filecontent)(1) 216 | 217 | val numcells = ReadWT.getNumCells(filecontent)(0) 218 | 219 | val myarch = ReadWT.getArch(filecontent) 220 | 221 | val depth = ReadWT.getDepth(myarch) 222 | 223 | val inedges = ReadWT.getIn(m, n, myarch) 224 | 225 | val outedges = ReadWT.getOut(m, n, myarch) 226 | 227 | val res = ReadWT.getRes(m, n, myarch) 228 | 229 | val topDesign = () => new Wallace(m, n, myarch, inedges, outedges, res) 230 | chisel3.Driver.execute(Array("-td", "./RTL/wt"), topDesign) 231 | iotesters.Driver.execute(Array("-tgvo", "on", "-tbn", "verilator"), topDesign) { 232 | c => new WallaceTester(c) 233 | } 234 | 235 | iotesters.Driver.execute(Array("-tgvo", "on", "-tbn", "verilator"), () => new Wallace(m, n, myarch, inedges, outedges, res)) { 236 | c => new WallaceTester(c) 237 | } 238 | } 239 | } 240 | 241 | class WallaceTester(c: Wallace) extends PeekPokeTester(c) { 242 | poke(c.io.pp(0), 0) 243 | poke(c.io.pp(1), 5) 244 | poke(c.io.pp(2), 0) 245 | poke(c.io.pp(3), 0) 246 | 247 | step(1) 248 | //println("The addend of parallel prefix adder is: " + peek(c.io.addend).toString()) 249 | //println("The result of parallel prefix adder is: " + peek(c.io.outs).toString()) 250 | 251 | println("The result of 5*2 with is: " + peek(c.io.augend).toString()) 252 | 253 | expect(c.io.augend, 8) 254 | }*/ -------------------------------------------------------------------------------- /src/main/scala/wtmultiplier/wtmultiplier.scala: -------------------------------------------------------------------------------- 1 | package wtmultiplier 2 | 3 | import io._ 4 | import ppadder._ 5 | import partialprod._ 6 | import wallace._ 7 | 8 | import chisel3.iotesters.PeekPokeTester 9 | import chisel3.util._ 10 | import chisel3.{Bundle, Input, Module, Output, UInt, _} 11 | 12 | import java.io.PrintWriter 13 | import java.io.File 14 | 15 | import scala.io.Source 16 | 17 | 18 | class WTMultiplier(m: Int, n: Int, myarchw: List[Int], inedges: Map[List[Int], List[Int]], outedges: Map[List[Int], List[Int]], res: Map[Int, List[Int]], myarcha: List[Int], pedge: Map[List[Int], List[Int]], gedge: Map[List[Int], List[Int]], post: Map[Int, Int]) extends Module { 19 | val io = IO(new Bundle { 20 | val multiplicand = Input(UInt(m.W)) 21 | val multiplier = Input(UInt(n.W)) 22 | val outs = Output(UInt((m + n - 1).W)) 23 | }) 24 | 25 | val pp = Module(new PartialProd(m, n)) 26 | pp.io.multiplicand := io.multiplicand 27 | pp.io.multiplier := io.multiplier 28 | 29 | val wt = Module(new Wallace(m, n, myarchw, inedges, outedges, res)) 30 | wt.io.pp := pp.io.outs 31 | 32 | val ppa = Module(new PPAdder((m + n - 1), myarcha, pedge, gedge, post)) 33 | ppa.io.augend := wt.io.augend 34 | ppa.io.addend := wt.io.addend 35 | 36 | io.outs := ppa.io.outs 37 | } 38 | 39 | /* 40 | object test{ 41 | val usage = """ 42 | Usage: generate [--input1-bit input1] [--input2-bit input2] [--compressor-file filename1] [--prefix-adder-file filename2] 43 | """ 44 | def main(args: Array[String]): Unit = { 45 | 46 | if (args.length == 0) println(usage) 47 | 48 | val arglist = args.toList 49 | val optionNames = arglist.filter(s => s.contains('-')) 50 | 51 | //type OptionMap = Map[Symbol, Any] 52 | 53 | val argmap = (0 until arglist.size / 2).map(i => arglist(i * 2) -> arglist(i * 2 + 1)).toMap 54 | 55 | val filename1 = argmap("--wallace-file") 56 | val filename2 = argmap("--prefix-adder-file") 57 | 58 | println(filename1) 59 | println(filename2) 60 | 61 | val filecontent = ReadWT.readFromWTTxt(filename1) 62 | 63 | val m = ReadWT.getBits(filecontent)(0) 64 | val n = ReadWT.getBits(filecontent)(1) 65 | 66 | val numcompressors = ReadWT.getNumCells(filecontent)(0) 67 | println("The compressors are: " + numcompressors) 68 | 69 | val myarchw = ReadWT.getArch(filecontent) 70 | println(myarchw) 71 | 72 | val depthw = ReadWT.getDepth(myarchw) 73 | println(depthw) 74 | 75 | val inedges = ReadWT.getIn(m, n, myarchw) 76 | println(inedges) 77 | 78 | val outedges = ReadWT.getOut(m, n, myarchw) 79 | println(outedges) 80 | 81 | val res = ReadWT.getRes(m, n, myarchw) 82 | println(res) 83 | 84 | val filecontent1 = ReadPPA.readFromPPATxt(filename2) 85 | 86 | val l = ReadPPA.getBits(filecontent1)(0) 87 | println("A " + n + "-bit parallel prefix adder") 88 | 89 | val numpgcells = ReadPPA.getNumCells(filecontent1)(0) 90 | println("The prefix nodes are: " + numpgcells) 91 | 92 | val myarcha = ReadPPA.getArch(filecontent1) 93 | println(myarcha) 94 | 95 | val deptha = ReadPPA.getDepth(myarcha) 96 | println("The depth of ppa is: " + deptha) 97 | 98 | val pedge = ReadPPA.genPEdge(l, deptha, myarcha) 99 | println(pedge) 100 | 101 | val gedge = ReadPPA.genGEdge(l, deptha, myarcha) 102 | println(gedge) 103 | 104 | val pos = ReadPPA.genFinal(l, myarcha) 105 | println(pos) 106 | 107 | val topDesign = () => new WTMultiplier(m, n, myarchw, inedges, outedges, res, myarcha, pedge, gedge, pos) 108 | chisel3.Driver.execute(Array("-td", "./RTL/mult"), topDesign) 109 | iotesters.Driver.execute(Array("-tgvo", "on", "-tbn", "verilator"), topDesign) { 110 | c => new WTMultiplierTester(c) 111 | } 112 | 113 | iotesters.Driver.execute(Array("-tgvo", "on", "-tbn", "verilator"), () => new WTMultiplier(m, n, myarchw, inedges, outedges, res, myarcha, pedge, gedge, pos)) { 114 | c => new WTMultiplierTester(c) 115 | } 116 | } 117 | } 118 | 119 | class WTMultiplierTester(c: WTMultiplier) extends PeekPokeTester(c) { 120 | poke(c.io.multiplicand, 15) 121 | poke(c.io.multiplier, 8) 122 | 123 | step(1) 124 | 125 | println("The result of 15 * 8 with is: " + peek(c.io.outs).toString()) 126 | 127 | expect(c.io.outs, 120) 128 | }*/ --------------------------------------------------------------------------------