aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/passes/memlib/RenameAnnotatedMemoryPorts.scala
blob: 168a6a4866937bb65b7bd5efdca0f4accf2a704d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// See LICENSE for license details.

package firrtl.passes
package memlib

import firrtl._
import firrtl.ir._
import firrtl.Utils._
import firrtl.Mappers._
import AnalysisUtils._
import MemPortUtils._
import MemTransformUtils._


/** Changes memory port names to standard port names (i.e. RW0 instead T_408)
 */
object RenameAnnotatedMemoryPorts extends Pass {

  def name = "Rename Annotated Memory Ports"

  /** Renames memory ports to a standard naming scheme:
   *    - R0, R1, ... for each read port
   *    - W0, W1, ... for each write port
   *    - RW0, RW1, ... for each readwrite port
   */
  def createMemProto(m: DefAnnotatedMemory): DefAnnotatedMemory = {
    val rports = m.readers.indices map (i => s"R$i")
    val wports = m.writers.indices map (i => s"W$i")
    val rwports = m.readwriters.indices map (i => s"RW$i")
    m copy (readers = rports, writers = wports, readwriters = rwports)
  }

  /** Maps the serialized form of all memory port field names to the
   *    corresponding new memory port field Expression.
   *  E.g.:
   *    - ("m.read.addr") becomes (m.R0.addr)
   */
  def getMemPortMap(m: DefAnnotatedMemory): MemPortMap = {
    val memPortMap = new MemPortMap
    val defaultFields = Seq("addr", "en", "clk")
    val rFields = defaultFields :+ "data"
    val wFields = rFields :+ "mask"
    val rwFields = defaultFields ++ Seq("wmode", "wdata", "rdata", "wmask")

    def updateMemPortMap(ports: Seq[String], fields: Seq[String], newPortKind: String): Unit =
      for ((p, i) <- ports.zipWithIndex; f <- fields) {
        val newPort = createSubField(createRef(m.name), newPortKind + i)
        val field = createSubField(newPort, f)
        memPortMap(s"${m.name}.$p.$f") = field
      }
    updateMemPortMap(m.readers, rFields, "R")
    updateMemPortMap(m.writers, wFields, "W")
    updateMemPortMap(m.readwriters, rwFields, "RW")
    memPortMap
  }

  /** Replaces candidate memories with memories with standard port names
    * Does not update the references (this is done via updateStmtRefs)
    */
  def updateMemStmts(memPortMap: MemPortMap)(s: Statement): Statement = s match {
    case m: DefAnnotatedMemory =>
      val updatedMem = createMemProto(m)
      memPortMap ++= getMemPortMap(m)
      updatedMem
    case s => s map updateMemStmts(memPortMap)
  }

  /** Replaces candidate memories and their references with standard port names
   */
  def updateMemMods(m: DefModule) = {
    val memPortMap = new MemPortMap
    (m map updateMemStmts(memPortMap)
       map updateStmtRefs(memPortMap))
  }

  def run(c: Circuit) = c copy (modules = c.modules map updateMemMods)
}