aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorazidar2016-02-09 13:14:52 -0800
committerazidar2016-02-09 18:57:08 -0800
commit57473f4c6a9f35752bb71fc7b8d6b54471aeaa07 (patch)
tree9425ee401579fa3472cd4f2160f0a1258fee9361 /src
parente63a058b04d428cd407528b0276cc0413b581be2 (diff)
CHIRRTL passes work, parser is updated
Diffstat (limited to 'src')
-rw-r--r--src/main/antlr4/FIRRTL.g414
-rw-r--r--src/main/scala/firrtl/Emitter.scala4
-rw-r--r--src/main/scala/firrtl/Utils.scala5
-rw-r--r--src/main/scala/firrtl/Visitor.scala29
-rw-r--r--src/main/scala/firrtl/WIR.scala4
-rw-r--r--src/main/scala/firrtl/passes/Checks.scala502
-rw-r--r--src/main/scala/firrtl/passes/Passes.scala19
7 files changed, 550 insertions, 27 deletions
diff --git a/src/main/antlr4/FIRRTL.g4 b/src/main/antlr4/FIRRTL.g4
index 6e6b972f..59de36dd 100644
--- a/src/main/antlr4/FIRRTL.g4
+++ b/src/main/antlr4/FIRRTL.g4
@@ -57,6 +57,9 @@ stmt
| 'readwriter' '=>' id
)*
'}'
+ | 'cmem' id ':' type
+ | 'smem' id ':' type
+ | mdir 'mport' id '=' id '[' exp ']' exp
| 'inst' id 'of' id
| 'node' id '=' exp
| exp '<=' exp
@@ -68,6 +71,13 @@ stmt
| 'skip'
;
+mdir
+ : 'infer'
+ | 'read'
+ | 'write'
+ | 'rdwr'
+ ;
+
ruw
: 'old'
| 'new'
@@ -129,6 +139,10 @@ keyword
| 'undefined'
| 'mux'
| 'validif'
+ | 'write'
+ | 'read'
+ | 'rdwr'
+ | 'infer'
;
// Parentheses are added as part of name because semantics require no space between primop and open parentheses
diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala
index 499ab6db..a3b42695 100644
--- a/src/main/scala/firrtl/Emitter.scala
+++ b/src/main/scala/firrtl/Emitter.scala
@@ -38,6 +38,7 @@ object VerilogEmitter extends Emitter {
var percent:Boolean = false
for (c <- s) {
if (c == '\n') sx += "\\n"
+ else if (c == '"') sx += '\\'.toString + '"'.toString
else {
if((c == 'x') && percent) sx += "h" else sx += c.toString
}
@@ -335,7 +336,8 @@ object VerilogEmitter extends Emitter {
Seq("$fdisplay(32'h80000002,\"",ret,"\");$finish;")
}
def printf (str:String,args:Seq[Expression]) : Seq[Any] = {
- val strx = (Seq(escape(str)) ++ args).reduce(Seq(_, ",", _))
+ val q = '"'.toString
+ val strx = (Seq(q + escape(str) + q) ++ args.map(x => escape(x.serialize()))).reduce(_ + "," + _)
Seq("$fwrite(32'h80000002,",strx,");")
}
def delay (e:Expression, n:Int, clk:Expression) : Expression = {
diff --git a/src/main/scala/firrtl/Utils.scala b/src/main/scala/firrtl/Utils.scala
index e4525560..546ba17b 100644
--- a/src/main/scala/firrtl/Utils.scala
+++ b/src/main/scala/firrtl/Utils.scala
@@ -875,8 +875,11 @@ object Utils {
}
case i: IsInvalid => s"${i.exp.serialize} is invalid"
case s: Stop => s"stop(${s.clk.serialize}, ${s.en.serialize}, ${s.ret})"
- case p: Print => s"printf(${p.clk.serialize}, ${p.en.serialize}, ${p.string}" +
+ case p: Print => {
+ val q = '"'.toString
+ s"printf(${p.clk.serialize}, ${p.en.serialize}, ${q}${p.string}${q}" +
(if (p.args.nonEmpty) p.args.map(_.serialize).mkString(", ", ", ", "") else "") + ")"
+ }
case s:Empty => "skip"
case s:CDefMemory => {
if (s.seq) s"smem ${s.name} : ${s.tpe} [${s.size}]"
diff --git a/src/main/scala/firrtl/Visitor.scala b/src/main/scala/firrtl/Visitor.scala
index f77a3f58..76759687 100644
--- a/src/main/scala/firrtl/Visitor.scala
+++ b/src/main/scala/firrtl/Visitor.scala
@@ -59,17 +59,23 @@ class Visitor(val fullFilename: String) extends FIRRTLBaseVisitor[AST]
private def visitModule[AST](ctx: FIRRTLParser.ModuleContext): Module =
InModule(getInfo(ctx), (ctx.id.getText), ctx.port.map(visitPort), visitBlock(ctx.block))
- private def visitPort[AST](ctx: FIRRTLParser.PortContext): Port =
+ private def visitPort[AST](ctx: FIRRTLParser.PortContext): Port =
Port(getInfo(ctx), (ctx.id.getText), visitDir(ctx.dir), visitType(ctx.`type`))
-
- private def visitDir[AST](ctx: FIRRTLParser.DirContext): Direction =
+ private def visitDir[AST](ctx: FIRRTLParser.DirContext): Direction =
ctx.getText match {
case "input" => INPUT
case "output" => OUTPUT
}
+ private def visitMdir[AST](ctx: FIRRTLParser.MdirContext): MPortDir =
+ ctx.getText match {
+ case "infer" => MInfer
+ case "read" => MRead
+ case "write" => MWrite
+ case "rdwr" => MReadWrite
+ }
// Match on a type instead of on strings?
- private def visitType[AST](ctx: FIRRTLParser.TypeContext): Type = {
+ private def visitType[AST](ctx: FIRRTLParser.TypeContext): Type = {
ctx.getChild(0) match {
case term: TerminalNode =>
term.getText match {
@@ -145,6 +151,20 @@ class Visitor(val fullFilename: String) extends FIRRTLBaseVisitor[AST]
DefRegister(info, name, tpe, visitExp(ctx.exp(0)), reset, init)
}
case "mem" => visitMem(ctx)
+ case "cmem" => {
+ val t = visitType(ctx.`type`(0))
+ t match {
+ case (t:VectorType) => CDefMemory(info,ctx.id(0).getText,t.tpe,t.size,false)
+ case _ => throw new ParserException(s"${info}: Must provide cmem with vector type")
+ }
+ }
+ case "smem" => {
+ val t = visitType(ctx.`type`(0))
+ t match {
+ case (t:VectorType) => CDefMemory(info,ctx.id(0).getText,t.tpe,t.size,true)
+ case _ => throw new ParserException(s"${info}: Must provide cmem with vector type")
+ }
+ }
case "inst" => DefInstance(info, (ctx.id(0).getText), (ctx.id(1).getText))
case "node" => DefNode(info, (ctx.id(0).getText), visitExp(ctx.exp(0)))
case "when" => {
@@ -162,6 +182,7 @@ class Visitor(val fullFilename: String) extends FIRRTLBaseVisitor[AST]
case "<=" => Connect(info, visitExp(ctx.exp(0)), visitExp(ctx.exp(1)) )
case "<-" => BulkConnect(info, visitExp(ctx.exp(0)), visitExp(ctx.exp(1)) )
case "is" => IsInvalid(info, visitExp(ctx.exp(0)))
+ case "mport" => CDefMPort(info, ctx.id(0).getText, UnknownType(),ctx.id(1).getText,Seq(visitExp(ctx.exp(0)),visitExp(ctx.exp(1))),visitMdir(ctx.mdir))
}
}
}
diff --git a/src/main/scala/firrtl/WIR.scala b/src/main/scala/firrtl/WIR.scala
index eaa4166b..61657879 100644
--- a/src/main/scala/firrtl/WIR.scala
+++ b/src/main/scala/firrtl/WIR.scala
@@ -190,6 +190,6 @@ case object MRead extends MPortDir
case object MWrite extends MPortDir
case object MReadWrite extends MPortDir
-case class CDefMemory (val info: FileInfo, val name: String, val tpe: Type, val size: Int, val seq: Boolean) extends Stmt
-case class CDefMPort (val info: FileInfo, val name: String, val tpe: Type, val mem: String, val exps: Seq[Expression], val direction: MPortDir) extends Stmt
+case class CDefMemory (val info: Info, val name: String, val tpe: Type, val size: Int, val seq: Boolean) extends Stmt
+case class CDefMPort (val info: Info, val name: String, val tpe: Type, val mem: String, val exps: Seq[Expression], val direction: MPortDir) extends Stmt
diff --git a/src/main/scala/firrtl/passes/Checks.scala b/src/main/scala/firrtl/passes/Checks.scala
index 50ede528..e8d8b112 100644
--- a/src/main/scala/firrtl/passes/Checks.scala
+++ b/src/main/scala/firrtl/passes/Checks.scala
@@ -10,6 +10,7 @@ import scala.collection.mutable.ArrayBuffer
import firrtl._
import firrtl.Utils._
import firrtl.PrimOps._
+import firrtl.WrappedType._
object CheckHighForm extends Pass with LazyLogging {
def name = "High Form Check"
@@ -266,3 +267,504 @@ object CheckHighForm extends Pass with LazyLogging {
}
}
+object CheckTypes extends Pass with LazyLogging {
+ def name = "Check Types"
+ var mname = ""
+
+ // Custom Exceptions
+ class SubfieldNotInBundle(info:Info, name:String) extends PassException(s"${info}: [module ${mname} ] Subfield ${name} is not in bundle.")
+ class SubfieldOnNonBundle(info:Info, name:String) extends PassException(s"${info}: [module ${mname}] Subfield ${name} is accessed on a non-bundle.")
+ class IndexTooLarge(info:Info, value:Int) extends PassException(s"${info}: [module ${mname}] Index with value ${value} is too large.")
+ class IndexOnNonVector(info:Info) extends PassException(s"${info}: [module ${mname}] Index illegal on non-vector type.")
+ 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 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.")
+ class EnNotUInt(info:Info) extends PassException(s"${info}: [module ${mname}] Enable must be a UIntType typed signal.")
+ class PredNotUInt(info:Info) extends PassException(s"${info}: [module ${mname}] Predicate not a UIntType.")
+ class OpNotGround(info:Info, op:String) extends PassException(s"${info}: [module ${mname}] Primop ${op} cannot operate on non-ground types.")
+ class OpNotUInt(info:Info, op:String,e:String) extends PassException(s"${info}: [module ${mname}] Primop ${op} requires argument ${e} to be a UInt type.")
+ class OpNotAllUInt(info:Info, op:String) extends PassException(s"${info}: [module ${mname}] Primop ${op} requires all arguments to be UInt type.")
+ class OpNotAllSameType(info:Info, op:String) extends PassException(s"${info}: [module ${mname}] Primop ${op} requires all operands to have the same type.")
+ class NodePassiveType(info:Info) extends PassException(s"${info}: [module ${mname}] Node must be a passive type.")
+ class MuxSameType(info:Info) extends PassException(s"${info}: [module ${mname}] Must mux between equivalent types.")
+ class MuxPassiveTypes(info:Info) extends PassException(s"${info}: [module ${mname}] Must mux between passive types.")
+ class MuxCondUInt(info:Info) extends PassException(s"${info}: [module ${mname}] A mux condition must be of type UInt.")
+ class ValidIfPassiveTypes(info:Info) extends PassException(s"${info}: [module ${mname}] Must validif a passive type.")
+ class ValidIfCondUInt(info:Info) extends PassException(s"${info}: [module ${mname}] A validif condition must be of type UInt.")
+ //;---------------- Helper Functions --------------
+ def ut () : UIntType = UIntType(UnknownWidth())
+ def st () : SIntType = SIntType(UnknownWidth())
+
+ def check_types_primop (e:DoPrim, errors:ArrayBuffer[PassException],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())
+ }
+ 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())
+ }
+ 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())
+ }
+ 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())
+ }
+
+ e.op match {
+ case AS_UINT_OP => {}
+ case AS_SINT_OP => {}
+ case AS_CLOCK_OP => {}
+ case DYN_SHIFT_LEFT_OP => is_uint(e.args(1)); all_ground(e.args)
+ case DYN_SHIFT_RIGHT_OP => is_uint(e.args(1)); all_ground(e.args)
+ case ADD_OP => all_ground(e.args)
+ case SUB_OP => all_ground(e.args)
+ case MUL_OP => all_ground(e.args)
+ case DIV_OP => all_ground(e.args)
+ case REM_OP => all_ground(e.args)
+ case LESS_OP => all_ground(e.args)
+ case LESS_EQ_OP => all_ground(e.args)
+ case GREATER_OP => all_ground(e.args)
+ case GREATER_EQ_OP => all_ground(e.args)
+ case EQUAL_OP => all_ground(e.args)
+ case NEQUAL_OP => all_ground(e.args)
+ case PAD_OP => all_ground(e.args)
+ case SHIFT_LEFT_OP => all_ground(e.args)
+ case SHIFT_RIGHT_OP => all_ground(e.args)
+ case CONVERT_OP => all_ground(e.args)
+ case NEG_OP => all_ground(e.args)
+ case NOT_OP => all_ground(e.args)
+ case AND_OP => all_ground(e.args)
+ case OR_OP => all_ground(e.args)
+ case XOR_OP => all_ground(e.args)
+ case AND_REDUCE_OP => all_ground(e.args)
+ case OR_REDUCE_OP => all_ground(e.args)
+ case XOR_REDUCE_OP => all_ground(e.args)
+ case CONCAT_OP => all_ground(e.args)
+ case BITS_SELECT_OP => all_ground(e.args)
+ case HEAD_OP => all_ground(e.args)
+ case TAIL_OP => all_ground(e.args)
+ }
+ }
+
+ def run (c:Circuit) : Circuit = {
+ val errors = ArrayBuffer[PassException]()
+ def passive (t:Type) : Boolean = {
+ (t) match {
+ case (_:UIntType|_:SIntType) => true
+ case (t:VectorType) => passive(t.tpe)
+ case (t:BundleType) => {
+ var p = true
+ for (x <- t.fields ) {
+ if (x.flip == REVERSE) p = false
+ if (!passive(x.tpe)) p = false
+ }
+ p
+ }
+ case (t) => true
+ }
+ }
+ def check_types_e (info:Info)(e:Expression) : Expression = {
+ (eMap(check_types_e(info) _,e)) match {
+ case (e:WRef) => e
+ case (e:WSubField) => {
+ (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)
+ }
+ case (t) => errors += 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)
+ }
+ case (t) => errors += new IndexOnNonVector(info)
+ }
+ }
+ case (e:WSubAccess) => {
+ (tpe(e.exp)) match {
+ case (t:VectorType) => false
+ case (t) => errors += new IndexOnNonVector(info)
+ }
+ (tpe(e.index)) match {
+ case (t:UIntType) => false
+ case (t) => errors += 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)
+ }
+ case (e:ValidIf) => {
+ if (!passive(tpe(e))) errors += new ValidIfPassiveTypes(info)
+ if (!(tpe(e.cond).typeof[UIntType])) errors += new ValidIfCondUInt(info)
+ }
+ case (_:UIntValue|_:SIntValue) => false
+ }
+ e
+ }
+
+ def bulk_equals (t1:Type,t2:Type) : Boolean = {
+ (t1,t2) match {
+ case (t1:BundleType,t2:BundleType) => {
+ var same = true
+ (t1.fields, t2.fields).zipped.map{ (f1,f2) => {
+ if (f1.name == f2.name) {
+ if (f1.flip != f2.flip) same = false
+ if (!bulk_equals(f1.tpe,f2.tpe)) same = false
+ }
+ }}
+ same
+ }
+ case (t1:ClockType,t2:ClockType) => true
+ case (t1:UIntType,t2:UIntType) => true
+ case (t1:SIntType,t2:SIntType) => true
+ case (t1:VectorType,t2:VectorType) => {
+ if (bulk_equals(t1.tpe,t2.tpe)) true
+ else false
+ }
+ case (t1,t2) => false
+ }
+ }
+
+ def check_types_s (s:Stmt) : Stmt = {
+ eMap(check_types_e(get_info(s)) _,s) match {
+ case (s:Connect) => if (wt(tpe(s.loc)) != wt(tpe(s.exp))) errors += new InvalidConnect(s.info)
+ case (s:BulkConnect) => if (!bulk_equals(tpe(s.loc),tpe(s.exp)) ) errors += new InvalidConnect(s.info)
+ 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)
+ }
+ 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(s.clk)) != wt(ClockType()) ) errors += new ReqClk(s.info)
+ if (wt(tpe(s.en)) != wt(ut()) ) errors += 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) => false
+ }
+ sMap(check_types_s,s)
+ }
+
+ for (m <- c.modules ) {
+ mname = m.name
+ (m) match {
+ case (m:ExModule) => false
+ case (m:InModule) => check_types_s(m.body)
+ }
+ }
+ if (errors.nonEmpty) throw new PassExceptions(errors)
+ c
+ }
+}
+
+/*
+object CheckGenders extends Pass {
+ def name = "Check Genders"
+ class WrongGender (info:Info,expr:String,wrong:String,right:String) extends PassException(s"${info}: [module ${mname} Expression ${expr} is used as a ${wrong} but can only be used as a ${right}.")
+
+ def dir-to-gender (d:Direction) : Gender = {
+ d match {
+ case INPUT => MALE
+ case OUTPUT => FEMALE //BI-GENDER
+ }
+ }
+
+ def as-srcsnk (g:Gender) : String = {
+ g match {
+ case MALE => "source"
+ case FEMALE => "sink"
+ case UNKNOWNGENDER => "unknown"
+ case BIGENDER => "sourceOrSink"
+ }
+ }
+
+ def run (c:Circuit): Circuit = {
+ val errors = ArrayBuffer[PassException]()
+ def get-kind (e:Expression) : Kind = {
+ (e) match {
+ case (e:WRef) => e.kind
+ case (e:WSubField) => get-kind(e.exp)
+ case (e:WSubIndex) => get-kind(e.exp)
+ case (e:WSubAccess) => get-kind(e.exp)
+ case (e) => NodeKind()
+ }
+ }
+
+ def check-gender (info:Info,genders:HashMap[String,Gender],desired:Gender)(e:Expression) : Unit = {
+ val gender = get-gender(e,genders)
+ val kindx = get-kind(e)
+ def flipQ (t:Type) : Boolean = {
+ var fQ = false
+ def flip-rec (t:Type,f:Flip) : Type =
+ (t) match {
+ case (t:BundleType) => {
+ for (field <- t.fields) {
+ flip-rec(field.tpe,times(f, field.flip))
+ }
+ }
+ case (t:VectorType) => flip-rec(t.tpe,f)
+ case (t) => if (f == REVERSE) fQ = true
+ }
+ t
+ }
+ flip-rec(t,DEFAULT)
+ fQ
+ }
+
+ val has-flipQ = flipQ(tpe(e))
+ //println(e)
+ //println(gender)
+ //println(desired)
+ //println(kindx)
+ //println(desired == gender)
+ //if gender != desired and gender != BI-GENDER:
+ (gender,desired) match {
+ case (MALE, FEMALE) => errors += WrongGender(info,e.serialize(),as-srcsnk(desired),as-srcsnk(gender))
+ case (FEMALE, MALE) =>
+ if ((kindx == PortKind() or kindx == InstanceKind()) && has-flipQ == false) {
+ //; OK!
+ false
+ } else {
+ //; Not Ok!
+ add(errors,WrongGender(info,to-symbol(e),as-srcsnk(desired),as-srcsnk(gender)))
+ }
+ case _ => false
+ }
+ }
+
+ def get-gender (e:Expression,genders:HashMap[String,Gender]) : Gender = {
+ (e) match {
+ case (e:WRef) => genders(e.name)
+ case (e:WSubField) =>
+ val f = tpe(e.exp).as[BundleType].get.fields.find(f => f.name == e.name)
+ times(get-gender(e.exp,genders),f.flip)
+ case (e:WSubIndex) => get-gender(e.exp,genders)
+ case (e:WSubAccess) => get-gender(e.exp,genders)
+ case (e:DoPrim) => MALE
+ case (e:UIntValue) => MALE
+ case (e:SIntValue) => MALE
+ case (e:Mux) => MALE
+ case (e:ValidIf) => MALE
+ }
+ }
+
+ def check-genders-e (info:Info,genders:HashMap[String,Gender])(e:Expression) : Expression = {
+ eMap(check-genders-e(info,genders) _,e)
+ (e) match {
+ case (e:WRef) => false
+ case (e:WSubField) => false
+ case (e:WSubIndex) => false
+ case (e:WSubAccess) => false
+ case (e:DoPrim) =>
+ for e in args(e) do :
+ check-gender(info,genders,MALE)(e)
+ case (e:Mux) => eMap(check-gender(info,genders,MALE) _,e)
+ case (e:ValidIf) => eMap(check-gender(info,genders,MALE) _,e)
+ case (e:UIntValue) => false
+ case (e:SIntValue) => false
+ }
+ e
+ }
+
+ def check-genders-s (genders:HashMap[String,Gender])(s:Stmt) : Stmt = {
+ eMap(check-genders-e(get_info(s),genders) _,s)
+ sMap(check-genders-s(genders) _,s)
+ (s) match {
+ case (s:DefWire) => genders(s.name) = BIGENDER
+ case (s:DefPoison) => genders(s.name) = MALE
+ case (s:DefRegister) => genders(s.name) = BIGENDER
+ case (s:DefNode) => {
+ check-gender(s.info,genders,MALE)(s.value)
+ genders(s.name) = MALE
+ }
+ case (s:DefMemory) => genders(s.name) = MALE
+ case (s:WDefInstance) => genders(s.name) = MALE
+ case (s:Connect) => {
+ check-gender(s.info,genders,FEMALE)(s.loc)
+ check-gender(s.info,genders,MALE)(s.exp)
+ }
+ case (s:Print) => {
+ for (x <- s.args ) {
+ check-gender(s.info,genders,MALE)(x)
+ }
+ check-gender(s.info,genders,MALE)(s.en)
+ check-gender(s.info,genders,MALE)(s.clk)
+ }
+ case (s:BulkConnect) => {
+ check-gender(s.info,genders,FEMALE)(s.loc)
+ check-gender(s.info,genders,MALE)(s.exp)
+ }
+ case (s:Conditionally) => {
+ check-gender(s.info,genders,MALE)(s.pred)
+ }
+ case (s:Empty) => false
+ case (s:Stop) => {
+ check-gender(s.info,genders,MALE)(s.en)
+ check-gender(s.info,genders,MALE)(s.clk)
+ }
+ case (_:Begin|_:IsInvalid) => false
+ }
+ s
+ }
+
+ for (m <- c.modules ) {
+ mname = m.name
+ val genders = HashMap[String,Gender]()
+ for (p <- m.ports) {
+ genders(p.name) = dir-to-gender(p.direction)
+ }
+ (m) match {
+ case (m:ExModule) => false
+ case (m:InModule) => check-genders-s(genders)(m.body)
+ }
+ }
+ if (errors.nonEmpty) throw new PassExceptions(errors)
+ c
+ }
+}
+
+object CheckWidths extends Pass with StanzaPass {
+ def name = "Width Check"
+ def run (c:Circuit): Circuit = stanzaPass(c, "width-check")
+ defn UninferredWidth (info:Info) :
+ PassException $ string-join $
+ [info ": [module " mname "] Uninferred width."]
+
+ defn WidthTooSmall (info:Info,v:String) :
+ PassException $ string-join $
+ [info ": [module " mname "] Width too small for constant " v "."]
+
+ ;---------------- Helper Functions --------------
+
+ ;--------------- Check Width Pass -------------------
+ public def check-width (c:Circuit) : Circuit =
+ val errors = ArrayBuffer[PassException]()
+
+ def check-width-m (m:Module) : Unit =
+ def check-width-w (info:Info,w:Width) : Width =
+ (w) match {
+ (w:IntWidth) :
+ if width(w) <= to-long(0) : add(errors,NegWidth())
+ (w) :
+ add(errors,UninferredWidth(info))
+ w
+
+ def check-width-e (info:Info,e:Expression) : Expression =
+ (map(check-width-e{info,_},e)) match {
+ (e:UIntValue) :
+ (width(e)) match {
+ (w:IntWidth) :
+ if max(to-long(1),to-long(req-num-bits(value(e)) - 1)) > width(w) :
+ add(errors,WidthTooSmall(info,to-string(value(e))))
+ (w) : add(errors,UninferredWidth(info))
+ check-width-w(info,width(e))
+ (e:SIntValue) :
+ (width(e)) match {
+ (w:IntWidth) :
+ if to-long(req-num-bits(value(e))) > width(w) :
+ add(errors,WidthTooSmall(info,to-string(value(e))))
+ (w) : add(errors,UninferredWidth(info))
+ check-width-w(info,width(e))
+ (e:DoPrim) : false
+ (e) : false
+
+ ;mapr(check-width-w{info,_},type(map(check-width-e{info,_},e)))
+ e
+
+ def check-width-s (s:Stmt) : Stmt =
+ sinfo! = info(s)
+ map(check-width-e{info(s),_},map(check-width-s,s))
+ map(mapr{check-width-w{info(s),_},_:Type},s)
+
+ for p in ports(m) do :
+ mapr(check-width-w{info(p),_},type(p))
+
+ (m) match {
+ (m:ExModule) : false
+ (m:InModule) : check-width-s(body(m))
+ false
+
+ for m in modules(c) do :
+ mname = name(m)
+ check-width-m(m)
+ throw(PassExceptions(errors)) when not empty?(errors)
+ c
+ }
+}
+
+object CheckInitialization extends Pass with StanzaPass {
+ def name = "Check Initialization"
+ def run (c:Circuit): Circuit = {
+ defn RefNotInitialized (info:Info, name:String) :
+ PassException $ string-join $
+ [info ": [module " mname "] Reference " name " is not fully initialized."]
+
+ ;------------ Helper Functions -------------
+
+ ;------------ Pass ------------------
+
+ public def check-init (c:Circuit) :
+ val errors = ArrayBuffer[PassException]()
+
+ def check-init-m (m:InModule) :
+ def get-name (e:Expression) : String =
+ (e) match {
+ (e:WRef) : name(e)
+ (e:WSubField) : symbol-join([get-name(exp(e)) `. name(e)])
+ (e:WSubIndex) : symbol-join([get-name(exp(e)) to-symbol("[") value(e) to-symbol("]")])
+ (e) : error("Shouldn't be here")
+ def has-void? (e:Expression) : Boolean =
+ var void? = false
+ def has-void (e:Expression) : Expression =
+ (e) match {
+ (e:WVoid) :
+ void? = true
+ e
+ (e) : map(has-void,e)
+ has-void(e)
+ void?
+ def check-init-s (s:Stmt) : Stmt =
+ (s) match {
+ (s:Connect) :
+ if has-void?(exp(s)) : add(errors,RefNotInitialized(info(s),get-name(loc(s))))
+ s
+ (s) : map(check-init-s,s)
+
+ check-init-s(body(m))
+
+ for m in modules(c) do :
+ mname = name(m)
+ (m) match {
+ (m:InModule) : check-init-m(m)
+ (m) : false
+
+ throw(PassExceptions(errors)) when not empty?(errors)
+ c
+ }
+}
+*/
diff --git a/src/main/scala/firrtl/passes/Passes.scala b/src/main/scala/firrtl/passes/Passes.scala
index de07aaab..452b994f 100644
--- a/src/main/scala/firrtl/passes/Passes.scala
+++ b/src/main/scala/firrtl/passes/Passes.scala
@@ -252,10 +252,6 @@ object InferTypes extends Pass {
Circuit(c.info,modulesx.map({m => mname = m.name; infer_types(m)}) , c.main )
}
}
-object CheckTypes extends Pass with StanzaPass {
- def name = "Check Types"
- def run (c:Circuit): Circuit = stanzaPass(c, "check-types")
-}
object ResolveGenders extends Pass {
private var mname = ""
@@ -320,11 +316,6 @@ object ResolveGenders extends Pass {
}
}
-object CheckGenders extends Pass with StanzaPass {
- def name = "Check Genders"
- def run (c:Circuit): Circuit = stanzaPass(c, "check-genders")
-}
-
object InferWidths extends Pass {
def name = "Infer Widths"
var mname = ""
@@ -623,11 +614,6 @@ object InferWidths extends Pass {
}
}
-object CheckWidths extends Pass with StanzaPass {
- def name = "Width Check"
- def run (c:Circuit): Circuit = stanzaPass(c, "width-check")
-}
-
object PullMuxes extends Pass {
private var mname = ""
def name = "Pull Muxes"
@@ -1114,11 +1100,6 @@ object ExpandWhens extends Pass {
}
}
-object CheckInitialization extends Pass with StanzaPass {
- def name = "Check Initialization"
- def run (c:Circuit): Circuit = stanzaPass(c, "check-init")
-}
-
object ConstProp extends Pass {
def name = "Constant Propogation"
var mname = ""