diff options
| author | Adam Izraelevitz | 2016-07-27 13:53:30 -0700 |
|---|---|---|
| committer | GitHub | 2016-07-27 13:53:30 -0700 |
| commit | 486cdb5ea4a3450c81231f09488b5b166c363133 (patch) | |
| tree | 0df3abbd5ee94a1d221b5d798e2722dfe9844028 /src | |
| parent | 42d38081f19b25ccb78f81f451b58e77b3e96d53 (diff) | |
| parent | a6c8493e907dedcbb289f6d4f6323cc26fb1edc0 (diff) | |
Merge pull request #198 from ucb-bar/add-chirrtl-check
Added a Chirrtl check for undeclared wires, etc.
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/firrtl/LoweringCompilers.scala | 6 | ||||
| -rw-r--r-- | src/main/scala/firrtl/PrimOps.scala | 549 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Utils.scala | 22 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/CheckChirrtl.scala | 166 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/Checks.scala | 18 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/ChirrtlSpec.scala | 59 |
6 files changed, 507 insertions, 313 deletions
diff --git a/src/main/scala/firrtl/LoweringCompilers.scala b/src/main/scala/firrtl/LoweringCompilers.scala index 9a2bc11f..036156dc 100644 --- a/src/main/scala/firrtl/LoweringCompilers.scala +++ b/src/main/scala/firrtl/LoweringCompilers.scala @@ -61,6 +61,7 @@ trait SimpleRun extends LazyLogging { // TODO(izraelevitz): Create RenameMap from RemoveCHIRRTL class Chisel3ToHighFirrtl () extends Transform with SimpleRun { val passSeq = Seq( + passes.CheckChirrtl, passes.CInferTypes, passes.CInferMDir, passes.RemoveCHIRRTL) @@ -108,8 +109,9 @@ class HighFirrtlToMiddleFirrtl () extends Transform with SimpleRun { passes.CheckInitialization, passes.ResolveKinds, passes.InferTypes, - passes.ResolveGenders, - passes.InferWidths) + passes.ResolveGenders) + //passes.InferWidths, + //passes.CheckWidths) def execute (circuit: Circuit, annotations: Seq[CircuitAnnotation]): TransformResult = run(circuit, passSeq) } diff --git a/src/main/scala/firrtl/PrimOps.scala b/src/main/scala/firrtl/PrimOps.scala index 7e8d77db..7d7524f6 100644 --- a/src/main/scala/firrtl/PrimOps.scala +++ b/src/main/scala/firrtl/PrimOps.scala @@ -127,279 +127,282 @@ object PrimOps extends LazyLogging { def w3 () = Utils.widthBANG(a(2).tpe) def c1 () = IntWidth(c(0)) def c2 () = IntWidth(c(1)) - o match { - case Add => { - val t = (t1(),t2()) match { - case (t1:UIntType, t2:UIntType) => UIntType(PLUS(MAX(w1(),w2()),Utils.ONE)) - case (t1:UIntType, t2:SIntType) => SIntType(PLUS(MAX(w1(),w2()),Utils.ONE)) - case (t1:SIntType, t2:UIntType) => SIntType(PLUS(MAX(w1(),w2()),Utils.ONE)) - case (t1:SIntType, t2:SIntType) => SIntType(PLUS(MAX(w1(),w2()),Utils.ONE)) - case (t1, t2) => UnknownType - } - DoPrim(o,a,c,t) - } - case Sub => { - val t = (t1(),t2()) match { - case (t1:UIntType, t2:UIntType) => SIntType(PLUS(MAX(w1(),w2()),Utils.ONE)) - case (t1:UIntType, t2:SIntType) => SIntType(PLUS(MAX(w1(),w2()),Utils.ONE)) - case (t1:SIntType, t2:UIntType) => SIntType(PLUS(MAX(w1(),w2()),Utils.ONE)) - case (t1:SIntType, t2:SIntType) => SIntType(PLUS(MAX(w1(),w2()),Utils.ONE)) - case (t1, t2) => UnknownType - } - DoPrim(o,a,c,t) - } - case Mul => { - val t = (t1(),t2()) match { - case (t1:UIntType, t2:UIntType) => UIntType(PLUS(w1(),w2())) - case (t1:UIntType, t2:SIntType) => SIntType(PLUS(w1(),w2())) - case (t1:SIntType, t2:UIntType) => SIntType(PLUS(w1(),w2())) - case (t1:SIntType, t2:SIntType) => SIntType(PLUS(w1(),w2())) - case (t1, t2) => UnknownType - } - DoPrim(o,a,c,t) - } - case Div => { - val t = (t1(),t2()) match { - case (t1:UIntType, t2:UIntType) => UIntType(w1()) - case (t1:UIntType, t2:SIntType) => SIntType(PLUS(w1(),Utils.ONE)) - case (t1:SIntType, t2:UIntType) => SIntType(w1()) - case (t1:SIntType, t2:SIntType) => SIntType(PLUS(w1(),Utils.ONE)) - case (t1, t2) => UnknownType - } - DoPrim(o,a,c,t) - } - case Rem => { - val t = (t1(),t2()) match { - case (t1:UIntType, t2:UIntType) => UIntType(MIN(w1(),w2())) - case (t1:UIntType, t2:SIntType) => UIntType(MIN(w1(),w2())) - case (t1:SIntType, t2:UIntType) => SIntType(MIN(w1(),PLUS(w2(),Utils.ONE))) - case (t1:SIntType, t2:SIntType) => SIntType(MIN(w1(),w2())) - case (t1, t2) => UnknownType - } - DoPrim(o,a,c,t) - } - case Lt => { - val t = (t1(),t2()) match { - case (t1:UIntType, t2:UIntType) => Utils.BoolType - case (t1:SIntType, t2:UIntType) => Utils.BoolType - case (t1:UIntType, t2:SIntType) => Utils.BoolType - case (t1:SIntType, t2:SIntType) => Utils.BoolType - case (t1, t2) => UnknownType - } - DoPrim(o,a,c,t) - } - case Leq => { - val t = (t1(),t2()) match { - case (t1:UIntType, t2:UIntType) => Utils.BoolType - case (t1:SIntType, t2:UIntType) => Utils.BoolType - case (t1:UIntType, t2:SIntType) => Utils.BoolType - case (t1:SIntType, t2:SIntType) => Utils.BoolType - case (t1, t2) => UnknownType - } - DoPrim(o,a,c,t) - } - case Gt => { - val t = (t1(),t2()) match { - case (t1:UIntType, t2:UIntType) => Utils.BoolType - case (t1:SIntType, t2:UIntType) => Utils.BoolType - case (t1:UIntType, t2:SIntType) => Utils.BoolType - case (t1:SIntType, t2:SIntType) => Utils.BoolType - case (t1, t2) => UnknownType - } - DoPrim(o,a,c,t) - } - case Geq => { - val t = (t1(),t2()) match { - case (t1:UIntType, t2:UIntType) => Utils.BoolType - case (t1:SIntType, t2:UIntType) => Utils.BoolType - case (t1:UIntType, t2:SIntType) => Utils.BoolType - case (t1:SIntType, t2:SIntType) => Utils.BoolType - case (t1, t2) => UnknownType - } - DoPrim(o,a,c,t) - } - case Eq => { - val t = (t1(),t2()) match { - case (t1:UIntType, t2:UIntType) => Utils.BoolType - case (t1:SIntType, t2:UIntType) => Utils.BoolType - case (t1:UIntType, t2:SIntType) => Utils.BoolType - case (t1:SIntType, t2:SIntType) => Utils.BoolType - case (t1, t2) => UnknownType - } - DoPrim(o,a,c,t) - } - case Neq => { - val t = (t1(),t2()) match { - case (t1:UIntType, t2:UIntType) => Utils.BoolType - case (t1:SIntType, t2:UIntType) => Utils.BoolType - case (t1:UIntType, t2:SIntType) => Utils.BoolType - case (t1:SIntType, t2:SIntType) => Utils.BoolType - case (t1, t2) => UnknownType - } - DoPrim(o,a,c,t) - } - case Pad => { - val t = (t1()) match { - case (t1:UIntType) => UIntType(MAX(w1(),c1())) - case (t1:SIntType) => SIntType(MAX(w1(),c1())) - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - case AsUInt => { - val t = (t1()) match { - case (t1:UIntType) => UIntType(w1()) - case (t1:SIntType) => UIntType(w1()) - case ClockType => UIntType(Utils.ONE) - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - case AsSInt => { - val t = (t1()) match { - case (t1:UIntType) => SIntType(w1()) - case (t1:SIntType) => SIntType(w1()) - case ClockType => SIntType(Utils.ONE) - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - case AsClock => { - val t = (t1()) match { - case (t1:UIntType) => ClockType - case (t1:SIntType) => ClockType - case ClockType => ClockType - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - case Shl => { - val t = (t1()) match { - case (t1:UIntType) => UIntType(PLUS(w1(),c1())) - case (t1:SIntType) => SIntType(PLUS(w1(),c1())) - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - case Shr => { - val t = (t1()) match { - case (t1:UIntType) => UIntType(MAX(MINUS(w1(),c1()),Utils.ONE)) - case (t1:SIntType) => SIntType(MAX(MINUS(w1(),c1()),Utils.ONE)) - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - case Dshl => { - val t = (t1()) match { - case (t1:UIntType) => UIntType(PLUS(w1(),POW(w2()))) - case (t1:SIntType) => SIntType(PLUS(w1(),POW(w2()))) - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - case Dshr => { - val t = (t1()) match { - case (t1:UIntType) => UIntType(w1()) - case (t1:SIntType) => SIntType(w1()) - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - case Cvt => { - val t = (t1()) match { - case (t1:UIntType) => SIntType(PLUS(w1(),Utils.ONE)) - case (t1:SIntType) => SIntType(w1()) - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - case Neg => { - val t = (t1()) match { - case (t1:UIntType) => SIntType(PLUS(w1(),Utils.ONE)) - case (t1:SIntType) => SIntType(PLUS(w1(),Utils.ONE)) - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - case Not => { - val t = (t1()) match { - case (t1:UIntType) => UIntType(w1()) - case (t1:SIntType) => UIntType(w1()) - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - case And => { - val t = (t1(),t2()) match { - case (_:SIntType|_:UIntType, _:SIntType|_:UIntType) => UIntType(MAX(w1(),w2())) - case (t1,t2) => UnknownType - } - DoPrim(o,a,c,t) - } - case Or => { - val t = (t1(),t2()) match { - case (_:SIntType|_:UIntType, _:SIntType|_:UIntType) => UIntType(MAX(w1(),w2())) - case (t1,t2) => UnknownType - } - DoPrim(o,a,c,t) - } - case Xor => { - val t = (t1(),t2()) match { - case (_:SIntType|_:UIntType, _:SIntType|_:UIntType) => UIntType(MAX(w1(),w2())) - case (t1,t2) => UnknownType - } - DoPrim(o,a,c,t) - } - case Andr => { - val t = (t1()) match { - case (_:UIntType|_:SIntType) => Utils.BoolType - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - case Orr => { - val t = (t1()) match { - case (_:UIntType|_:SIntType) => Utils.BoolType - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - case Xorr => { - val t = (t1()) match { - case (_:UIntType|_:SIntType) => Utils.BoolType - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - case Cat => { - val t = (t1(),t2()) match { - case (_:UIntType|_:SIntType,_:UIntType|_:SIntType) => UIntType(PLUS(w1(),w2())) - case (t1, t2) => UnknownType - } - DoPrim(o,a,c,t) - } - case Bits => { - val t = (t1()) match { - case (_:UIntType|_:SIntType) => UIntType(PLUS(MINUS(c1(),c2()),Utils.ONE)) - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - case Head => { - val t = (t1()) match { - case (_:UIntType|_:SIntType) => UIntType(c1()) - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - case Tail => { - val t = (t1()) match { - case (_:UIntType|_:SIntType) => UIntType(MINUS(w1(),c1())) - case (t1) => UnknownType - } - DoPrim(o,a,c,t) - } - + e.tpe match { + case UIntType(IntWidth(w)) => e + case SIntType(IntWidth(w)) => e + case _ => o match { + case Add => { + val t = (t1(),t2()) match { + case (t1:UIntType, t2:UIntType) => UIntType(PLUS(MAX(w1(),w2()),Utils.ONE)) + case (t1:UIntType, t2:SIntType) => SIntType(PLUS(MAX(w1(),w2()),Utils.ONE)) + case (t1:SIntType, t2:UIntType) => SIntType(PLUS(MAX(w1(),w2()),Utils.ONE)) + case (t1:SIntType, t2:SIntType) => SIntType(PLUS(MAX(w1(),w2()),Utils.ONE)) + case (t1, t2) => UnknownType + } + DoPrim(o,a,c,t) + } + case Sub => { + val t = (t1(),t2()) match { + case (t1:UIntType, t2:UIntType) => SIntType(PLUS(MAX(w1(),w2()),Utils.ONE)) + case (t1:UIntType, t2:SIntType) => SIntType(PLUS(MAX(w1(),w2()),Utils.ONE)) + case (t1:SIntType, t2:UIntType) => SIntType(PLUS(MAX(w1(),w2()),Utils.ONE)) + case (t1:SIntType, t2:SIntType) => SIntType(PLUS(MAX(w1(),w2()),Utils.ONE)) + case (t1, t2) => UnknownType + } + DoPrim(o,a,c,t) + } + case Mul => { + val t = (t1(),t2()) match { + case (t1:UIntType, t2:UIntType) => UIntType(PLUS(w1(),w2())) + case (t1:UIntType, t2:SIntType) => SIntType(PLUS(w1(),w2())) + case (t1:SIntType, t2:UIntType) => SIntType(PLUS(w1(),w2())) + case (t1:SIntType, t2:SIntType) => SIntType(PLUS(w1(),w2())) + case (t1, t2) => UnknownType + } + DoPrim(o,a,c,t) + } + case Div => { + val t = (t1(),t2()) match { + case (t1:UIntType, t2:UIntType) => UIntType(w1()) + case (t1:UIntType, t2:SIntType) => SIntType(PLUS(w1(),Utils.ONE)) + case (t1:SIntType, t2:UIntType) => SIntType(w1()) + case (t1:SIntType, t2:SIntType) => SIntType(PLUS(w1(),Utils.ONE)) + case (t1, t2) => UnknownType + } + DoPrim(o,a,c,t) + } + case Rem => { + val t = (t1(),t2()) match { + case (t1:UIntType, t2:UIntType) => UIntType(MIN(w1(),w2())) + case (t1:UIntType, t2:SIntType) => UIntType(MIN(w1(),w2())) + case (t1:SIntType, t2:UIntType) => SIntType(MIN(w1(),PLUS(w2(),Utils.ONE))) + case (t1:SIntType, t2:SIntType) => SIntType(MIN(w1(),w2())) + case (t1, t2) => UnknownType + } + DoPrim(o,a,c,t) + } + case Lt => { + val t = (t1(),t2()) match { + case (t1:UIntType, t2:UIntType) => Utils.BoolType + case (t1:SIntType, t2:UIntType) => Utils.BoolType + case (t1:UIntType, t2:SIntType) => Utils.BoolType + case (t1:SIntType, t2:SIntType) => Utils.BoolType + case (t1, t2) => UnknownType + } + DoPrim(o,a,c,t) + } + case Leq => { + val t = (t1(),t2()) match { + case (t1:UIntType, t2:UIntType) => Utils.BoolType + case (t1:SIntType, t2:UIntType) => Utils.BoolType + case (t1:UIntType, t2:SIntType) => Utils.BoolType + case (t1:SIntType, t2:SIntType) => Utils.BoolType + case (t1, t2) => UnknownType + } + DoPrim(o,a,c,t) + } + case Gt => { + val t = (t1(),t2()) match { + case (t1:UIntType, t2:UIntType) => Utils.BoolType + case (t1:SIntType, t2:UIntType) => Utils.BoolType + case (t1:UIntType, t2:SIntType) => Utils.BoolType + case (t1:SIntType, t2:SIntType) => Utils.BoolType + case (t1, t2) => UnknownType + } + DoPrim(o,a,c,t) + } + case Geq => { + val t = (t1(),t2()) match { + case (t1:UIntType, t2:UIntType) => Utils.BoolType + case (t1:SIntType, t2:UIntType) => Utils.BoolType + case (t1:UIntType, t2:SIntType) => Utils.BoolType + case (t1:SIntType, t2:SIntType) => Utils.BoolType + case (t1, t2) => UnknownType + } + DoPrim(o,a,c,t) + } + case Eq => { + val t = (t1(),t2()) match { + case (t1:UIntType, t2:UIntType) => Utils.BoolType + case (t1:SIntType, t2:UIntType) => Utils.BoolType + case (t1:UIntType, t2:SIntType) => Utils.BoolType + case (t1:SIntType, t2:SIntType) => Utils.BoolType + case (t1, t2) => UnknownType + } + DoPrim(o,a,c,t) + } + case Neq => { + val t = (t1(),t2()) match { + case (t1:UIntType, t2:UIntType) => Utils.BoolType + case (t1:SIntType, t2:UIntType) => Utils.BoolType + case (t1:UIntType, t2:SIntType) => Utils.BoolType + case (t1:SIntType, t2:SIntType) => Utils.BoolType + case (t1, t2) => UnknownType + } + DoPrim(o,a,c,t) + } + case Pad => { + val t = (t1()) match { + case (t1:UIntType) => UIntType(MAX(w1(),c1())) + case (t1:SIntType) => SIntType(MAX(w1(),c1())) + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + case AsUInt => { + val t = (t1()) match { + case (t1:UIntType) => UIntType(w1()) + case (t1:SIntType) => UIntType(w1()) + case ClockType => UIntType(Utils.ONE) + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + case AsSInt => { + val t = (t1()) match { + case (t1:UIntType) => SIntType(w1()) + case (t1:SIntType) => SIntType(w1()) + case ClockType => SIntType(Utils.ONE) + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + case AsClock => { + val t = (t1()) match { + case (t1:UIntType) => ClockType + case (t1:SIntType) => ClockType + case ClockType => ClockType + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + case Shl => { + val t = (t1()) match { + case (t1:UIntType) => UIntType(PLUS(w1(),c1())) + case (t1:SIntType) => SIntType(PLUS(w1(),c1())) + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + case Shr => { + val t = (t1()) match { + case (t1:UIntType) => UIntType(MAX(MINUS(w1(),c1()),Utils.ONE)) + case (t1:SIntType) => SIntType(MAX(MINUS(w1(),c1()),Utils.ONE)) + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + case Dshl => { + val t = (t1()) match { + case (t1:UIntType) => UIntType(PLUS(w1(),POW(w2()))) + case (t1:SIntType) => SIntType(PLUS(w1(),POW(w2()))) + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + case Dshr => { + val t = (t1()) match { + case (t1:UIntType) => UIntType(w1()) + case (t1:SIntType) => SIntType(w1()) + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + case Cvt => { + val t = (t1()) match { + case (t1:UIntType) => SIntType(PLUS(w1(),Utils.ONE)) + case (t1:SIntType) => SIntType(w1()) + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + case Neg => { + val t = (t1()) match { + case (t1:UIntType) => SIntType(PLUS(w1(),Utils.ONE)) + case (t1:SIntType) => SIntType(PLUS(w1(),Utils.ONE)) + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + case Not => { + val t = (t1()) match { + case (t1:UIntType) => UIntType(w1()) + case (t1:SIntType) => UIntType(w1()) + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + case And => { + val t = (t1(),t2()) match { + case (_:SIntType|_:UIntType, _:SIntType|_:UIntType) => UIntType(MAX(w1(),w2())) + case (t1,t2) => UnknownType + } + DoPrim(o,a,c,t) + } + case Or => { + val t = (t1(),t2()) match { + case (_:SIntType|_:UIntType, _:SIntType|_:UIntType) => UIntType(MAX(w1(),w2())) + case (t1,t2) => UnknownType + } + DoPrim(o,a,c,t) + } + case Xor => { + val t = (t1(),t2()) match { + case (_:SIntType|_:UIntType, _:SIntType|_:UIntType) => UIntType(MAX(w1(),w2())) + case (t1,t2) => UnknownType + } + DoPrim(o,a,c,t) + } + case Andr => { + val t = (t1()) match { + case (_:UIntType|_:SIntType) => Utils.BoolType + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + case Orr => { + val t = (t1()) match { + case (_:UIntType|_:SIntType) => Utils.BoolType + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + case Xorr => { + val t = (t1()) match { + case (_:UIntType|_:SIntType) => Utils.BoolType + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + case Cat => { + val t = (t1(),t2()) match { + case (_:UIntType|_:SIntType,_:UIntType|_:SIntType) => UIntType(PLUS(w1(),w2())) + case (t1, t2) => UnknownType + } + DoPrim(o,a,c,t) + } + case Bits => { + val t = (t1()) match { + case (_:UIntType|_:SIntType) => UIntType(PLUS(MINUS(c1(),c2()),Utils.ONE)) + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + case Head => { + val t = (t1()) match { + case (_:UIntType|_:SIntType) => UIntType(c1()) + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + case Tail => { + val t = (t1()) match { + case (_:UIntType|_:SIntType) => UIntType(MINUS(w1(),c1())) + case (t1) => UnknownType + } + DoPrim(o,a,c,t) + } + } } } diff --git a/src/main/scala/firrtl/Utils.scala b/src/main/scala/firrtl/Utils.scala index 2053a70d..76c8e61e 100644 --- a/src/main/scala/firrtl/Utils.scala +++ b/src/main/scala/firrtl/Utils.scala @@ -203,6 +203,22 @@ object Utils extends LazyLogging { } } + /** Returns true if t, or any subtype, contains a flipped field + * @param t [[firrtl.ir.Type]] + * @return if t contains [[firrtl.ir.Flip]] + */ + def hasFlip(t: Type): Boolean = { + var has = false + def findFlip(t: Type): Type = t map (findFlip) match { + case t: BundleType => + for (f <- t.fields) { if (f.flip == Flip) has = true } + t + case t: Type => t + } + findFlip(t) + has + } + //============== TYPES ================ def mux_type (e1:Expression,e2:Expression) : Type = mux_type(tpe(e1),tpe(e2)) def mux_type (t1:Type,t2:Type) : Type = { @@ -268,7 +284,11 @@ object Utils extends LazyLogging { } def long_BANG (t:Type) : Long = { (t) match { - case g: GroundType => g.width.as[IntWidth].get.width.toLong + case g: GroundType => + g.width match { + case IntWidth(x) => x.toLong + case _ => throw new FIRRTLException(s"Expecting IntWidth, got: ${g.width}") + } case (t:BundleType) => { var w = 0 for (f <- t.fields) { w = w + long_BANG(f.tpe).toInt } diff --git a/src/main/scala/firrtl/passes/CheckChirrtl.scala b/src/main/scala/firrtl/passes/CheckChirrtl.scala new file mode 100644 index 00000000..42f5bba2 --- /dev/null +++ b/src/main/scala/firrtl/passes/CheckChirrtl.scala @@ -0,0 +1,166 @@ +/* +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 com.typesafe.scalalogging.LazyLogging + +// Datastructures +import scala.collection.mutable.HashMap +import scala.collection.mutable.ArrayBuffer + +import firrtl._ +import firrtl.ir._ +import firrtl.Utils._ +import firrtl.Mappers._ +import firrtl.Serialize._ +import firrtl.PrimOps._ +import firrtl.WrappedType._ + + +object CheckChirrtl extends Pass with LazyLogging { + def name = "Chirrtl Check" + + // TODO FIXME + // - Do we need to check for uniquness on port names? + def run (c: Circuit): Circuit = { + var mname: String = "" + var sinfo: Info = NoInfo + + class NotUniqueException(name: String) extends PassException(s"${sinfo}: [module ${mname}] Reference ${name} does not have a unique name.") + class InvalidLOCException extends PassException(s"${sinfo}: [module ${mname}] Invalid connect to an expression that is not a reference or a WritePort.") + class UndeclaredReferenceException(name: String) extends PassException(s"${sinfo}: [module ${mname}] Reference ${name} is not declared.") + class MemWithFlipException(name: String) extends PassException(s"${sinfo}: [module ${mname}] Memory ${name} cannot be a bundle type with flips.") + class InvalidAccessException extends PassException(s"${sinfo}: [module ${mname}] Invalid access to non-reference.") + class NoTopModuleException(name: String) extends PassException(s"${sinfo}: A single module must be named ${name}.") + class ModuleNotDefinedException(name: String) extends PassException(s"${sinfo}: Module ${name} is not defined.") + class NegWidthException extends PassException(s"${sinfo}: [module ${mname}] Width cannot be negative or zero.") + class NegVecSizeException extends PassException(s"${sinfo}: [module ${mname}] Vector type size cannot be negative.") + class NegMemSizeException extends PassException(s"${sinfo}: [module ${mname}] Memory size cannot be negative or zero.") + + val errors = new Errors() + def checkValidLoc(e: Expression) = e match { + case e @ (_: UIntLiteral | _: SIntLiteral | _: DoPrim ) => errors.append(new InvalidLOCException) + case _ => // Do Nothing + } + def checkChirrtlW(w: Width): Width = w match { + case w: IntWidth if (w.width <= BigInt(0)) => + errors.append(new NegWidthException) + w + case _ => w + } + def checkChirrtlT(t: Type): Type = { + t map (checkChirrtlT) match { + case t: VectorType if (t.size < 0) => errors.append(new NegVecSizeException) + case _ => // Do nothing + } + t map (checkChirrtlW) + } + + def checkChirrtlM(m: DefModule): DefModule = { + val names = HashMap[String, Boolean]() + val mnames = HashMap[String, Boolean]() + def checkChirrtlE(e: Expression): Expression = { + def validSubexp(e: Expression): Expression = e match { + case (_:Reference|_:SubField|_:SubIndex|_:SubAccess|_:Mux|_:ValidIf) => e // No error + case _ => + errors.append(new InvalidAccessException) + e + } + e map (checkChirrtlE) match { + case e: Reference if (!names.contains(e.name)) => errors.append(new UndeclaredReferenceException(e.name)) + case e: DoPrim => {} + case (_:Mux|_:ValidIf) => {} + case e: SubAccess => + validSubexp(e.expr) + e + case e: UIntLiteral => {} + case e => e map (validSubexp) + } + e map (checkChirrtlW) + e map (checkChirrtlT) + e + } + def checkChirrtlS(s: Statement): Statement = { + sinfo = s.getInfo + def checkName(name: String): String = { + if (names.contains(name)) errors.append(new NotUniqueException(name)) + else names(name) = true + name + } + + s map (checkName) + s map (checkChirrtlT) + s map (checkChirrtlE) + s match { + case s: DefMemory => + if (hasFlip(s.dataType)) errors.append(new MemWithFlipException(s.name)) + if (s.depth <= 0) errors.append(new NegMemSizeException) + case s: DefInstance => + if (!c.modules.map(_.name).contains(s.module)) + errors.append(new ModuleNotDefinedException(s.module)) + case s: Connect => checkValidLoc(s.loc) + case s: PartialConnect => checkValidLoc(s.loc) + case s: Print => {} + case _ => // Do Nothing + } + + s map (checkChirrtlS) + } + + mname = m.name + for (m <- c.modules) { + mnames(m.name) = true + } + for (p <- m.ports) { + sinfo = p.info + names(p.name) = true + val tpe = p.getType + tpe map (checkChirrtlT) + tpe map (checkChirrtlW) + } + + m match { + case m: Module => checkChirrtlS(m.body) + case m: ExtModule => // Do Nothing + } + m + } + + var numTopM = 0 + for (m <- c.modules) { + if (m.name == c.main) numTopM = numTopM + 1 + checkChirrtlM(m) + } + sinfo = c.info + if (numTopM != 1) errors.append(new NoTopModuleException(c.main)) + errors.trigger + c + } +} + +// vim: set ts=4 sw=4 et: diff --git a/src/main/scala/firrtl/passes/Checks.scala b/src/main/scala/firrtl/passes/Checks.scala index 5c0bb251..9bbf7fa8 100644 --- a/src/main/scala/firrtl/passes/Checks.scala +++ b/src/main/scala/firrtl/passes/Checks.scala @@ -117,24 +117,6 @@ object CheckHighForm extends Pass with LazyLogging { } } - // Utility functions - def hasFlip(t: Type): Boolean = { - var has = false - def findFlip(t: Type): Type = { - t map (findFlip) match { - case t: BundleType => { - for (f <- t.fields) { - if (f.flip == Flip) has = true - } - t - } - case t: Type => t - } - } - findFlip(t) - has - } - // TODO FIXME // - Do we need to check for uniquness on port names? // Global Variables diff --git a/src/test/scala/firrtlTests/ChirrtlSpec.scala b/src/test/scala/firrtlTests/ChirrtlSpec.scala index d3e02ff1..a24cd9fa 100644 --- a/src/test/scala/firrtlTests/ChirrtlSpec.scala +++ b/src/test/scala/firrtlTests/ChirrtlSpec.scala @@ -35,27 +35,28 @@ import firrtl.ir.Circuit import firrtl.passes._ class ChirrtlSpec extends FirrtlFlatSpec { + def passes = Seq( + CheckChirrtl, + CInferTypes, + CInferMDir, + RemoveCHIRRTL, + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes, + ResolveGenders, + CheckGenders, + InferWidths, + CheckWidths, + PullMuxes, + ExpandConnects, + RemoveAccesses, + ExpandWhens, + CheckInitialization + ) "Chirrtl memories" should "allow ports with clocks defined after the memory" in { - val passes = Seq( - CInferTypes, - CInferMDir, - RemoveCHIRRTL, - ToWorkingIR, - CheckHighForm, - ResolveKinds, - InferTypes, - CheckTypes, - ResolveGenders, - CheckGenders, - InferWidths, - CheckWidths, - PullMuxes, - ExpandConnects, - RemoveAccesses, - ExpandWhens, - CheckInitialization - ) val input = """circuit Unit : | module Unit : @@ -73,6 +74,26 @@ class ChirrtlSpec extends FirrtlFlatSpec { } } + "Chirrtl" should "catch undeclared wires" in { + val input = + """circuit Unit : + | module Unit : + | input clk : Clock + | smem ram : UInt<32>[128] + | node newClock = clk + | infer mport x = ram[UInt(2)], newClock + | x <= UInt(3) + | when UInt(1) : + | infer mport y = ram[UInt(4)], newClock + | y <= z + """.stripMargin + intercept[PassException] { + passes.foldLeft(Parser.parse(input.split("\n").toIterator)) { + (c: Circuit, p: Pass) => p.run(c) + } + } + } + it should "compile and run" in { runFirrtlTest("ChirrtlMems", "/features") } |
