diff options
Diffstat (limited to 'src/main/scala/firrtl/passes/Resolves.scala')
| -rw-r--r-- | src/main/scala/firrtl/passes/Resolves.scala | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/main/scala/firrtl/passes/Resolves.scala b/src/main/scala/firrtl/passes/Resolves.scala new file mode 100644 index 00000000..3100f0c3 --- /dev/null +++ b/src/main/scala/firrtl/passes/Resolves.scala @@ -0,0 +1,163 @@ +/* +Copyright (c) 2014 - 2016 The Regents of the University of +California (Regents). All Rights Reserved. Redistribution and use in +source and binary forms, with or without modification, are permitted +provided that the following conditions are met: + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, +ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF +REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF +ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION +TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. +*/ + +package firrtl.passes + +import firrtl._ +import firrtl.ir._ +import firrtl.Mappers._ + +object ResolveKinds extends Pass { + def name = "Resolve Kinds" + type KindMap = collection.mutable.LinkedHashMap[String, Kind] + + def find_port(kinds: KindMap)(p: Port): Port = { + kinds(p.name) = PortKind() ; p + } + + def find_stmt(kinds: KindMap)(s: Statement):Statement = { + s match { + case s: DefWire => kinds(s.name) = WireKind() + case s: DefNode => kinds(s.name) = NodeKind() + case s: DefRegister => kinds(s.name) = RegKind() + case s: WDefInstance => kinds(s.name) = InstanceKind() + case s: DefMemory => kinds(s.name) = MemKind(s.readers ++ s.writers ++ s.readwriters) + case s => + } + s map find_stmt(kinds) + } + + def resolve_expr(kinds: KindMap)(e: Expression): Expression = e match { + case e: WRef => e copy (kind = kinds(e.name)) + case e => e map resolve_expr(kinds) + } + + def resolve_stmt(kinds: KindMap)(s: Statement): Statement = + s map resolve_stmt(kinds) map resolve_expr(kinds) + + def resolve_kinds(m: DefModule): DefModule = { + val kinds = new KindMap + (m map find_port(kinds) + map find_stmt(kinds) + map resolve_stmt(kinds)) + } + + def run(c: Circuit): Circuit = + c copy (modules = (c.modules map resolve_kinds)) +} + +object ResolveGenders extends Pass { + def name = "Resolve Genders" + def resolve_e(g: Gender)(e: Expression): Expression = e match { + case e: WRef => e copy (gender = g) + case WSubField(exp, name, tpe, _) => WSubField( + Utils.field_flip(exp.tpe, name) match { + case Default => resolve_e(g)(exp) + case Flip => resolve_e(Utils.swap(g))(exp) + }, name, tpe, g) + case WSubIndex(exp, value, tpe, _) => + WSubIndex(resolve_e(g)(exp), value, tpe, g) + case WSubAccess(exp, index, tpe, _) => + WSubAccess(resolve_e(g)(exp), resolve_e(MALE)(index), tpe, g) + case e => e map resolve_e(g) + } + + def resolve_s(s: Statement): Statement = s match { + case IsInvalid(info, expr) => + IsInvalid(info, resolve_e(FEMALE)(expr)) + case Connect(info, loc, expr) => + Connect(info, resolve_e(FEMALE)(loc), resolve_e(MALE)(expr)) + case PartialConnect(info, loc, expr) => + PartialConnect(info, resolve_e(FEMALE)(loc), resolve_e(MALE)(expr)) + case s => s map resolve_e(MALE) map resolve_s + } + + def resolve_gender(m: DefModule): DefModule = m map resolve_s + + def run(c: Circuit): Circuit = + c copy (modules = (c.modules map resolve_gender)) +} + +object CInferMDir extends Pass { + def name = "CInfer MDir" + type MPortDirMap = collection.mutable.LinkedHashMap[String, MPortDir] + + def infer_mdir_e(mports: MPortDirMap, dir: MPortDir)(e: Expression): Expression = { + (e map infer_mdir_e(mports, dir)) match { + case e: Reference => mports get e.name match { + case Some(p) => mports(e.name) = (p, dir) match { + case (MInfer, MInfer) => Utils.error("Shouldn't be here") + case (MInfer, MWrite) => MWrite + case (MInfer, MRead) => MRead + case (MInfer, MReadWrite) => MReadWrite + case (MWrite, MInfer) => Utils.error("Shouldn't be here") + case (MWrite, MWrite) => MWrite + case (MWrite, MRead) => MReadWrite + case (MWrite, MReadWrite) => MReadWrite + case (MRead, MInfer) => Utils.error("Shouldn't be here") + case (MRead, MWrite) => MReadWrite + case (MRead, MRead) => MRead + case (MRead, MReadWrite) => MReadWrite + case (MReadWrite, MInfer) => Utils.error("Shouldn't be here") + case (MReadWrite, MWrite) => MReadWrite + case (MReadWrite, MRead) => MReadWrite + case (MReadWrite, MReadWrite) => MReadWrite + } ; e + case None => e + } + case _ => e + } + } + + def infer_mdir_s(mports: MPortDirMap)(s: Statement): Statement = s match { + case s: CDefMPort => + mports(s.name) = s.direction + s map infer_mdir_e(mports, MRead) + case s: Connect => + infer_mdir_e(mports, MRead)(s.expr) + infer_mdir_e(mports, MWrite)(s.loc) + s + case s: PartialConnect => + infer_mdir_e(mports, MRead)(s.expr) + infer_mdir_e(mports, MWrite)(s.loc) + s + case s => s map infer_mdir_s(mports) map infer_mdir_e(mports, MRead) + } + + def set_mdir_s(mports: MPortDirMap)(s: Statement): Statement = s match { + case s: CDefMPort => s copy (direction = mports(s.name)) + case s => s map set_mdir_s(mports) + } + + def infer_mdir(m: DefModule): DefModule = { + val mports = new MPortDirMap + m map infer_mdir_s(mports) map set_mdir_s(mports) + } + + def run(c: Circuit): Circuit = + c copy (modules = (c.modules map infer_mdir)) +} |
