diff options
| author | Jack Koenig | 2019-02-14 15:08:35 -0800 |
|---|---|---|
| committer | GitHub | 2019-02-14 15:08:35 -0800 |
| commit | 2272044c6ab46b5148c39c124e66e1a8e9073a24 (patch) | |
| tree | 83ad2141b1a3c54707dd9b33073f9217b0ae16c8 /src/main/scala/firrtl/passes | |
| parent | d487b4cb6726e7e8d1a18f894021652594125221 (diff) | |
Asynchronous Reset (#1011)
Fixes #219
* Adds AsyncResetType (similar to ClockType)
* Registers with reset signal of type AsyncResetType are async reset
registers
* Registers with async reset can only be reset to literal values
* Add initialization logic for async reset registers
Diffstat (limited to 'src/main/scala/firrtl/passes')
| -rw-r--r-- | src/main/scala/firrtl/passes/CheckWidths.scala | 1 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/Checks.scala | 54 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/InferWidths.scala | 12 |
3 files changed, 42 insertions, 25 deletions
diff --git a/src/main/scala/firrtl/passes/CheckWidths.scala b/src/main/scala/firrtl/passes/CheckWidths.scala index 061c6b16..e1e9fc5f 100644 --- a/src/main/scala/firrtl/passes/CheckWidths.scala +++ b/src/main/scala/firrtl/passes/CheckWidths.scala @@ -107,6 +107,7 @@ object CheckWidths extends Pass { case sx: DefRegister => sx.reset.tpe match { case UIntType(IntWidth(w)) if w == 1 => + case AsyncResetType => case _ => errors.append(new CheckTypes.IllegalResetType(info, target.serialize, sx.name)) } case _ => diff --git a/src/main/scala/firrtl/passes/Checks.scala b/src/main/scala/firrtl/passes/Checks.scala index 4b996f5d..b6855d75 100644 --- a/src/main/scala/firrtl/passes/Checks.scala +++ b/src/main/scala/firrtl/passes/Checks.scala @@ -53,6 +53,8 @@ object CheckHighForm extends Pass { s"$info: [module $mname] Primop $op argument $value < 0.") class LsbLargerThanMsbException(info: Info, mname: String, op: String, lsb: Int, msb: Int) extends PassException( s"$info: [module $mname] Primop $op lsb $lsb > $msb.") + class NonLiteralAsyncResetValueException(info: Info, mname: String, reg: String, init: String) extends PassException( + s"$info: [module $mname] AsyncReset Reg '$reg' reset to non-literal '$init'") def run(c: Circuit): Circuit = { val errors = new Errors() @@ -74,7 +76,7 @@ object CheckHighForm extends Pass { case Add | Sub | Mul | Div | Rem | Lt | Leq | Gt | Geq | Eq | Neq | Dshl | Dshr | And | Or | Xor | Cat => correctNum(Option(2), 0) - case AsUInt | AsSInt | AsClock | Cvt | Neq | Not => + case AsUInt | AsSInt | AsClock | AsAsyncReset | Cvt | Neq | Not => correctNum(Option(1), 0) case AsFixedPoint | Pad | Head | Tail | BPShl | BPShr | BPSet => correctNum(Option(1), 1) @@ -164,6 +166,13 @@ object CheckHighForm extends Pass { val info = get_info(s) match {case NoInfo => minfo case x => x} s foreach checkName(info, mname, names) s match { + case DefRegister(info, name, _,_, reset, init) if reset.tpe == AsyncResetType => + init match { + case _: Literal => // okay + case nonlit => + val e = new NonLiteralAsyncResetValueException(info, mname, name, nonlit.serialize) + errors.append(e) + } case sx: DefMemory => if (hasFlip(sx.dataType)) errors.append(new MemWithFlipException(info, mname, sx.name)) @@ -291,41 +300,43 @@ object CheckTypes extends Pass { case tx => true } def check_types_primop(info: Info, mname: String, e: DoPrim): Unit = { - def checkAllTypes(exprs: Seq[Expression], okUInt: Boolean, okSInt: Boolean, okClock: Boolean, okFix: Boolean): Unit = { - exprs.foldLeft((false, false, false, false)) { - case ((isUInt, isSInt, isClock, isFix), expr) => expr.tpe match { - case u: UIntType => (true, isSInt, isClock, isFix) - case s: SIntType => (isUInt, true, isClock, isFix) - case ClockType => (isUInt, isSInt, true, isFix) - case f: FixedType => (isUInt, isSInt, isClock, true) - case UnknownType => + def checkAllTypes(exprs: Seq[Expression], okUInt: Boolean, okSInt: Boolean, okClock: Boolean, okFix: Boolean, okAsync: Boolean): Unit = { + exprs.foldLeft((false, false, false, false, false)) { + case ((isUInt, isSInt, isClock, isFix, isAsync), expr) => expr.tpe match { + case u: UIntType => (true, isSInt, isClock, isFix, isAsync) + case s: SIntType => (isUInt, true, isClock, isFix, isAsync) + case ClockType => (isUInt, isSInt, true, isFix, isAsync) + case f: FixedType => (isUInt, isSInt, isClock, true, isAsync) + case AsyncResetType => (isUInt, isSInt, isClock, isFix, true) + case UnknownType => errors.append(new IllegalUnknownType(info, mname, e.serialize)) - (isUInt, isSInt, isClock, isFix) + (isUInt, isSInt, isClock, isFix, isAsync) case other => throwInternalError(s"Illegal Type: ${other.serialize}") } } match { // (UInt, SInt, Clock, Fixed) - case (isAll, false, false, false) if isAll == okUInt => - case (false, isAll, false, false) if isAll == okSInt => - case (false, false, isAll, false) if isAll == okClock => - case (false, false, false, isAll) if isAll == okFix => + case (isAll, false, false, false, false) if isAll == okUInt => + case (false, isAll, false, false, false) if isAll == okSInt => + case (false, false, isAll, false, false) if isAll == okClock => + case (false, false, false, isAll, false) if isAll == okFix => + case (false, false, false, false, isAll) if isAll == okAsync => case x => errors.append(new OpNotCorrectType(info, mname, e.op.serialize, exprs.map(_.tpe.serialize))) } } e.op match { - case AsUInt | AsSInt | AsClock | AsFixedPoint => + case AsUInt | AsSInt | AsClock | AsFixedPoint | AsAsyncReset => // All types are ok case Dshl | Dshr => - checkAllTypes(Seq(e.args.head), okUInt=true, okSInt=true, okClock=false, okFix=true) - checkAllTypes(Seq(e.args(1)), okUInt=true, okSInt=false, okClock=false, okFix=false) + checkAllTypes(Seq(e.args.head), okUInt=true, okSInt=true, okClock=false, okFix=true, okAsync=false) + checkAllTypes(Seq(e.args(1)), okUInt=true, okSInt=false, okClock=false, okFix=false, okAsync=false) case Add | Sub | Mul | Lt | Leq | Gt | Geq | Eq | Neq => - checkAllTypes(e.args, okUInt=true, okSInt=true, okClock=false, okFix=true) + checkAllTypes(e.args, okUInt=true, okSInt=true, okClock=false, okFix=true, okAsync=false) case Pad | Shl | Shr | Cat | Bits | Head | Tail => - checkAllTypes(e.args, okUInt=true, okSInt=true, okClock=false, okFix=true) + checkAllTypes(e.args, okUInt=true, okSInt=true, okClock=false, okFix=true, okAsync=false) case BPShl | BPShr | BPSet => - checkAllTypes(e.args, okUInt=false, okSInt=false, okClock=false, okFix=true) + checkAllTypes(e.args, okUInt=false, okSInt=false, okClock=false, okFix=true, okAsync=false) case _ => - checkAllTypes(e.args, okUInt=true, okSInt=true, okClock=false, okFix=false) + checkAllTypes(e.args, okUInt=true, okSInt=true, okClock=false, okFix=false, okAsync=false) } } @@ -415,6 +426,7 @@ object CheckTypes extends Pass { } sx.reset.tpe match { case UIntType(IntWidth(w)) if w == 1 => + case AsyncResetType => case UIntType(UnknownWidth) => // cannot catch here, though width may ultimately be wrong case _ => errors.append(new IllegalResetType(info, mname, sx.name)) } diff --git a/src/main/scala/firrtl/passes/InferWidths.scala b/src/main/scala/firrtl/passes/InferWidths.scala index 6420c3a2..6652c1fe 100644 --- a/src/main/scala/firrtl/passes/InferWidths.scala +++ b/src/main/scala/firrtl/passes/InferWidths.scala @@ -228,6 +228,7 @@ object InferWidths extends Pass { case (t1: UIntType, t2: UIntType) => Seq(WGeq(t1.width, t2.width)) case (t1: SIntType, t2: SIntType) => Seq(WGeq(t1.width, t2.width)) case (ClockType, ClockType) => Nil + case (AsyncResetType, AsyncResetType) => Nil case (FixedType(w1, p1), FixedType(w2, p2)) => Seq(WGeq(w1,w2), WGeq(p1,p2)) case (AnalogType(w1), AnalogType(w2)) => Seq(WGeq(w1,w2), WGeq(w2,w1)) case (t1: BundleType, t2: BundleType) => @@ -282,10 +283,13 @@ object InferWidths extends Pass { case Flip => get_constraints_t(expx.tpe, locx.tpe)//WGeq(getWidth(expx), getWidth(locx)) } }) - case (s: DefRegister) => v ++= ( - get_constraints_t(s.reset.tpe, UIntType(IntWidth(1))) ++ - get_constraints_t(UIntType(IntWidth(1)), s.reset.tpe) ++ - get_constraints_t(s.tpe, s.init.tpe)) + case (s: DefRegister) => + if (s.reset.tpe != AsyncResetType ) { + v ++= ( + get_constraints_t(s.reset.tpe, UIntType(IntWidth(1))) ++ + get_constraints_t(UIntType(IntWidth(1)), s.reset.tpe)) + } + v ++= get_constraints_t(s.tpe, s.init.tpe) case (s:Conditionally) => v ++= get_constraints_t(s.pred.tpe, UIntType(IntWidth(1))) ++ get_constraints_t(UIntType(IntWidth(1)), s.pred.tpe) |
