Skip to content

Commit

Permalink
Andr, Orr, and Xorr were broken because mask applied to their input (#79
Browse files Browse the repository at this point in the history
)

was based on output width of operation instead of input width. This
fixes that problem and adds a test for this error
Fixes Issue #78
  • Loading branch information
chick committed Jan 17, 2019
1 parent a10de08 commit a86c69d
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 10 deletions.
20 changes: 11 additions & 9 deletions src/main/scala/treadle/executable/ExpressionCompiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,8 @@ class ExpressionCompiler(
case ClockType => 1
}

val sourceWidth = getWidth(expressions.head)

arg1 match {
case e1: IntExpressionResult =>
op match {
Expand All @@ -475,9 +477,9 @@ class ExpressionCompiler(
case Neg => NegInts(e1.apply)
case Not => NotInts(e1.apply, width)

case Andr => AndrInts(e1.apply, width)
case Orr => OrrInts(e1.apply, width)
case Xorr => XorrInts(e1.apply, width)
case Andr => AndrInts(e1.apply, sourceWidth)
case Orr => OrrInts(e1.apply, sourceWidth)
case Xorr => XorrInts(e1.apply, sourceWidth)
}
case e1: LongExpressionResult =>
op match {
Expand All @@ -490,9 +492,9 @@ class ExpressionCompiler(
case Neg => NegLongs(e1.apply)
case Not => NotLongs(e1.apply, width)

case Andr => AndrLongs(e1.apply, width)
case Orr => OrrLongs(e1.apply, width)
case Xorr => XorrLongs(e1.apply, width)
case Andr => AndrLongs(e1.apply, sourceWidth)
case Orr => OrrLongs(e1.apply, sourceWidth)
case Xorr => XorrLongs(e1.apply, sourceWidth)
}
case e1: BigExpressionResult =>
op match {
Expand All @@ -505,9 +507,9 @@ class ExpressionCompiler(
case Neg => NegBigs(e1.apply)
case Not => NotBigs(e1.apply, width)

case Andr => AndrBigs(e1.apply, width)
case Orr => OrrBigs(e1.apply, width)
case Xorr => XorrBigs(e1.apply, width)
case Andr => AndrBigs(e1.apply, sourceWidth)
case Orr => OrrBigs(e1.apply, sourceWidth)
case Xorr => XorrBigs(e1.apply, sourceWidth)
}
}
}
Expand Down
70 changes: 69 additions & 1 deletion src/test/scala/treadle/primops/AndrOrrXorr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
package treadle.primops

import treadle.executable._
import treadle.{BigIntTestValuesGenerator, BitTwiddlingUtils, extremaOfUIntOfWidth, extremaOfSIntOfWidth}
import treadle._
import org.scalatest.{FreeSpec, Matchers}


Expand Down Expand Up @@ -114,6 +114,74 @@ class AndrOrrXorr extends FreeSpec with Matchers {
}
}

"Andr, Orr, Xorr reduction should work with vec converted to uint" in {
val input =
"""
|circuit XorReduce :
| module XorReduce :
| input clock : Clock
| input reset : UInt<1>
| input io_in1_0 : UInt<1>
| input io_in1_1 : UInt<1>
| input io_in1_2 : UInt<1>
| input io_in1_3 : UInt<1>
| output io_out_andr : UInt<1>
| output io_out_orr : UInt<1>
| output io_out_xorr : UInt<1>
|
| node _T = cat(io_in1_1, io_in1_0) @[XorReducer.scala 15:21]
| node _T_1 = cat(io_in1_3, io_in1_2) @[XorReducer.scala 15:21]
| node _T_2 = cat(_T_1, _T) @[XorReducer.scala 15:21]
| node _T_3 = andr(_T_2) @[XorReducer.scala 15:28]
| node _T_4 = orr(_T_2) @[XorReducer.scala 15:28]
| node _T_5 = xorr(_T_2) @[XorReducer.scala 15:28]
| io_out_andr <= _T_3 @[XorReducer.scala 15:11]
| io_out_orr <= _T_4 @[XorReducer.scala 15:11]
| io_out_xorr <= _T_5 @[XorReducer.scala 15:11]
""".stripMargin

val manager = new TreadleOptionsManager {
treadleOptions = treadleOptions.copy(
showFirrtlAtLoad = false,
setVerbose = false,
rollbackBuffers = 0
)
}

def scalaXorReduce(x: BigInt, width: Int): Int = {
if(x.bitCount % 2 == 0) 0 else 1
}

def scalaAndReduce(x: BigInt, width: Int): Int = {
if((0 until width).forall(i => x.testBit(i))) 1 else 0
}

def scalaOrReduce(x: BigInt, width: Int): Int = {
if((0 until width).exists(i => x.testBit(i))) 1 else 0
}

val t = new TreadleTester(input, manager)
for {
i0 <- 0 to 1
i1 <- 0 to 1
i2 <- 0 to 1
i3 <- 0 to 1
} {
t.poke(s"io_in1_0", i0)
t.poke(s"io_in1_1", i1)
t.poke(s"io_in1_2", i2)
t.poke(s"io_in1_3", i3)

t.expect("io_out_andr", scalaAndReduce(i0 + (i1 << 1) + (i2 << 2) + (i3 << 3), 4))
t.expect("io_out_orr", scalaOrReduce(i0 + (i1 << 1) + (i2 << 2) + (i3 << 3), 4))
t.expect("io_out_xorr", scalaXorReduce(i0 + (i1 << 1) + (i2 << 2) + (i3 << 3), 4))

// println(s"got $i0$i1$i2$i3 " + t.peek("io_out_andr") + " " +
// t.peek("io_out_orr") + " " + t.peek("io_out_xorr"))
}
t.report()
}

"Reductions should pass for different bit widths when using SInt" in {
for (size <- BigIntTestValuesGenerator((1, DataSize.LongThreshold * Big(2)))) {
val bitWidth = size.toInt
Expand Down

0 comments on commit a86c69d

Please sign in to comment.