/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package unittest

import chisel3._
import chisel3.util._
import chiseltest._
import chiseltest.iotesters._
import unittest.util._
import vta.core._
import vta.util.config._

class TensorGemmTester(c: TensorGemmSimple) extends PeekPokeTester(c) {
  poke(c.io.start, 0)
  poke(c.io.dec.reset, 0)
  poke(c.io.dec.uop_begin, 0)
  poke(c.io.dec.uop_end, 1)
  poke(c.io.dec.lp_0, 1)
  poke(c.io.dec.lp_1, 1)
  poke(c.io.dec.acc_0, 1)
  poke(c.io.dec.acc_1, 1)
  poke(c.io.dec.inp_0, 1)
  poke(c.io.dec.inp_1, 1)
  poke(c.io.dec.wgt_0, 1)
  poke(c.io.dec.wgt_1, 1)
  // Don't need empty_0, {push, pop}_{next, prev}, op

  poke(c.io.uop.data.bits.u0, 0)
  poke(c.io.uop.data.bits.u1, 0)
  poke(c.io.uop.data.bits.u2, 0)

  val inp = IndexedSeq.fill(c.io.inp.rd(0).data.bits(0).size){BigInt(1)}
  for {lhs <- c.io.inp.rd(0).data.bits} {
    poke(lhs, inp.reverse)
  }

  val wgt = IndexedSeq.fill(c.io.wgt.rd(0).data.bits(0).size){BigInt(1)}
  for {lhs <- c.io.wgt.rd(0).data.bits} {
    poke(lhs, wgt.reverse)
  }

  val acc = IndexedSeq.fill(c.io.acc.rd(0).data.bits(0).size){BigInt(1)}
  for {lhs <- c.io.acc.rd(0).data.bits} {
    poke(lhs, acc.reverse)
  }

  class TensorMasterMock(tm: TensorMaster) {
    poke(tm.rd(0).data.valid, 0)
    var valid = peek(tm.rd(0).idx.valid)

    def logical_step(v: BigInt) {
      poke(tm.rd(0).data.valid, valid)
      valid = peek(tm.rd(0).idx.valid)
      expect(tm.rd(0).idx.valid, v)
    }
  }

  class UopMasterMock(um: UopMaster) {
    poke(um.data.valid, 0)
    var valid = peek(um.idx.valid)

    def logical_step(v: BigInt) {
      poke(um.data.valid, valid)
      valid = peek(um.idx.valid)
      expect(um.idx.valid, v)
    }
  }

  class Mocks {
    val uop_mock = new UopMasterMock(c.io.uop)
    val inp_mock = new TensorMasterMock(c.io.inp)
    val wgt_mock = new TensorMasterMock(c.io.wgt)
    val acc_mock = new TensorMasterMock(c.io.acc)

    def logical_step(sram_valid: BigInt, uop_valid: BigInt) {
      step(1)
      uop_mock.logical_step(uop_valid)
      inp_mock.logical_step(sram_valid)
      wgt_mock.logical_step(sram_valid)
      acc_mock.logical_step(sram_valid)
    }
  }

  val mocks = new Mocks
  poke(c.io.start, 0)

  step(1)

  expect(c.io.state, c.sIdle)

  poke(c.io.start, 1)
  mocks.logical_step(0, 1)
  expect(c.io.state, c.sReadUop)

  expect(c.io.out.wr(0).valid, 0)
  expect(c.io.acc.wr(0).valid, 0)

  poke(c.io.start, 0)

  mocks.logical_step(0, 0)
  expect(c.io.state, c.sComputeIdx)
  expect(c.io.out.wr(0).valid, 0)
  expect(c.io.acc.wr(0).valid, 0)

  mocks.logical_step(1, 0)
  expect(c.io.state, c.sReadTensor)
  expect(c.io.out.wr(0).valid, 0)
  expect(c.io.acc.wr(0).valid, 0)

  mocks.logical_step(0, 0)
  expect(c.io.state, c.sExe)
  expect(c.io.out.wr(0).valid, 0)
  expect(c.io.acc.wr(0).valid, 0)
  expect(c.io.done, 0)

  mocks.logical_step(0, 0)
  expect(c.io.state, c.sWait)
  expect(c.io.inflight, 1)

  expect(c.io.out.wr(0).valid, 0)
  expect(c.io.acc.wr(0).valid, 0)

  mocks.logical_step(0, 0)
  expect(c.io.state, c.sWait)
  expect(c.io.inflight, 1)

  expect(c.io.out.wr(0).valid, 1)
  expect(c.io.acc.wr(0).valid, 1)

  mocks.logical_step(0, 0)
  expect(c.io.state, c.sWait)
  expect(c.io.inflight, 0)

  expect(c.io.out.wr(0).valid, 0)
  expect(c.io.acc.wr(0).valid, 0)

  mocks.logical_step(0, 0)
  expect(c.io.state, c.sIdle)
  expect(c.io.inflight, 0)

  expect(c.io.out.wr(0).valid, 0)
  expect(c.io.acc.wr(0).valid, 0)

}

class TensorGemmTest extends GenericTest("TensorGemm", (p:Parameters) => new TensorGemmSimple()(p),
  (c:TensorGemmSimple) => new TensorGemmTester(c))

class TensorGemmIdxTester(c: TensorGemmSimple) extends PeekPokeTester(c) {

  poke(c.io.start, 0)

  val uop_begin = 0
  val uop_end = 2
  assert(uop_begin < uop_end)
  val lp_0 = 2
  val lp_1 = 3
  val acc_0 = 1*lp_1
  val inp_0 = 2*lp_1
  val wgt_0 = 4*lp_1
  val acc_1 = 1
  val inp_1 = 2
  val wgt_1 = 4
  val u0 = BigInt("000", 16)
  val u1 = BigInt("100", 16)
  val u2 = BigInt("200", 16)

  poke(c.io.dec.reset, 0)
  poke(c.io.dec.uop_begin, uop_begin)
  poke(c.io.dec.uop_end, uop_end)
  poke(c.io.dec.lp_0, lp_0)
  poke(c.io.dec.lp_1, lp_1)
  poke(c.io.dec.acc_0, acc_0)
  poke(c.io.dec.acc_1, acc_1)
  poke(c.io.dec.inp_0, inp_0)
  poke(c.io.dec.inp_1, inp_1)
  poke(c.io.dec.wgt_0, wgt_0)
  poke(c.io.dec.wgt_1, wgt_1)
  // Don't need empty_0,{push,pop}_{next,prev},op

  poke(c.io.uop.data.bits.u0, u0)
  poke(c.io.uop.data.bits.u1, u1)
  poke(c.io.uop.data.bits.u2, u2)

  val inp = IndexedSeq.fill(c.io.inp.rd(0).data.bits(0).size){BigInt(1)}
  for {lhs <- c.io.inp.rd(0).data.bits} {
    poke(lhs, inp.reverse)
  }

  val wgt = IndexedSeq.fill(c.io.wgt.rd(0).data.bits(0).size){BigInt(1)}
  for {lhs <- c.io.wgt.rd(0).data.bits} {
    poke(lhs, wgt.reverse)
  }

  val acc = IndexedSeq.fill(c.io.acc.rd(0).data.bits(0).size){BigInt(1)}
  for {lhs <- c.io.acc.rd(0).data.bits} {
    poke(lhs, acc.reverse)
  }

  class TensorMasterMock(tm: TensorMaster) {
    poke(tm.rd(0).data.valid, 0)
    var valid = peek(tm.rd(0).idx.valid)
    def logical_step(v: BigInt) {
      poke(tm.rd(0).data.valid, valid)
      valid = peek(tm.rd(0).idx.valid)
      expect(tm.rd(0).idx.valid, v)
    }
  }

  class UopMasterMock(um: UopMaster) {
    poke(um.data.valid, 0)
    var valid = peek(um.idx.valid)
    def logical_step(v: BigInt) {
      poke(um.data.valid, valid)
      valid = peek(um.idx.valid)
      expect(um.idx.valid, v)
    }
  }

  class Mocks {
    val uop_mock = new UopMasterMock(c.io.uop)
    val inp_mock = new TensorMasterMock(c.io.inp)
    val wgt_mock = new TensorMasterMock(c.io.wgt)
    val acc_mock = new TensorMasterMock(c.io.acc)

    val uop_indices = new scala.collection.mutable.Queue[BigInt]
    val acc_indices = new scala.collection.mutable.Queue[BigInt]
    val inp_indices = new scala.collection.mutable.Queue[BigInt]
    val wgt_indices = new scala.collection.mutable.Queue[BigInt]
    val accout_indices = new scala.collection.mutable.Queue[BigInt]
    val out_indices = new scala.collection.mutable.Queue[BigInt]

    def logical_step(sram_valid: BigInt, uop_valid: BigInt) {
      step(1)
      uop_mock.logical_step(uop_valid)
      inp_mock.logical_step(sram_valid)
      wgt_mock.logical_step(sram_valid)
      acc_mock.logical_step(sram_valid)
      if (peek(c.io.uop.idx.valid) == 1) {
        expect(c.io.uop.idx.bits, uop_indices.dequeue())
      }
      if (peek(c.io.acc.rd(0).idx.valid) == 1) {
        expect(c.io.acc.rd(0).idx.bits, acc_indices.dequeue())
      }
      if (peek(c.io.inp.rd(0).idx.valid) == 1) {
        expect(c.io.inp.rd(0).idx.bits, inp_indices.dequeue())
      }
      if (peek(c.io.wgt.rd(0).idx.valid) == 1) {
        expect(c.io.wgt.rd(0).idx.bits, wgt_indices.dequeue())
      }
      if (peek(c.io.acc.wr(0).valid) == 1) {
        expect(c.io.acc.wr(0).bits.idx, accout_indices.dequeue())
      }
      if (peek(c.io.out.wr(0).valid) == 1) {
        expect(c.io.out.wr(0).bits.idx, out_indices.dequeue())
      }
    }

    def test_if_done() {
      assert(uop_indices.isEmpty)
      assert(acc_indices.isEmpty)
      assert(inp_indices.isEmpty)
      assert(wgt_indices.isEmpty)
    }
  }

  val mocks = new Mocks
  for {
    cnt_o <- 0 until lp_0
    cnt_i <- 0 until lp_1
    uop_idx <- uop_begin until uop_end
  } {
    mocks.uop_indices.enqueue(uop_idx)
    mocks.acc_indices.enqueue(u0 + acc_0*cnt_o + acc_1*cnt_i)
    mocks.inp_indices.enqueue(u1 + inp_0*cnt_o + inp_1*cnt_i)
    mocks.wgt_indices.enqueue(u2 + wgt_0*cnt_o + wgt_1*cnt_i)
    mocks.accout_indices.enqueue(u0 + acc_0*cnt_o + acc_1*cnt_i)
    mocks.out_indices.enqueue(u0 + acc_0*cnt_o + acc_1*cnt_i)
  }

  poke(c.io.start, 0)
  step(1)
  expect(c.io.state, c.sIdle)

  poke(c.io.start, 1)

  for {q <- 0 until (uop_end-uop_begin)*lp_0*lp_1} {
    mocks.logical_step(0, 1)
    expect(c.io.out.wr(0).valid, 0)
    expect(c.io.acc.wr(0).valid, 0)

    poke(c.io.start, 0)

    mocks.logical_step(0, 0)
    expect(c.io.out.wr(0).valid, if (q > 0) 1 else 0)
    expect(c.io.acc.wr(0).valid, if (q > 0) 1 else 0)

    mocks.logical_step(1, 0)
    expect(c.io.out.wr(0).valid, 0)
    expect(c.io.acc.wr(0).valid, 0)

    mocks.logical_step(0, 0)
    expect(c.io.out.wr(0).valid, 0)
    expect(c.io.acc.wr(0).valid, 0)
    expect(c.io.done, 0)
  }

  mocks.logical_step(0, 0)
  expect(c.io.inflight, 1)

  expect(c.io.out.wr(0).valid, 0)
  expect(c.io.acc.wr(0).valid, 0)

  mocks.logical_step(0, 0)
  expect(c.io.inflight, 1)

  expect(c.io.out.wr(0).valid, 1)
  expect(c.io.acc.wr(0).valid, 1)

  mocks.logical_step(0, 0)
  expect(c.io.inflight, 0)

  expect(c.io.out.wr(0).valid, 0)
  expect(c.io.acc.wr(0).valid, 0)

  mocks.logical_step(0, 0)
  expect(c.io.inflight, 0)

  expect(c.io.out.wr(0).valid, 0)
  expect(c.io.acc.wr(0).valid, 0)

  mocks.test_if_done()
}

class TensorGemmIdxTest extends GenericTest("TensorGemmIdx", (p:Parameters) => new TensorGemmSimple()(p),
  (c:TensorGemmSimple) => new TensorGemmIdxTester(c))

class TensorGemmIndexGeneratorTester(c: TensorGemmIndexGenerator) extends PeekPokeTester(c) {
  val uop_begin = 0
  val uop_end = 2
  assert(uop_begin < uop_end)
  val lp_0 = 2
  val lp_1 = 3
  val acc_0 = 1*lp_1
  val inp_0 = 2*lp_1
  val wgt_0 = 4*lp_1
  val acc_1 = 1
  val inp_1 = 2
  val wgt_1 = 4

  poke(c.io.dec.reset, 0)
  poke(c.io.dec.uop_begin, uop_begin)
  poke(c.io.dec.uop_end, uop_end)
  poke(c.io.dec.lp_0, lp_0)
  poke(c.io.dec.lp_1, lp_1)
  poke(c.io.dec.acc_0, acc_0)
  poke(c.io.dec.acc_1, acc_1)
  poke(c.io.dec.inp_0, inp_0)
  poke(c.io.dec.inp_1, inp_1)
  poke(c.io.dec.wgt_0, wgt_0)
  poke(c.io.dec.wgt_1, wgt_1)
  // Don't need empty_0,{push,pop}_{next,prev},op

  class Mocks {
    val uop_indices = new scala.collection.mutable.Queue[BigInt]
    val acc_indices = new scala.collection.mutable.Queue[BigInt]
    val inp_indices = new scala.collection.mutable.Queue[BigInt]
    val wgt_indices = new scala.collection.mutable.Queue[BigInt]

    def logical_step() {
      step(1)
      if (peek(c.io.valid) == 1) {
        expect(c.io.uop_idx, uop_indices.dequeue())
        expect(c.io.acc_i, acc_indices.dequeue())
        expect(c.io.inp_i, inp_indices.dequeue())
        expect(c.io.wgt_i, wgt_indices.dequeue())
      }
    }

    def test_if_done() {
      println(s"uop_indices remaining: ${uop_indices.size}")
      println(s"acc_indices remaining: ${acc_indices.size}")
      println(s"inp_indices remaining: ${inp_indices.size}")
      println(s"wgt_indices remaining: ${wgt_indices.size}")
      assert(uop_indices.isEmpty)
      assert(acc_indices.isEmpty)
      assert(inp_indices.isEmpty)
      assert(wgt_indices.isEmpty)
    }
  }

  val mocks = new Mocks
  for {
    cnt_o <- 0 until lp_0
    cnt_i <- 0 until lp_1
    uop_idx <- uop_begin until uop_end
  } {
    mocks.uop_indices.enqueue(uop_idx)
    mocks.acc_indices.enqueue(acc_0*cnt_o + acc_1*cnt_i)
    mocks.inp_indices.enqueue(inp_0*cnt_o + inp_1*cnt_i)
    mocks.wgt_indices.enqueue(wgt_0*cnt_o + wgt_1*cnt_i)
  }

  poke(c.io.start, 1)
  mocks.logical_step()
  poke(c.io.start, 0)

  val end = (uop_end-uop_begin)*lp_0*lp_1
  var count = 0
  while(peek(c.io.last) == 0 && count < 10*end + 100) {
    mocks.logical_step()
    count += 1
  }
  mocks.test_if_done()
}

class TensorGemmIndexGeneratorTest extends GenericTest("TensorGemmIndexGenerator",
  (p:Parameters) => new TensorGemmIndexGenerator()(p),
  (c:TensorGemmIndexGenerator) => new TensorGemmIndexGeneratorTester(c))

class TensorGemmPipelinedTester(c: TensorGemmPipelinedSplit) extends PeekPokeTester(c) {
  poke(c.io.start, 0)

  val uop_begin = 0
  val uop_end = 2
  assert(uop_begin < uop_end)
  val lp_0 = 2
  val lp_1 = 3
  val acc_0 = 1*lp_1
  val inp_0 = 2*lp_1
  val wgt_0 = 4*lp_1
  val acc_1 = 1
  val inp_1 = 2
  val wgt_1 = 4
  val u0 = BigInt("000", 16)
  val u1 = BigInt("100", 16)
  val u2 = BigInt("200", 16)

  poke(c.io.dec.reset, 0)
  poke(c.io.dec.uop_begin, uop_begin)
  poke(c.io.dec.uop_end, uop_end)
  poke(c.io.dec.lp_0, lp_0)
  poke(c.io.dec.lp_1, lp_1)
  poke(c.io.dec.acc_0, acc_0)
  poke(c.io.dec.acc_1, acc_1)
  poke(c.io.dec.inp_0, inp_0)
  poke(c.io.dec.inp_1, inp_1)
  poke(c.io.dec.wgt_0, wgt_0)
  poke(c.io.dec.wgt_1, wgt_1)
  // Don't need empty_0,{push,pop}_{next,prev},op

  poke(c.io.uop.data.bits.u0, u0)
  poke(c.io.uop.data.bits.u1, u1)
  poke(c.io.uop.data.bits.u2, u2)

  val inp = IndexedSeq.fill(c.io.inp.rd(0).data.bits(0).size){BigInt(1)}
  for {lhs <- c.io.inp.rd(0).data.bits} {
    poke(lhs, inp.reverse)
  }

  val wgt = IndexedSeq.fill(c.io.wgt.rd(0).data.bits(0).size){BigInt(1)}
  for {lhs <- c.io.wgt.rd(0).data.bits} {
    poke(lhs, wgt.reverse)
  }

  val acc = IndexedSeq.fill(c.io.acc.rd(0).data.bits(0).size){BigInt(1)}
  for {lhs <- c.io.acc.rd(0).data.bits} {
    poke(lhs, acc.reverse)
  }

  class TensorMasterMock(tm: TensorMaster) {
    poke(tm.rd(0).data.valid, 0)
    var valid = peek(tm.rd(0).idx.valid)
    def logical_step(v: Option[BigInt]) {
      poke(tm.rd(0).data.valid, valid)
      valid = peek(tm.rd(0).idx.valid)
      for {x <- v} expect(tm.rd(0).idx.valid, x)
    }
  }

  class UopMasterMock(um: UopMaster) {
    poke(um.data.valid, 0)
    var valid = peek(um.idx.valid)
    def logical_step(v: Option[BigInt]) {
      poke(um.data.valid, valid)
      valid = peek(um.idx.valid)
      for {x <- v} expect(um.idx.valid, x)
    }
  }

  class Mocks {
    val uop_mock = new UopMasterMock(c.io.uop)
    val inp_mock = new TensorMasterMock(c.io.inp)
    val wgt_mock = new TensorMasterMock(c.io.wgt)
    val acc_mock = new TensorMasterMock(c.io.acc)

    val uop_indices = new scala.collection.mutable.Queue[BigInt]
    val acc_indices = new scala.collection.mutable.Queue[BigInt]
    val inp_indices = new scala.collection.mutable.Queue[BigInt]
    val wgt_indices = new scala.collection.mutable.Queue[BigInt]
    val accout_indices = new scala.collection.mutable.Queue[BigInt]
    val out_indices = new scala.collection.mutable.Queue[BigInt]

    def logical_step() {
      step(1)
      uop_mock.logical_step(None)
      inp_mock.logical_step(None)
      wgt_mock.logical_step(None)
      acc_mock.logical_step(None)
      if (peek(c.io.uop.idx.valid) == 1) {
        expect(c.io.uop.idx.bits, uop_indices.dequeue())
      }
      if (peek(c.io.acc.rd(0).idx.valid) == 1) {
        expect(c.io.acc.rd(0).idx.bits, acc_indices.dequeue())
      }
      if (peek(c.io.inp.rd(0).idx.valid) == 1) {
        expect(c.io.inp.rd(0).idx.bits, inp_indices.dequeue())
      }
      if (peek(c.io.wgt.rd(0).idx.valid) == 1) {
        expect(c.io.wgt.rd(0).idx.bits, wgt_indices.dequeue())
      }
      if (peek(c.io.acc.wr(0).valid) == 1) {
        expect(c.io.acc.wr(0).bits.idx, accout_indices.dequeue())
      }
      if (peek(c.io.out.wr(0).valid) == 1) {
        expect(c.io.out.wr(0).bits.idx, out_indices.dequeue())
      }
    }

    def test_if_done() {
      println(s"uop_indices remaining: ${uop_indices.size}")
      println(s"acc_indices remaining: ${acc_indices.size}")
      println(s"inp_indices remaining: ${inp_indices.size}")
      println(s"wgt_indices remaining: ${wgt_indices.size}")
      println(s"accout_indices remaining: ${accout_indices.size}")
      println(s"out_indices remaining: ${out_indices.size}")
    }
  }

  val mocks = new Mocks
  for {
    cnt_o <- 0 until lp_0
    cnt_i <- 0 until lp_1
    uop_idx <- uop_begin until uop_end
  } {
    mocks.uop_indices.enqueue(uop_idx)
    mocks.acc_indices.enqueue(u0 + acc_0*cnt_o + acc_1*cnt_i)
    mocks.inp_indices.enqueue(u1 + inp_0*cnt_o + inp_1*cnt_i)
    mocks.wgt_indices.enqueue(u2 + wgt_0*cnt_o + wgt_1*cnt_i)
    mocks.accout_indices.enqueue(u0 + acc_0*cnt_o + acc_1*cnt_i)
    mocks.out_indices.enqueue(u0 + acc_0*cnt_o + acc_1*cnt_i)
  }

  poke(c.io.start, 0)
  step(1)
  expect(c.io.state, c.sIdle)
  poke(c.io.start, 1)

  var count = 0
  val end = (uop_end-uop_begin)*lp_0*lp_1

  while (peek(c.io.done) == 0 && count < 10*end + 100) {
    mocks.logical_step()
    poke(c.io.start, 0)
  }

  expect(c.io.done, 1)
  mocks.test_if_done()
}

class TensorGemmPipelinedTest extends GenericTest("TensorGemmPipelined",
  (p:Parameters) => new TensorGemmPipelinedSplit()(p),
  (c:TensorGemmPipelinedSplit) => new TensorGemmPipelinedTester(c))

class TensorGemmResetTester(c: TensorGemm) extends PeekPokeTester(c) {
  poke(c.io.start, 0)

  val uop_begin = 0
  val uop_end = 2
  assert(uop_begin < uop_end)
  val lp_0 = 2
  val lp_1 = 3
  val acc_0 = 1*lp_1
  val inp_0 = 2*lp_1
  val wgt_0 = 4*lp_1
  val acc_1 = 1
  val inp_1 = 2
  val wgt_1 = 4
  val u0 = BigInt("000", 16)
  val u1 = BigInt("100", 16)
  val u2 = BigInt("200", 16)
  val dec_reset = 1

  poke(c.io.dec.reset, dec_reset)
  poke(c.io.dec.uop_begin, uop_begin)
  poke(c.io.dec.uop_end, uop_end)
  poke(c.io.dec.lp_0, lp_0)
  poke(c.io.dec.lp_1, lp_1)
  poke(c.io.dec.acc_0, acc_0)
  poke(c.io.dec.acc_1, acc_1)
  poke(c.io.dec.inp_0, inp_0)
  poke(c.io.dec.inp_1, inp_1)
  poke(c.io.dec.wgt_0, wgt_0)
  poke(c.io.dec.wgt_1, wgt_1)
  // Don't need empty_0,{push,pop}_{next,prev},op

  poke(c.io.uop.data.bits.u0, u0)
  poke(c.io.uop.data.bits.u1, u1)
  poke(c.io.uop.data.bits.u2, u2)

  val inp = IndexedSeq.fill(c.io.inp.rd(0).data.bits(0).size){BigInt(1)}
  for {lhs <- c.io.inp.rd(0).data.bits} {
    poke(lhs, inp.reverse)
  }

  val wgt = IndexedSeq.fill(c.io.wgt.rd(0).data.bits(0).size){BigInt(1)}
  for {lhs <- c.io.wgt.rd(0).data.bits} {
    poke(lhs, wgt.reverse)
  }

  val acc = IndexedSeq.fill(c.io.acc.rd(0).data.bits(0).size){BigInt(1)}
  for {lhs <- c.io.acc.rd(0).data.bits} {
    poke(lhs, acc.reverse)
  }

  class TensorMasterMock(tm: TensorMaster) {
    poke(tm.rd(0).data.valid, 0)
    var valid = peek(tm.rd(0).idx.valid)
    def logical_step(v: Option[BigInt]) {
      poke(tm.rd(0).data.valid, valid)
      valid = peek(tm.rd(0).idx.valid)
      for {x <- v} expect(tm.rd(0).idx.valid, x)
    }
  }

  class UopMasterMock(um: UopMaster) {
    poke(um.data.valid, 0)
    var valid = peek(um.idx.valid)
    def logical_step(v: Option[BigInt]) {
      poke(um.data.valid, valid)
      valid = peek(um.idx.valid)
      for {x <- v} expect(um.idx.valid, x)
    }
  }

  class Mocks {
    val uop_mock = new UopMasterMock(c.io.uop)
    val inp_mock = new TensorMasterMock(c.io.inp)
    val wgt_mock = new TensorMasterMock(c.io.wgt)
    val acc_mock = new TensorMasterMock(c.io.acc)

    val uop_indices = new scala.collection.mutable.Queue[BigInt]
    val acc_indices = new scala.collection.mutable.Queue[BigInt]
    val inp_indices = new scala.collection.mutable.Queue[BigInt]
    val wgt_indices = new scala.collection.mutable.Queue[BigInt]
    val accout_indices = new scala.collection.mutable.Queue[BigInt]
    val out_indices = new scala.collection.mutable.Queue[BigInt]

    def logical_step(sram_valid: BigInt, uop_valid: BigInt) {
      step(1)
      uop_mock.logical_step(None)
      inp_mock.logical_step(None)
      wgt_mock.logical_step(None)
      acc_mock.logical_step(None)
      if (peek(c.io.uop.idx.valid) == 1) {
        expect(c.io.uop.idx.bits, uop_indices.dequeue())
      }
      if (peek(c.io.acc.rd(0).idx.valid) == 1) {
        expect(c.io.acc.rd(0).idx.bits, acc_indices.dequeue())
      }
      if (peek(c.io.inp.rd(0).idx.valid) == 1) {
        expect(c.io.inp.rd(0).idx.bits, inp_indices.dequeue())
      }
      if (peek(c.io.wgt.rd(0).idx.valid) == 1) {
        expect(c.io.wgt.rd(0).idx.bits, wgt_indices.dequeue())
      }
      if (peek(c.io.acc.wr(0).valid) == 1) {
        expect(c.io.acc.wr(0).bits.idx, accout_indices.dequeue())
      }
      if (peek(c.io.out.wr(0).valid) == 1) {
        expect(c.io.out.wr(0).bits.idx, out_indices.dequeue())
      }
    }

    def test_if_done() {
      assert(uop_indices.isEmpty)
      assert(acc_indices.isEmpty)
      assert(inp_indices.isEmpty)
      assert(wgt_indices.isEmpty)
      assert(accout_indices.isEmpty)
      assert(out_indices.isEmpty)
    }
  }

  val mocks = new Mocks
  for {
    cnt_o <- 0 until lp_0
    cnt_i <- 0 until lp_1
    uop_idx <- uop_begin until uop_end
  } {
    mocks.uop_indices.enqueue(uop_idx)
    mocks.acc_indices.enqueue(u0 + acc_0*cnt_o + acc_1*cnt_i)
    mocks.inp_indices.enqueue(u1 + inp_0*cnt_o + inp_1*cnt_i)
    mocks.wgt_indices.enqueue(u2 + wgt_0*cnt_o + wgt_1*cnt_i)
    mocks.accout_indices.enqueue(u0 + acc_0*cnt_o + acc_1*cnt_i)

    if (dec_reset == 0) {
      mocks.out_indices.enqueue(u0 + acc_0*cnt_o + acc_1*cnt_i)
    }
  }

  poke(c.io.start, 0)
  step(1)
  expect(c.io.state, c.sIdle)
  poke(c.io.start, 1)

  while(peek(c.io.done) == 0) {
    mocks.logical_step(0, 0)
    poke(c.io.start, 0)
  }

  mocks.test_if_done()
}

class TensorGemmResetTest extends GenericTest("TensorGemmReset", (p:Parameters) => new TensorGemm()(p),
  (c:TensorGemm) => new TensorGemmResetTester(c))
