aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/firrtl/Emitter.scala33
-rw-r--r--src/main/scala/firrtl/Serialize.scala30
-rw-r--r--src/main/scala/firrtl/Utils.scala2
-rw-r--r--src/main/scala/firrtl/passes/Checks.scala125
-rw-r--r--src/main/scala/firrtl/passes/LowerTypes.scala2
-rw-r--r--src/main/scala/firrtl/passes/Passes.scala85
-rw-r--r--src/test/scala/firrtlTests/CheckSpec.scala2
-rw-r--r--src/test/scala/firrtlTests/IntegrationSpec.scala3
-rw-r--r--src/test/scala/firrtlTests/UnitTests.scala4
9 files changed, 145 insertions, 141 deletions
diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala
index 5414053a..eb4cd9b8 100644
--- a/src/main/scala/firrtl/Emitter.scala
+++ b/src/main/scala/firrtl/Emitter.scala
@@ -55,10 +55,11 @@ object FIRRTLEmitter extends Emitter {
}
case class VIndent()
-case class VRandom()
+case object VRandom extends Expression {
+ def tpe = UIntType(UnknownWidth())
+}
class VerilogEmitter extends Emitter {
val tab = " "
- val ran = VRandom()
var w:Option[Writer] = None
var mname = ""
def wref (n:String,t:Type) = WRef(n,t,ExpKind(),UNKNOWNGENDER)
@@ -72,7 +73,7 @@ class VerilogEmitter extends Emitter {
def emit (x:Any) = emit2(x,0)
def emit2 (x:Any, top:Int) : Unit = {
def cast (e:Expression) : Any = {
- (tpe(e)) match {
+ e.tpe match {
case (t:UIntType) => e
case (t:SIntType) => Seq("$signed(",e,")")
case (t:ClockType) => e
@@ -89,6 +90,8 @@ class VerilogEmitter extends Emitter {
case (e:WSubAccess) => w.get.write(LowerTypes.loweredName(e.exp) + "[" + LowerTypes.loweredName(e.index) + "]")
case (e:WSubIndex) => w.get.write(e.serialize)
case (_:UIntValue|_:SIntValue) => v_print(e)
+ case VRandom => w.get.write("$random")
+
}
}
case (t:Type) => {
@@ -113,7 +116,6 @@ class VerilogEmitter extends Emitter {
case (i:Int) => w.get.write(i.toString)
case (i:Long) => w.get.write(i.toString)
case (t:VIndent) => w.get.write(" ")
- case (r:VRandom) => w.get.write("$random")
case (s:Seq[Any]) => {
s.foreach((x:Any) => emit2(x.as[Any].get, top + 1))
if (top == 0) w.get.write("\n")
@@ -308,6 +310,14 @@ class VerilogEmitter extends Emitter {
}
def assign (e:Expression,value:Expression) =
assigns += Seq("assign ",e," = ",value,";")
+ // Like assign but with different versions for synthesis and simulation
+ def synSimAssign(e: Expression, syn: Expression, sim: Expression) = {
+ assigns += Seq("`ifdef SYNTHESIS")
+ assigns += Seq("assign ", e, " = ", syn, ";")
+ assigns += Seq("`else")
+ assigns += Seq("assign ", e, " = ", sim, ";")
+ assigns += Seq("`endif")
+ }
def update_and_reset(r: Expression, clk: Expression, reset: Expression, init: Expression) = {
def addUpdate(e: Expression, tabs: String): Seq[Seq[Any]] = {
e match {
@@ -349,7 +359,7 @@ class VerilogEmitter extends Emitter {
val nx = namespace.newTemp
val wx = ((long_BANG(t) + 31) / 32).toInt
val tx = SIntType(IntWidth(wx * 32))
- val rand = Seq("{",wx.toString,"{",ran,"}}")
+ val rand = Seq("{",wx.toString,"{",VRandom,"}}")
declare("reg",nx,tx)
initials += Seq(wref(nx,tx)," = ",rand,";")
Seq(nx,"[",long_BANG(t) - 1,":0]")
@@ -486,7 +496,10 @@ class VerilogEmitter extends Emitter {
val addrx = delay(addr,s.read_latency,clk)
val enx = delay(en,s.read_latency,clk)
val mem_port = WSubAccess(mem,addrx,s.data_type,UNKNOWNGENDER)
- assign(data,mem_port)
+ val depthValue = UIntValue(s.depth, IntWidth(BigInt(s.depth).bitLength))
+ val garbageGuard = DoPrim(GREATER_EQ_OP, Seq(addrx, depthValue), Seq(), UnknownType())
+ val garbageMux = Mux(garbageGuard, VRandom, mem_port, UnknownType())
+ synSimAssign(data, mem_port, garbageMux)
}
for (w <- s.writers ) {
@@ -554,7 +567,13 @@ class VerilogEmitter extends Emitter {
val rmem_port = WSubAccess(mem,raddrx,s.data_type,UNKNOWNGENDER)
assign(rdata,rmem_port)
val wmem_port = WSubAccess(mem,waddrx,s.data_type,UNKNOWNGENDER)
- update(wmem_port,datax,clk,AND(AND(enx,maskx),wmode))
+
+ val tempName = namespace.newTemp
+ val tempExp = AND(enx,maskx)
+ declare("wire", tempName, tpe(tempExp))
+ val tempWRef = wref(tempName, tpe(tempExp))
+ assign(tempWRef, tempExp)
+ update(wmem_port,datax,clk,AND(tempWRef,wmode))
}
}
case (s:Begin) => s map (build_streams)
diff --git a/src/main/scala/firrtl/Serialize.scala b/src/main/scala/firrtl/Serialize.scala
index 0229bb57..1735c270 100644
--- a/src/main/scala/firrtl/Serialize.scala
+++ b/src/main/scala/firrtl/Serialize.scala
@@ -31,25 +31,29 @@ import firrtl.PrimOps._
import firrtl.Utils._
private object Serialize {
-
def serialize(root: AST): String = {
+ lazy val ser = new Serialize
root match {
- case r: PrimOp => serialize(r)
- case r: Expression => serialize(r)
- case r: Stmt => serialize(r)
- case r: Width => serialize(r)
- case r: Flip => serialize(r)
- case r: Field => serialize(r)
- case r: Type => serialize(r)
- case r: Direction => serialize(r)
- case r: Port => serialize(r)
- case r: Module => serialize(r)
- case r: Circuit => serialize(r)
- case r: StringLit => serialize(r)
+ case r: PrimOp => ser.serialize(r)
+ case r: Expression => ser.serialize(r)
+ case r: Stmt => ser.serialize(r)
+ case r: Width => ser.serialize(r)
+ case r: Flip => ser.serialize(r)
+ case r: Field => ser.serialize(r)
+ case r: Type => ser.serialize(r)
+ case r: Direction => ser.serialize(r)
+ case r: Port => ser.serialize(r)
+ case r: Module => ser.serialize(r)
+ case r: Circuit => ser.serialize(r)
+ case r: StringLit => ser.serialize(r)
case _ => throw new Exception("serialize called on unknown AST node!")
}
}
+ /** Creates new instance of Serialize */
+ def apply() = new Serialize
+}
+class Serialize {
def serialize(bi: BigInt): String =
if (bi < BigInt(0)) "\"h" + bi.toString(16).substring(1) + "\""
else "\"h" + bi.toString(16) + "\""
diff --git a/src/main/scala/firrtl/Utils.scala b/src/main/scala/firrtl/Utils.scala
index 98edaf4b..a2ca3103 100644
--- a/src/main/scala/firrtl/Utils.scala
+++ b/src/main/scala/firrtl/Utils.scala
@@ -630,7 +630,7 @@ object Utils extends LazyLogging {
case decl: IsDeclaration => if (decl.name == name) Some(decl) else None
case c: Conditionally =>
val m = (getRootDecl(name)(c.conseq), getRootDecl(name)(c.alt))
- m match {
+ (m: @unchecked) match {
case (Some(decl), None) => Some(decl)
case (None, Some(decl)) => Some(decl)
case (None, None) => None
diff --git a/src/main/scala/firrtl/passes/Checks.scala b/src/main/scala/firrtl/passes/Checks.scala
index 618c0e99..23613e65 100644
--- a/src/main/scala/firrtl/passes/Checks.scala
+++ b/src/main/scala/firrtl/passes/Checks.scala
@@ -45,7 +45,6 @@ object CheckHighForm extends Pass with LazyLogging {
// Custom Exceptions
class NotUniqueException(name: String) extends PassException(s"${sinfo}: [module ${mname}] Reference ${name} does not have a unique name.")
- class IsPrefixException(prefix: String) extends PassException(s"${sinfo}: [module ${mname}] Symbol ${prefix} is a prefix.")
class InvalidLOCException extends PassException(s"${sinfo}: [module ${mname}] Invalid connect to an expression that is not a reference or a WritePort.")
class NegUIntException extends PassException(s"${sinfo}: [module ${mname}] UIntValue cannot be negative.")
class UndeclaredReferenceException(name: String) extends PassException(s"${sinfo}: [module ${mname}] Reference ${name} is not declared.")
@@ -63,35 +62,6 @@ object CheckHighForm extends Pass with LazyLogging {
class BadPrintfTrailingException extends PassException(s"${sinfo}: [module ${mname}] Bad printf format: trailing " + "\"%\"")
class BadPrintfIncorrectNumException extends PassException(s"${sinfo}: [module ${mname}] Bad printf format: incorrect number of arguments")
- // Trie Datastructure for prefix checking
- case class Trie(var children: HashMap[String, Trie], var end: Boolean) {
- def empty: Boolean = children.isEmpty
- def add(ls: Seq[String]): Boolean = {
- var t: Trie = this
- var sawEnd = false
- for (x <- ls) {
- if (t.end) sawEnd = true
- if (t.contains(x)) t = t.children(x)
- else {
- val temp = new Trie(HashMap[String,Trie](),false)
- t.children(x) = temp
- t = temp
- }
- }
- t.end = true
- sawEnd | !t.empty
- }
- def contains(s: String): Boolean = children.contains(s)
- def contains(ls: Seq[String]): Boolean = {
- var t: Trie = this
- for (x <- ls) {
- if (t.contains(x)) t = t.children(x)
- else return false
- }
- t.end
- }
- }
-
// Utility functions
def hasFlip(t: Type): Boolean = {
var has = false
@@ -116,7 +86,7 @@ object CheckHighForm extends Pass with LazyLogging {
private var mname: String = ""
private var sinfo: Info = NoInfo
def run (c:Circuit): Circuit = {
- val errors = ArrayBuffer[PassException]()
+ val errors = new Errors()
def checkHighFormPrimop(e: DoPrim) = {
def correctNum(ne: Option[Int], nc: Int) = {
ne match {
@@ -202,7 +172,6 @@ object CheckHighForm extends Pass with LazyLogging {
def checkHighFormM(m: Module): Module = {
val names = HashMap[String, Boolean]()
val mnames = HashMap[String, Boolean]()
- val tries = Trie(HashMap[String, Trie](),false)
def checkHighFormE(e: Expression): Expression = {
def validSubexp(e: Expression): Expression = {
e match {
@@ -232,8 +201,6 @@ object CheckHighForm extends Pass with LazyLogging {
def checkName(name: String): String = {
if (names.contains(name)) errors.append(new NotUniqueException(name))
else names(name) = true
- val ls: Seq[String] = name.split('$')
- if (tries.add(ls)) errors.append(new IsPrefixException(name))
name
}
sinfo = s.getInfo
@@ -289,7 +256,7 @@ object CheckHighForm extends Pass with LazyLogging {
}
sinfo = c.info
if (numTopM != 1) errors.append(new NoTopModuleException(c.main))
- if (errors.nonEmpty) throw new PassExceptions(errors)
+ errors.trigger
c
}
}
@@ -306,7 +273,7 @@ object CheckTypes extends Pass with LazyLogging {
class AccessIndexNotUInt(info:Info) extends PassException(s"${info}: [module ${mname}] Access index must be a UInt type.")
class IndexNotUInt(info:Info) extends PassException(s"${info}: [module ${mname}] Index is not of UIntType.")
class EnableNotUInt(info:Info) extends PassException(s"${info}: [module ${mname}] Enable is not of UIntType.")
- class InvalidConnect(info:Info) extends PassException(s"${info}: [module ${mname}] Type mismatch.")
+ class InvalidConnect(info:Info, lhs:String, rhs:String) extends PassException(s"${info}: [module ${mname}] Type mismatch. Cannot connect ${lhs} to ${rhs}.")
class InvalidRegInit(info:Info) extends PassException(s"${info}: [module ${mname}] Type of init must match type of DefRegister.")
class PrintfArgNotGround(info:Info) extends PassException(s"${info}: [module ${mname}] Printf arguments must be either UIntType or SIntType.")
class ReqClk(info:Info) extends PassException(s"${info}: [module ${mname}] Requires a clock typed signal.")
@@ -326,32 +293,32 @@ object CheckTypes extends Pass with LazyLogging {
def ut () : UIntType = UIntType(UnknownWidth())
def st () : SIntType = SIntType(UnknownWidth())
- def check_types_primop (e:DoPrim, errors:ArrayBuffer[PassException],info:Info) : Unit = {
+ def check_types_primop (e:DoPrim, errors:Errors, info:Info) : Unit = {
def all_same_type (ls:Seq[Expression]) : Unit = {
var error = false
for (x <- ls) {
if (wt(tpe(ls.head)) != wt(tpe(x))) error = true
}
- if (error) errors += new OpNotAllSameType(info,e.op.serialize)
+ if (error) errors.append(new OpNotAllSameType(info,e.op.serialize))
}
def all_ground (ls:Seq[Expression]) : Unit = {
var error = false
for (x <- ls ) {
if (!(tpe(x).typeof[UIntType] || tpe(x).typeof[SIntType])) error = true
}
- if (error) errors += new OpNotGround(info,e.op.serialize)
+ if (error) errors.append(new OpNotGround(info,e.op.serialize))
}
def all_uint (ls:Seq[Expression]) : Unit = {
var error = false
for (x <- ls ) {
if (!(tpe(x).typeof[UIntType])) error = true
}
- if (error) errors += new OpNotAllUInt(info,e.op.serialize)
+ if (error) errors.append(new OpNotAllUInt(info,e.op.serialize))
}
def is_uint (x:Expression) : Unit = {
var error = false
if (!(tpe(x).typeof[UIntType])) error = true
- if (error) errors += new OpNotUInt(info,e.op.serialize,x.serialize)
+ if (error) errors.append(new OpNotUInt(info,e.op.serialize,x.serialize))
}
e.op match {
@@ -391,7 +358,7 @@ object CheckTypes extends Pass with LazyLogging {
}
def run (c:Circuit) : Circuit = {
- val errors = ArrayBuffer[PassException]()
+ val errors = new Errors()
def passive (t:Type) : Boolean = {
(t) match {
case (_:UIntType|_:SIntType) => true
@@ -414,39 +381,39 @@ object CheckTypes extends Pass with LazyLogging {
(tpe(e.exp)) match {
case (t:BundleType) => {
val ft = t.fields.find(p => p.name == e.name)
- if (ft == None) errors += new SubfieldNotInBundle(info,e.name)
+ if (ft == None) errors.append(new SubfieldNotInBundle(info,e.name))
}
- case (t) => errors += new SubfieldOnNonBundle(info,e.name)
+ case (t) => errors.append(new SubfieldOnNonBundle(info,e.name))
}
}
case (e:WSubIndex) => {
(tpe(e.exp)) match {
case (t:VectorType) => {
- if (e.value >= t.size) errors += new IndexTooLarge(info,e.value)
+ if (e.value >= t.size) errors.append(new IndexTooLarge(info,e.value))
}
- case (t) => errors += new IndexOnNonVector(info)
+ case (t) => errors.append(new IndexOnNonVector(info))
}
}
case (e:WSubAccess) => {
(tpe(e.exp)) match {
case (t:VectorType) => false
- case (t) => errors += new IndexOnNonVector(info)
+ case (t) => errors.append(new IndexOnNonVector(info))
}
(tpe(e.index)) match {
case (t:UIntType) => false
- case (t) => errors += new AccessIndexNotUInt(info)
+ case (t) => errors.append(new AccessIndexNotUInt(info))
}
}
case (e:DoPrim) => check_types_primop(e,errors,info)
case (e:Mux) => {
- if (wt(tpe(e.tval)) != wt(tpe(e.fval))) errors += new MuxSameType(info)
- if (!passive(tpe(e))) errors += new MuxPassiveTypes(info)
- if (!passive(tpe(e))) errors += new MuxPassiveTypes(info)
- if (!(tpe(e.cond).typeof[UIntType])) errors += new MuxCondUInt(info)
+ if (wt(tpe(e.tval)) != wt(tpe(e.fval))) errors.append(new MuxSameType(info))
+ if (!passive(tpe(e))) errors.append(new MuxPassiveTypes(info))
+ if (!passive(tpe(e))) errors.append(new MuxPassiveTypes(info))
+ if (!(tpe(e.cond).typeof[UIntType])) errors.append(new MuxCondUInt(info))
}
case (e:ValidIf) => {
- if (!passive(tpe(e))) errors += new ValidIfPassiveTypes(info)
- if (!(tpe(e.cond).typeof[UIntType])) errors += new ValidIfCondUInt(info)
+ if (!passive(tpe(e))) errors.append(new ValidIfPassiveTypes(info))
+ if (!(tpe(e.cond).typeof[UIntType])) errors.append(new ValidIfCondUInt(info))
}
case (_:UIntValue|_:SIntValue) => false
}
@@ -479,22 +446,22 @@ object CheckTypes extends Pass with LazyLogging {
def check_types_s (s:Stmt) : Stmt = {
s map (check_types_e(get_info(s))) match {
- case (s:Connect) => if (wt(tpe(s.loc)) != wt(tpe(s.exp))) errors += new InvalidConnect(s.info)
- case (s:DefRegister) => if (wt(s.tpe) != wt(tpe(s.init))) errors += new InvalidRegInit(s.info)
- case (s:BulkConnect) => if (!bulk_equals(tpe(s.loc),tpe(s.exp),DEFAULT,DEFAULT) ) errors += new InvalidConnect(s.info)
+ case (s:Connect) => if (wt(tpe(s.loc)) != wt(tpe(s.exp))) errors.append(new InvalidConnect(s.info, s.loc.serialize, s.exp.serialize))
+ case (s:DefRegister) => if (wt(s.tpe) != wt(tpe(s.init))) errors.append(new InvalidRegInit(s.info))
+ case (s:BulkConnect) => if (!bulk_equals(tpe(s.loc),tpe(s.exp),DEFAULT,DEFAULT) ) errors.append(new InvalidConnect(s.info, s.loc.serialize, s.exp.serialize))
case (s:Stop) => {
- if (wt(tpe(s.clk)) != wt(ClockType()) ) errors += new ReqClk(s.info)
- if (wt(tpe(s.en)) != wt(ut()) ) errors += new EnNotUInt(s.info)
+ if (wt(tpe(s.clk)) != wt(ClockType()) ) errors.append(new ReqClk(s.info))
+ if (wt(tpe(s.en)) != wt(ut()) ) errors.append(new EnNotUInt(s.info))
}
case (s:Print)=> {
for (x <- s.args ) {
- if (wt(tpe(x)) != wt(ut()) && wt(tpe(x)) != wt(st()) ) errors += new PrintfArgNotGround(s.info)
+ if (wt(tpe(x)) != wt(ut()) && wt(tpe(x)) != wt(st()) ) errors.append(new PrintfArgNotGround(s.info))
}
- if (wt(tpe(s.clk)) != wt(ClockType()) ) errors += new ReqClk(s.info)
- if (wt(tpe(s.en)) != wt(ut()) ) errors += new EnNotUInt(s.info)
+ if (wt(tpe(s.clk)) != wt(ClockType()) ) errors.append(new ReqClk(s.info))
+ if (wt(tpe(s.en)) != wt(ut()) ) errors.append(new EnNotUInt(s.info))
}
- case (s:Conditionally) => if (wt(tpe(s.pred)) != wt(ut()) ) errors += new PredNotUInt(s.info)
- case (s:DefNode) => if (!passive(tpe(s.value)) ) errors += new NodePassiveType(s.info)
+ case (s:Conditionally) => if (wt(tpe(s.pred)) != wt(ut()) ) errors.append(new PredNotUInt(s.info))
+ case (s:DefNode) => if (!passive(tpe(s.value)) ) errors.append(new NodePassiveType(s.info))
case (s) => false
}
s map (check_types_s)
@@ -507,7 +474,7 @@ object CheckTypes extends Pass with LazyLogging {
case (m:InModule) => check_types_s(m.body)
}
}
- if (errors.nonEmpty) throw new PassExceptions(errors)
+ errors.trigger
c
}
}
@@ -534,7 +501,7 @@ object CheckGenders extends Pass {
}
def run (c:Circuit): Circuit = {
- val errors = ArrayBuffer[PassException]()
+ val errors = new Errors()
def get_kind (e:Expression) : Kind = {
(e) match {
case (e:WRef) => e.kind
@@ -574,14 +541,14 @@ object CheckGenders extends Pass {
//println(desired == gender)
//if gender != desired and gender != BI-GENDER:
(gender,desired) match {
- case (MALE, FEMALE) => errors += new WrongGender(info,e.serialize,as_srcsnk(desired),as_srcsnk(gender))
+ case (MALE, FEMALE) => errors.append(new WrongGender(info,e.serialize,as_srcsnk(desired),as_srcsnk(gender)))
case (FEMALE, MALE) =>
if ((kindx == PortKind() || kindx == InstanceKind()) && has_flipQ == false) {
//; OK!
false
} else {
//; Not Ok!
- errors += new WrongGender(info,e.serialize,as_srcsnk(desired),as_srcsnk(gender))
+ errors.append(new WrongGender(info,e.serialize,as_srcsnk(desired),as_srcsnk(gender)))
}
case _ => false
}
@@ -672,7 +639,7 @@ object CheckGenders extends Pass {
case (m:InModule) => check_genders_s(genders)(m.body)
}
}
- if (errors.nonEmpty) throw new PassExceptions(errors)
+ errors.trigger
c
}
}
@@ -681,15 +648,17 @@ object CheckWidths extends Pass {
def name = "Width Check"
var mname = ""
class UninferredWidth (info:Info) extends PassException(s"${info} : [module ${mname}] Uninferred width.")
- class WidthTooSmall (info:Info,v:String) extends PassException(s"${info} : [module ${mname} Width too small for constant ${v}.")
+ class WidthTooSmall(info: Info, b: BigInt) extends PassException(
+ s"$info : [module $mname] Width too small for constant " +
+ Serialize().serialize(b) + ".")
class NegWidthException(info:Info) extends PassException(s"${info}: [module ${mname}] Width cannot be negative or zero.")
def run (c:Circuit): Circuit = {
- val errors = ArrayBuffer[PassException]()
+ val errors = new Errors()
def check_width_m (m:Module) : Unit = {
def check_width_w (info:Info)(w:Width) : Width = {
(w) match {
- case (w:IntWidth)=> if (w.width <= 0) errors += new NegWidthException(info)
- case (w) => errors += new UninferredWidth(info)
+ case (w:IntWidth)=> if (w.width <= 0) errors.append(new NegWidthException(info))
+ case (w) => errors.append(new UninferredWidth(info))
}
w
}
@@ -699,17 +668,17 @@ object CheckWidths extends Pass {
(e.width) match {
case (w:IntWidth) =>
if (scala.math.max(1,e.value.bitLength) > w.width) {
- errors += new WidthTooSmall(info, serialize(e.value))
+ errors.append(new WidthTooSmall(info, e.value))
}
- case (w) => errors += new UninferredWidth(info)
+ case (w) => errors.append(new UninferredWidth(info))
}
check_width_w(info)(e.width)
}
case (e:SIntValue) => {
(e.width) match {
case (w:IntWidth) =>
- if (e.value.bitLength + 1 > w.width) errors += new WidthTooSmall(info, serialize(e.value))
- case (w) => errors += new UninferredWidth(info)
+ if (e.value.bitLength + 1 > w.width) errors.append(new WidthTooSmall(info, e.value))
+ case (w) => errors.append(new UninferredWidth(info))
}
check_width_w(info)(e.width)
}
@@ -738,7 +707,7 @@ object CheckWidths extends Pass {
mname = m.name
check_width_m(m)
}
- if (errors.nonEmpty) throw new PassExceptions(errors)
+ errors.trigger
c
}
}
diff --git a/src/main/scala/firrtl/passes/LowerTypes.scala b/src/main/scala/firrtl/passes/LowerTypes.scala
index 2caa2ce2..1dc3f782 100644
--- a/src/main/scala/firrtl/passes/LowerTypes.scala
+++ b/src/main/scala/firrtl/passes/LowerTypes.scala
@@ -100,7 +100,7 @@ object LowerTypes extends Pass {
def lowerTypesMemExp(e: Expression): Seq[Expression] = {
val (mem, port, field, tail) = splitMemRef(e)
// Fields that need to be replicated for each resulting mem
- if (Seq("addr", "en", "clk", "rmode").contains(field.name)) {
+ if (Seq("addr", "en", "clk", "wmode").contains(field.name)) {
require(tail.isEmpty) // there can't be a tail for these
val memType = memDataTypeMap(mem.name)
diff --git a/src/main/scala/firrtl/passes/Passes.scala b/src/main/scala/firrtl/passes/Passes.scala
index bc11bc9d..abd758bf 100644
--- a/src/main/scala/firrtl/passes/Passes.scala
+++ b/src/main/scala/firrtl/passes/Passes.scala
@@ -50,6 +50,17 @@ trait Pass extends LazyLogging {
// Error handling
class PassException(message: String) extends Exception(message)
class PassExceptions(exceptions: Seq[PassException]) extends Exception("\n" + exceptions.mkString("\n"))
+class Errors {
+ val errors = ArrayBuffer[PassException]()
+ def append(pe: PassException) = errors.append(pe)
+ def trigger = errors.size match {
+ case 0 =>
+ case 1 => throw errors.head
+ case _ =>
+ append(new PassException(s"${errors.length} errors detected!"))
+ throw new PassExceptions(errors)
+ }
+}
// These should be distributed into separate files
object ToWorkingIR extends Pass {
@@ -471,47 +482,47 @@ object InferWidths extends Pass {
case (t:ClockType) => IntWidth(1)
case (t) => error("No width!"); IntWidth(-1) } }
def width_BANG (e:Expression) : Width = width_BANG(tpe(e))
- def reduce_var_widths (c:Circuit,h:LinkedHashMap[String,Width]) : Circuit = {
- def evaluate (w:Width) : Width = {
- def apply_2 (a:Option[BigInt],b:Option[BigInt], f: (BigInt,BigInt) => BigInt) : Option[BigInt] = {
- (a,b) match {
- case (a:Some[BigInt],b:Some[BigInt]) => Some(f(a.get,b.get))
- case (a,b) => None } }
- def apply_1 (a:Option[BigInt], f: (BigInt) => BigInt) : Option[BigInt] = {
- (a) match {
- case (a:Some[BigInt]) => Some(f(a.get))
- case (a) => None } }
- def apply_l (l:Seq[Option[BigInt]],f:(BigInt,BigInt) => BigInt) : Option[BigInt] = {
- if (l.size == 0) Some(BigInt(0)) else apply_2(l.head,apply_l(l.tail,f),f)
- }
- def max (a:BigInt,b:BigInt) : BigInt = if (a >= b) a else b
- def min (a:BigInt,b:BigInt) : BigInt = if (a >= b) b else a
- def pow (a:BigInt,b:BigInt) : BigInt = BigInt((scala.math.pow(a.toDouble,b.toDouble) - 1).toLong)
- def solve (w:Width) : Option[BigInt] = {
- (w) match {
- case (w:VarWidth) => {
- val wx = h.get(w.name)
- (wx) match {
- case (wx:Some[Width]) => {
- wx.get match {
- case (v:VarWidth) => None
- case (v) => solve(v) }}
- case (None) => None }}
- case (w:MaxWidth) => apply_l(w.args.map(solve _),max)
- case (w:MinWidth) => apply_l(w.args.map(solve _),min)
- case (w:PlusWidth) => apply_2(solve(w.arg1),solve(w.arg2),{_ + _})
- case (w:MinusWidth) => apply_2(solve(w.arg1),solve(w.arg2),{_ - _})
- case (w:ExpWidth) => apply_2(Some(BigInt(2)),solve(w.arg1),pow)
- case (w:IntWidth) => Some(w.width)
- case (w) => println(w); error("Shouldn't be here"); None;
- }
+
+ def reduce_var_widths(c: Circuit, h: LinkedHashMap[String,Width]): Circuit = {
+ def evaluate(w: Width): Width = {
+ def map2(a: Option[BigInt], b: Option[BigInt], f: (BigInt,BigInt) => BigInt): Option[BigInt] =
+ for (a_num <- a; b_num <- b) yield f(a_num, b_num)
+ def reduceOptions(l: Seq[Option[BigInt]], f: (BigInt,BigInt) => BigInt): Option[BigInt] =
+ l.reduce(map2(_, _, f))
+
+ // This function shouldn't be necessary
+ // Added as protection in case a constraint accidentally uses MinWidth/MaxWidth
+ // without any actual Widths. This should be elevated to an earlier error
+ def forceNonEmpty(in: Seq[Option[BigInt]], default: Option[BigInt]): Seq[Option[BigInt]] =
+ if(in.isEmpty) Seq(default)
+ else in
+
+ def max(a: BigInt, b: BigInt): BigInt = if (a >= b) a else b
+ def min(a: BigInt, b: BigInt): BigInt = if (a >= b) b else a
+ def pow_minus_one(a: BigInt, b: BigInt): BigInt = a.pow(b.toInt) - 1
+
+ def solve(w: Width): Option[BigInt] = w match {
+ case (w: VarWidth) =>
+ for{
+ v <- h.get(w.name) if !v.isInstanceOf[VarWidth]
+ result <- solve(v)
+ } yield result
+ case (w: MaxWidth) => reduceOptions(forceNonEmpty(w.args.map(solve _), Some(BigInt(0))), max)
+ case (w: MinWidth) => reduceOptions(forceNonEmpty(w.args.map(solve _), None), min)
+ case (w: PlusWidth) => map2(solve(w.arg1), solve(w.arg2), {_ + _})
+ case (w: MinusWidth) => map2(solve(w.arg1), solve(w.arg2), {_ - _})
+ case (w: ExpWidth) => map2(Some(BigInt(2)), solve(w.arg1), pow_minus_one)
+ case (w: IntWidth) => Some(w.width)
+ case (w) => println(w); error("Shouldn't be here"); None;
}
+
val s = solve(w)
(s) match {
- case (s:Some[BigInt]) => IntWidth(s.get)
- case (s) => w }
+ case Some(s) => IntWidth(s)
+ case (s) => w
+ }
}
-
+
def reduce_var_widths_w (w:Width) : Width = {
//println-all-debug(["REPLACE: " w])
val wx = evaluate(w)
diff --git a/src/test/scala/firrtlTests/CheckSpec.scala b/src/test/scala/firrtlTests/CheckSpec.scala
index ea0767bb..5c1b1a67 100644
--- a/src/test/scala/firrtlTests/CheckSpec.scala
+++ b/src/test/scala/firrtlTests/CheckSpec.scala
@@ -19,7 +19,7 @@ class CheckSpec extends FlatSpec with Matchers {
| depth => 32
| read-latency => 0
| write-latency => 1""".stripMargin
- intercept[PassExceptions] {
+ intercept[CheckHighForm.MemWithFlipException] {
passes.foldLeft(Parser.parse(input.split("\n").toIterator)) {
(c: Circuit, p: Pass) => p.run(c)
}
diff --git a/src/test/scala/firrtlTests/IntegrationSpec.scala b/src/test/scala/firrtlTests/IntegrationSpec.scala
index 13e289d5..df4104a8 100644
--- a/src/test/scala/firrtlTests/IntegrationSpec.scala
+++ b/src/test/scala/firrtlTests/IntegrationSpec.scala
@@ -35,7 +35,8 @@ class IntegrationSpec extends FirrtlPropSpec {
case class Test(name: String, dir: String)
val runTests = Seq(Test("GCDTester", "/integration"),
- Test("RightShiftTester", "/integration"))
+ Test("RightShiftTester", "/integration"),
+ Test("MemTester", "/integration"))
runTests foreach { test =>
diff --git a/src/test/scala/firrtlTests/UnitTests.scala b/src/test/scala/firrtlTests/UnitTests.scala
index cee2c15d..98693c61 100644
--- a/src/test/scala/firrtlTests/UnitTests.scala
+++ b/src/test/scala/firrtlTests/UnitTests.scala
@@ -60,7 +60,7 @@ class UnitTests extends FirrtlFlatSpec {
| input y: {a : UInt<1>}
| output x: {a : UInt<1>, b : UInt<1>}
| x <= y""".stripMargin
- intercept[PassExceptions] {
+ intercept[CheckTypes.InvalidConnect] {
passes.foldLeft(parse(input)) {
(c: Circuit, p: Pass) => p.run(c)
}
@@ -82,7 +82,7 @@ class UnitTests extends FirrtlFlatSpec {
| wire x : { valid : UInt<1> }
| reg y : { valid : UInt<1>, bits : UInt<3> }, clk with :
| reset => (reset, x)""".stripMargin
- intercept[PassExceptions] {
+ intercept[CheckTypes.InvalidRegInit] {
passes.foldLeft(parse(input)) {
(c: Circuit, p: Pass) => p.run(c)
}