aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/passes
diff options
context:
space:
mode:
authorJack Koenig2019-02-14 15:08:35 -0800
committerGitHub2019-02-14 15:08:35 -0800
commit2272044c6ab46b5148c39c124e66e1a8e9073a24 (patch)
tree83ad2141b1a3c54707dd9b33073f9217b0ae16c8 /src/main/scala/firrtl/passes
parentd487b4cb6726e7e8d1a18f894021652594125221 (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.scala1
-rw-r--r--src/main/scala/firrtl/passes/Checks.scala54
-rw-r--r--src/main/scala/firrtl/passes/InferWidths.scala12
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)