Skip to content

Commit

Permalink
Wiring (#348)
Browse files Browse the repository at this point in the history
Added wiring pass and simple test
  • Loading branch information
azidar committed Oct 27, 2016
1 parent 1c61a0e commit 5b35f2d
Show file tree
Hide file tree
Showing 11 changed files with 922 additions and 21 deletions.
9 changes: 9 additions & 0 deletions in.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
pin:
name: mypin
source:
name: cmd
module: Htif
top:
name: Top
---
71 changes: 68 additions & 3 deletions src/main/scala/firrtl/Annotations.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package firrtl

import firrtl.ir._

import scala.collection.mutable
import java.io.Writer

Expand Down Expand Up @@ -38,16 +40,79 @@ import java.io.Writer
* ----------|----------|----------|------------|-----------|
*/
object Annotations {
/** Returns true if a valid Module name */
val SerializedModuleName = """([a-zA-Z_][a-zA-Z_0-9~!@#$%^*\-+=?/]*)""".r
def validModuleName(s: String): Boolean = s match {
case SerializedModuleName(name) => true
case _ => false
}

/** Returns true if a valid component/subcomponent name */
val SerializedComponentName = """([a-zA-Z_][a-zA-Z_0-9\[\]\.~!@#$%^*\-+=?/]*)""".r
def validComponentName(s: String): Boolean = s match {
case SerializedComponentName(name) => true
case _ => false
}

/** Tokenizes a string with '[', ']', '.' as tokens, e.g.:
* "foo.bar[boo.far]" becomes Seq("foo" "." "bar" "[" "boo" "." "far" "]")
*/
def tokenize(s: String): Seq[String] = s.find(c => "[].".contains(c)) match {
case Some(_) =>
val i = s.indexWhere(c => "[].".contains(c))
Seq(s.slice(0, i), s(i).toString) ++ tokenize(s.drop(i + 1))
case None => Seq(s)
}

/** Given a serialized component/subcomponent reference, subindex, subaccess,
* or subfield, return the corresponding IR expression.
*/
def toExp(s: String): Expression = {
def parse(tokens: Seq[String]): Expression = {
val DecPattern = """([1-9]\d*)""".r
def findClose(tokens: Seq[String], index: Int, nOpen: Int): Seq[String] =
if(index >= tokens.size) {
error("Cannot find closing bracket ]")
} else tokens(index) match {
case "[" => findClose(tokens, index + 1, nOpen + 1)
case "]" if nOpen == 1 => tokens.slice(1, index)
case _ => findClose(tokens, index + 1, nOpen)
}
def buildup(e: Expression, tokens: Seq[String]): Expression = tokens match {
case "[" :: tail =>
val indexOrAccess = findClose(tokens, 0, 0)
indexOrAccess.head match {
case DecPattern(d) => SubIndex(e, d.toInt, UnknownType)
case _ => buildup(SubAccess(e, parse(indexOrAccess), UnknownType), tokens.slice(1, indexOrAccess.size))
}
case "." :: tail =>
buildup(SubField(e, tokens(1), UnknownType), tokens.drop(2))
case Nil => e
}
val root = Reference(tokens.head, UnknownType)
buildup(root, tokens.tail)
}
if(validComponentName(s)) {
parse(tokenize(s))
} else error(s"Cannot convert $s into an expression.")
}

case class AnnotationException(message: String) extends Exception(message)

/**
* Named classes associate an annotation with a component in a Firrtl circuit
*/
trait Named { def name: String }
case class CircuitName(name: String) extends Named
case class ModuleName(name: String, circuit: CircuitName) extends Named
case class ComponentName(name: String, module: ModuleName) extends Named
case class CircuitName(name: String) extends Named {
if(!validModuleName(name)) throw AnnotationException(s"Illegal circuit name: $name")
}
case class ModuleName(name: String, circuit: CircuitName) extends Named {
if(!validModuleName(name)) throw AnnotationException(s"Illegal module name: $name")
}
case class ComponentName(name: String, module: ModuleName) extends Named {
if(!validComponentName(name)) throw AnnotationException(s"Illegal component name: $name")
def expr: Expression = toExp(name)
}

/**
* Transform ID (TransID) associates an annotation with an instantiated
Expand Down
2 changes: 2 additions & 0 deletions src/main/scala/firrtl/Utils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ import com.typesafe.scalalogging.LazyLogging
class FIRRTLException(str: String) extends Exception(str)

object Utils extends LazyLogging {
def throwInternalError =
error("Internal Error! Please file an issue at https://github.com/ucb-bar/firrtl/issues")
private[firrtl] def time[R](name: String)(block: => R): R = {
logger.info(s"Starting $name")
val t0 = System.nanoTime()
Expand Down
25 changes: 25 additions & 0 deletions src/main/scala/firrtl/passes/memlib/DecorateMems.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package firrtl
package passes
package memlib
import ir._
import Annotations._
import wiring._

class CreateMemoryAnnotations(reader: Option[YamlFileReader], replaceID: TransID, wiringID: TransID) extends Transform {
def name = "Create Memory Annotations"
def execute(c: Circuit, map: AnnotationMap): TransformResult = reader match {
case None => TransformResult(c)
case Some(r) =>
import CustomYAMLProtocol._
r.parse[Config] match {
case Seq(config) =>
val cN = CircuitName(c.main)
val top = TopAnnotation(ModuleName(config.top.name, cN), wiringID)
val source = SourceAnnotation(ComponentName(config.source.name, ModuleName(config.source.module, cN)), wiringID)
val pin = PinAnnotation(cN, replaceID, config.pin.name)
TransformResult(c, None, Some(AnnotationMap(Seq(top, source, pin))))
case Nil => TransformResult(c, None, None)
case _ => error("Can only have one config in yaml file")
}
}
}
27 changes: 24 additions & 3 deletions src/main/scala/firrtl/passes/memlib/ReplaceMemMacros.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,24 @@ import firrtl.Mappers._
import MemPortUtils.{MemPortMap, Modules}
import MemTransformUtils._
import AnalysisUtils._
import Annotations._
import wiring._


/** Annotates the name of the pin to add for WiringTransform
*/
case class PinAnnotation(target: CircuitName, tID: TransID, pin: String) extends Annotation with Loose with Unstable {
def duplicate(n: Named) = n match {
case n: CircuitName => this.copy(target = n)
case _ => throwInternalError
}
}

/** Replace DefAnnotatedMemory with memory blackbox + wrapper + conf file.
* This will not generate wmask ports if not needed.
* Creates the minimum # of black boxes needed by the design.
*/
class ReplaceMemMacros(writer: ConfWriter) extends Pass {
class ReplaceMemMacros(writer: ConfWriter, myID: TransID, wiringID: TransID) extends Transform {
def name = "Replace Memory Macros"

/** Return true if mask granularity is per bit, false if per byte or unspecified
Expand Down Expand Up @@ -194,14 +206,23 @@ class ReplaceMemMacros(writer: ConfWriter) extends Pass {
map updateStmtRefs(memPortMap))
}

def run(c: Circuit) = {
def execute(c: Circuit, map: AnnotationMap): TransformResult = {
val namespace = Namespace(c)
val memMods = new Modules
val nameMap = new NameMap
c.modules map (m => m map constructNameMap(namespace, nameMap, m.name))
val modules = c.modules map updateMemMods(namespace, nameMap, memMods)
// print conf
writer.serialize()
c copy (modules = modules ++ memMods)
val pin = map get myID match {
case Some(p) =>
p.values.head match {
case PinAnnotation(c, _, pin) => pin
case _ => error(s"Bad Annotations: ${p.values}")
}
case None => "pin"
}
val annos = memMods.collect { case m: ExtModule => SinkAnnotation(ModuleName(m.name, CircuitName(c.main)), wiringID, pin) }
TransformResult(c.copy(modules = modules ++ memMods), None, Some(AnnotationMap(annos)))
}
}
46 changes: 31 additions & 15 deletions src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Annotations._
import AnalysisUtils._
import Utils.error
import java.io.{File, CharArrayWriter, PrintWriter}
import wiring._

sealed trait PassOption
case object InputConfigFileName extends PassOption
Expand Down Expand Up @@ -92,21 +93,36 @@ Optional Arguments:
def duplicate(n: Named) = this copy (t = t.replace(s"-c:$passCircuit", s"-c:${n.name}"))
}

case class SimpleTransform(p: Pass) extends Transform {
def execute(c: Circuit, map: AnnotationMap): TransformResult =
TransformResult(p.run(c))
}
class ReplSeqMem(transID: TransID) extends Transform with SimpleRun {
def passSeq(inConfigFile: Option[YamlFileReader], outConfigFile: ConfWriter) =
Seq(Legalize,
ToMemIR,
ResolveMaskGranularity,
RenameAnnotatedMemoryPorts,
ResolveMemoryReference,
//new AnnotateValidMemConfigs(inConfigFile),
new ReplaceMemMacros(outConfigFile),
RemoveEmpty,
CheckInitialization,
InferTypes,
Uniquify,
ResolveKinds, // Must be run for the transform to work!
ResolveGenders)
def passSeq(inConfigFile: Option[YamlFileReader], outConfigFile: ConfWriter): Seq[Transform] =
Seq(SimpleTransform(Legalize),
SimpleTransform(ToMemIR),
SimpleTransform(ResolveMaskGranularity),
SimpleTransform(RenameAnnotatedMemoryPorts),
SimpleTransform(ResolveMemoryReference),
new CreateMemoryAnnotations(inConfigFile, TransID(-7), TransID(-8)),
new ReplaceMemMacros(outConfigFile, TransID(-7), TransID(-8)),
new WiringTransform(TransID(-8)),
SimpleTransform(RemoveEmpty),
SimpleTransform(CheckInitialization),
SimpleTransform(InferTypes),
SimpleTransform(Uniquify),
SimpleTransform(ResolveKinds),
SimpleTransform(ResolveGenders))
def run(circuit: Circuit, map: AnnotationMap, xForms: Seq[Transform]): TransformResult = {
(xForms.foldLeft(TransformResult(circuit, None, Some(map)))) { case (tr: TransformResult, xForm: Transform) =>
val x = xForm.execute(tr.circuit, tr.annotation.get)
x.annotation match {
case None => TransformResult(x.circuit, None, Some(map))
case Some(ann) => TransformResult(x.circuit, None, Some(
AnnotationMap(ann.annotations ++ tr.annotation.get.annotations)))
}
}
}

def execute(c: Circuit, map: AnnotationMap) = map get transID match {
case Some(p) => p get CircuitName(c.main) match {
Expand All @@ -118,7 +134,7 @@ class ReplSeqMem(transID: TransID) extends Transform with SimpleRun {
else error("Input configuration file does not exist!")
}
val outConfigFile = new ConfWriter(PassConfigUtil.getPassOptions(t)(OutputConfigFileName))
run(c, passSeq(inConfigFile, outConfigFile))
run(c, map, passSeq(inConfigFile, outConfigFile))
case _ => error("Unexpected transform annotation")
}
case _ => TransformResult(c)
Expand Down
10 changes: 10 additions & 0 deletions src/main/scala/firrtl/passes/memlib/YamlUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,18 @@ import java.io.{File, CharArrayWriter, PrintWriter}

object CustomYAMLProtocol extends DefaultYamlProtocol {
// bottom depends on top
implicit val _pin = yamlFormat1(Pin)
implicit val _source = yamlFormat2(Source)
implicit val _top = yamlFormat1(Top)
implicit val _configs = yamlFormat3(Config)
}

case class Pin(name: String)
case class Source(name: String, module: String)
case class Top(name: String)
case class Config(pin: Pin, source: Source, top: Top)


class YamlFileReader(file: String) {
import CustomYAMLProtocol._
def parse[A](implicit reader: YamlReader[A]) : Seq[A] = {
Expand Down

0 comments on commit 5b35f2d

Please sign in to comment.