diff options
| author | azidar | 2016-02-09 13:14:52 -0800 |
|---|---|---|
| committer | azidar | 2016-02-09 18:57:08 -0800 |
| commit | 57473f4c6a9f35752bb71fc7b8d6b54471aeaa07 (patch) | |
| tree | 9425ee401579fa3472cd4f2160f0a1258fee9361 /src | |
| parent | e63a058b04d428cd407528b0276cc0413b581be2 (diff) | |
CHIRRTL passes work, parser is updated
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/antlr4/FIRRTL.g4 | 14 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Emitter.scala | 4 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Utils.scala | 5 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Visitor.scala | 29 | ||||
| -rw-r--r-- | src/main/scala/firrtl/WIR.scala | 4 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/Checks.scala | 502 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/Passes.scala | 19 |
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 = "" |
