// See LICENSE for license details.

package firrtlTests

import firrtl._
import firrtl.testutils._
import firrtl.testutils.FirrtlCheckers._

class ReplaceTruncatingArithmeticSpec extends FirrtlFlatSpec {
  def compile(input: String): CircuitState =
    (new VerilogCompiler).compileAndEmit(CircuitState(parse(input), ChirrtlForm), List.empty)
  def compileBody(body: String) = {
    val str = """
                |circuit Test :
                |  module Test :
                |""".stripMargin + body.split("\n").mkString("    ", "\n    ", "")
    compile(str)
  }

  "Truncting addition" should "be inferred and emitted in Verilog" in {
    val result = compileBody(s"""
                                |input x : UInt<8>
                                |input y : UInt<8>
                                |output z : UInt<8>
                                |z <= tail(add(x, y), 1)""".stripMargin)
    result should containLine(s"assign z = x + y;")
  }
  it should "be inferred and emitted in Verilog even with an intermediate node" in {
    val result = compileBody(s"""
                                |input x : UInt<8>
                                |input y : UInt<8>
                                |output z : UInt<8>
                                |node n = add(x, y)
                                |z <= tail(n, 1)""".stripMargin)
    result should containLine(s"assign z = x + y;")
  }
  "Truncting subtraction" should "be inferred and emitted in Verilog" in {
    val result = compileBody(s"""
                                |input x : UInt<8>
                                |input y : UInt<8>
                                |output z : UInt<8>
                                |z <= tail(sub(x, y), 1)""".stripMargin)
    result should containLine(s"assign z = x - y;")
  }
  "Tailing more than 1" should "not result in a truncating operator" in {
    val result = compileBody(s"""
                                |input x : UInt<8>
                                |input y : UInt<8>
                                |output z : UInt<7>
                                |node n = sub(x, y)
                                |z <= tail(n, 2)""".stripMargin)
    result should containLine(s"wire [8:0] n = x - y;")
    result should containLine(s"assign z = n[6:0];")
  }

}
