From 522b32e04e35b0fd16bcd9b3a043d271016d4d0a Mon Sep 17 00:00:00 2001
From: Minyong Li <ml10g20@soton.ac.uk>
Date: Mon, 23 Aug 2021 22:28:12 +0100
Subject: [PATCH] core.BaseRound: fix reversed casts

Chisel UInt conversion from/to aggregates involves reversal. This
causes problem for the Quarter Rounds, since they receive wrong
bits, leading to completely different results (which are wrong).
---
 .../scala/uk/ac/soton/ecs/can/core/Adder.scala    |  2 ++
 .../uk/ac/soton/ecs/can/core/BaseRound.scala      | 15 +++++++++++++--
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/main/scala/uk/ac/soton/ecs/can/core/Adder.scala b/src/main/scala/uk/ac/soton/ecs/can/core/Adder.scala
index 9d5c083..581e558 100644
--- a/src/main/scala/uk/ac/soton/ecs/can/core/Adder.scala
+++ b/src/main/scala/uk/ac/soton/ecs/can/core/Adder.scala
@@ -10,6 +10,8 @@ class Adder extends MultiIOModule {
   val rhs = IO(Input(UInt(512.W)))
   val out = IO(Output(UInt(512.W)))
 
+  // NOTE: Unlike what's done in `BaseRound`, here no reversal is applied, since
+  // the additions are done on the basis of words and do not spread bits.
   private val _lhs = lhs.asTypeOf(Vec(16, UInt(32.W)))
   private val _rhs = rhs.asTypeOf(Vec(16, UInt(32.W)))
   private val _out = Wire(Vec(16, UInt(32.W)))
diff --git a/src/main/scala/uk/ac/soton/ecs/can/core/BaseRound.scala b/src/main/scala/uk/ac/soton/ecs/can/core/BaseRound.scala
index f92a53a..66523ee 100644
--- a/src/main/scala/uk/ac/soton/ecs/can/core/BaseRound.scala
+++ b/src/main/scala/uk/ac/soton/ecs/can/core/BaseRound.scala
@@ -4,6 +4,7 @@
 package uk.ac.soton.ecs.can.core
 
 import chisel3._
+import chisel3.util.Cat
 import uk.ac.soton.ecs.can.config.CanCoreConfiguration
 
 abstract class BaseRound(implicit cfg: CanCoreConfiguration)
@@ -11,9 +12,19 @@ abstract class BaseRound(implicit cfg: CanCoreConfiguration)
   val in = IO(Input(UInt(512.W)))
   val out = IO(Output(UInt(512.W)))
 
-  protected val _in = in.asTypeOf(Vec(16, UInt(32.W)))
+  // NOTE: A conversion between an UInt and an aggregate type reverses the
+  // sequence of elements. The `_in` cast below reverses such reversal by
+  // manually creating a `Vec` with the elements in the casted `Vec` reversed.
+  // Same for the `out` connection, where `Cat`, which concatenates elements
+  // from the most significant element to the least significant element, is used
+  // instead of `_out.asUInt()`, which puts the first element in the `Vec` to
+  // the least significant position of `UInt`.
+  //
+  // See also:
+  // - https://github.com/chipsalliance/chisel3/blob/master/core/src/main/scala/chisel3/Data.scala#L695-L696
+  protected val _in = VecInit(in.asTypeOf(Vec(16, UInt(32.W))).reverse)
   protected val _out = Wire(Vec(16, UInt(32.W)))
-  out := _out.asUInt()
+  out := Cat(_out)
 
   protected def wire(wireBox: Seq[Seq[Int]]): Unit = wireBox.foreach {
     wireSeq =>
-- 
GitLab