aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorazidar2016-02-09 14:48:12 -0800
committerazidar2016-02-09 18:57:08 -0800
commitbb5f68948c6d75d1f02c614f3e0ae4ef9bc6e689 (patch)
tree0ac38af05f64eb454d2c0925f34f5dae53d41f61 /src
parent57473f4c6a9f35752bb71fc7b8d6b54471aeaa07 (diff)
Added remaining check passes. Ready for open sourcing
Diffstat (limited to 'src')
-rw-r--r--src/main/antlr4/FIRRTL.g43
-rw-r--r--src/main/scala/firrtl/Compiler.scala6
-rw-r--r--src/main/scala/firrtl/Utils.scala11
-rw-r--r--src/main/scala/firrtl/Visitor.scala7
-rw-r--r--src/main/scala/firrtl/passes/Checks.scala280
-rw-r--r--src/main/scala/firrtl/passes/Passes.scala6
6 files changed, 164 insertions, 149 deletions
diff --git a/src/main/antlr4/FIRRTL.g4 b/src/main/antlr4/FIRRTL.g4
index 59de36dd..e3e662ac 100644
--- a/src/main/antlr4/FIRRTL.g4
+++ b/src/main/antlr4/FIRRTL.g4
@@ -16,6 +16,7 @@ circuit
module
: 'module' id ':' '{' port* block '}'
+ | 'extmodule' id ':' '{' port* '}'
;
port
@@ -106,6 +107,7 @@ id
keyword
: 'circuit'
| 'module'
+ | 'extmodule'
| 'input'
| 'output'
| 'UInt'
@@ -140,6 +142,7 @@ keyword
| 'mux'
| 'validif'
| 'write'
+ | 'with'
| 'read'
| 'rdwr'
| 'infer'
diff --git a/src/main/scala/firrtl/Compiler.scala b/src/main/scala/firrtl/Compiler.scala
index 78ea644d..5c6b76ae 100644
--- a/src/main/scala/firrtl/Compiler.scala
+++ b/src/main/scala/firrtl/Compiler.scala
@@ -27,15 +27,19 @@ object VerilogCompiler extends Compiler {
CInferMDir,
RemoveCHIRRTL,
ToWorkingIR,
+ CheckHighForm,
ResolveKinds,
InferTypes,
+ CheckTypes,
ResolveGenders,
+ CheckGenders,
InferWidths,
+ CheckWidths,
PullMuxes,
ExpandConnects,
RemoveAccesses,
ExpandWhens,
- //CheckInitialization,
+ CheckInitialization,
ConstProp,
ResolveKinds,
InferTypes,
diff --git a/src/main/scala/firrtl/Utils.scala b/src/main/scala/firrtl/Utils.scala
index 546ba17b..afd73bf0 100644
--- a/src/main/scala/firrtl/Utils.scala
+++ b/src/main/scala/firrtl/Utils.scala
@@ -580,7 +580,7 @@ object Utils {
case s:IsInvalid => s.info
case s:Stop => s.info
case s:Print => s.info
- case _ => error("Shouldn't be here"); NoInfo
+ case _ => NoInfo
}}
@@ -1034,6 +1034,15 @@ object Utils {
s ++= debug(m)
s.toString
}
+ case m:ExModule => {
+ var s = new StringBuilder(s"extmodule ${m.name} : ")
+ withIndent {
+ s ++= m.ports.map(newline ++ _.serialize).mkString
+ s ++= newline
+ }
+ s ++= debug(m)
+ s.toString
+ }
}
}
}
diff --git a/src/main/scala/firrtl/Visitor.scala b/src/main/scala/firrtl/Visitor.scala
index 76759687..3fe8c176 100644
--- a/src/main/scala/firrtl/Visitor.scala
+++ b/src/main/scala/firrtl/Visitor.scala
@@ -57,7 +57,10 @@ class Visitor(val fullFilename: String) extends FIRRTLBaseVisitor[AST]
Circuit(getInfo(ctx), ctx.module.map(visitModule), (ctx.id.getText))
private def visitModule[AST](ctx: FIRRTLParser.ModuleContext): Module =
- InModule(getInfo(ctx), (ctx.id.getText), ctx.port.map(visitPort), visitBlock(ctx.block))
+ ctx.getChild(0).getText match {
+ case "module" => InModule(getInfo(ctx), (ctx.id.getText), ctx.port.map(visitPort), visitBlock(ctx.block))
+ case "extmodule" => ExModule(getInfo(ctx), (ctx.id.getText), ctx.port.map(visitPort))
+ }
private def visitPort[AST](ctx: FIRRTLParser.PortContext): Port =
Port(getInfo(ctx), (ctx.id.getText), visitDir(ctx.dir), visitType(ctx.`type`))
@@ -206,7 +209,7 @@ class Visitor(val fullFilename: String) extends FIRRTLBaseVisitor[AST]
(IntWidth(string2BigInt(ctx.IntLit(0).getText)), string2BigInt(ctx.IntLit(1).getText))
else {
val bigint = string2BigInt(ctx.IntLit(0).getText)
- (IntWidth(BigInt(bigint.bitLength)),bigint)
+ (IntWidth(BigInt(scala.math.max(bigint.bitLength,1))),bigint)
}
UIntValue(value, width)
}
diff --git a/src/main/scala/firrtl/passes/Checks.scala b/src/main/scala/firrtl/passes/Checks.scala
index e8d8b112..4e3f8577 100644
--- a/src/main/scala/firrtl/passes/Checks.scala
+++ b/src/main/scala/firrtl/passes/Checks.scala
@@ -180,7 +180,7 @@ object CheckHighForm extends Pass with LazyLogging {
def checkHighFormE(e: Expression): Expression = {
def validSubexp(e: Expression): Expression = {
e match {
- case e @ (_: WRef | _: WSubField | _: WSubIndex | _: WSubAccess | _: Mux | _: ValidIf) => // No error
+ case (_:WRef|_:WSubField|_:WSubIndex|_:WSubAccess|_:Mux|_:ValidIf) => {} // No error
case _ => errors.append(new InvalidAccessException)
}
e
@@ -189,6 +189,7 @@ object CheckHighForm extends Pass with LazyLogging {
case e: WRef =>
if (!names.contains(e.name)) errors.append(new UndeclaredReferenceException(e.name))
case e: DoPrim => checkHighFormPrimop(e)
+ case (_:Mux|_:ValidIf) => {}
case e: WSubAccess => {
validSubexp(e.exp)
e
@@ -482,19 +483,19 @@ object CheckTypes extends Pass with LazyLogging {
}
}
-/*
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}.")
+ var mname = ""
+ 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 = {
+ def dir_to_gender (d:Direction) : Gender = {
d match {
case INPUT => MALE
case OUTPUT => FEMALE //BI-GENDER
}
}
- def as-srcsnk (g:Gender) : String = {
+ def as_srcsnk (g:Gender) : String = {
g match {
case MALE => "source"
case FEMALE => "sink"
@@ -505,38 +506,38 @@ object CheckGenders extends Pass {
def run (c:Circuit): Circuit = {
val errors = ArrayBuffer[PassException]()
- def get-kind (e:Expression) : Kind = {
+ 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: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 check_gender (info:Info,genders:HashMap[String,Gender],desired:Gender)(e:Expression) : Expression = {
+ 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 =
+ 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))
+ flip_rec(field.tpe,times(f, field.flip))
}
}
- case (t:VectorType) => flip-rec(t.tpe,f)
+ case (t:VectorType) => flip_rec(t.tpe,f)
case (t) => if (f == REVERSE) fQ = true
}
t
}
- flip-rec(t,DEFAULT)
+ flip_rec(t,DEFAULT)
fQ
}
- val has-flipQ = flipQ(tpe(e))
+ val has_flipQ = flipQ(tpe(e))
//println(e)
//println(gender)
//println(desired)
@@ -544,27 +545,28 @@ object CheckGenders extends Pass {
//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 (MALE, FEMALE) => errors += new WrongGender(info,e.serialize(),as_srcsnk(desired),as_srcsnk(gender))
case (FEMALE, MALE) =>
- if ((kindx == PortKind() or kindx == InstanceKind()) && has-flipQ == false) {
+ if ((kindx == PortKind() || kindx == InstanceKind()) && has_flipQ == false) {
//; OK!
false
} else {
//; Not Ok!
- add(errors,WrongGender(info,to-symbol(e),as-srcsnk(desired),as-srcsnk(gender)))
+ errors += new WrongGender(info,e.serialize(),as_srcsnk(desired),as_srcsnk(gender))
}
case _ => false
}
+ e
}
- def get-gender (e:Expression,genders:HashMap[String,Gender]) : Gender = {
+ 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)
+ val f = tpe(e.exp).as[BundleType].get.fields.find(f => f.name == e.name).get
+ 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
@@ -573,59 +575,57 @@ object CheckGenders extends Pass {
}
}
- def check-genders-e (info:Info,genders:HashMap[String,Gender])(e:Expression) : Expression = {
- eMap(check-genders-e(info,genders) _,e)
+ 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:DoPrim) => for (e <- e.args ) { 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)
+ 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)
+ 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)
+ 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)(x)
}
- check-gender(s.info,genders,MALE)(s.en)
- check-gender(s.info,genders,MALE)(s.clk)
+ 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)
+ 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)
+ 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)
+ check_gender(s.info,genders,MALE)(s.en)
+ check_gender(s.info,genders,MALE)(s.clk)
}
case (_:Begin|_:IsInvalid) => false
}
@@ -636,11 +636,11 @@ object CheckGenders extends Pass {
mname = m.name
val genders = HashMap[String,Gender]()
for (p <- m.ports) {
- genders(p.name) = dir-to-gender(p.direction)
+ genders(p.name) = dir_to_gender(p.direction)
}
(m) match {
case (m:ExModule) => false
- case (m:InModule) => check-genders-s(genders)(m.body)
+ case (m:InModule) => check_genders_s(genders)(m.body)
}
}
if (errors.nonEmpty) throw new PassExceptions(errors)
@@ -650,121 +650,117 @@ object CheckGenders extends Pass {
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 =
+ 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 NegWidthException(info:Info) extends PassException(s"${info}: [module ${mname}] Width cannot be negative or zero.")
+ def run (c:Circuit): Circuit = {
val errors = ArrayBuffer[PassException]()
-
- def check-width-m (m:Module) : Unit =
- def check-width-w (info:Info,w:Width) : Width =
+ 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))
+ case (w:IntWidth)=> if (w.width <= 0) errors += new NegWidthException(info)
+ case (w) => errors += new 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)))
+ }
+ def check_width_e (info:Info)(e:Expression) : Expression = {
+ (eMap(check_width_e(info) _,e)) match {
+ case (e:UIntValue) => {
+ (e.width) match {
+ case (w:IntWidth) =>
+ if (scala.math.max(1,e.value.bitLength) > w.width) {
+ errors += new WidthTooSmall(info,e.value.serialize())
+ }
+ case (w) => errors += 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,e.value.serialize())
+ case (w) => errors += new UninferredWidth(info)
+ }
+ check_width_w(info)(e.width)
+ }
+ case (e:DoPrim) => false
+ case (e) => false
+ }
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)
+ }
+ def check_width_s (s:Stmt) : Stmt = {
+ eMap(check_width_e(get_info(s)) _,sMap(check_width_s _,s))
+ def tm (t:Type) : Type = mapr(check_width_w(info(s)) _,t)
+ tMap(tm _,s)
+ }
- for p in ports(m) do :
- mapr(check-width-w{info(p),_},type(p))
+ for (p <- m.ports) {
+ mapr(check_width_w(p.info) _,p.tpe)
+ }
(m) match {
- (m:ExModule) : false
- (m:InModule) : check-width-s(body(m))
- false
+ case (m:ExModule) => {}
+ case (m:InModule) => check_width_s(m.body)
+ }
+ }
- for m in modules(c) do :
- mname = name(m)
- check-width-m(m)
- throw(PassExceptions(errors)) when not empty?(errors)
+ for (m <- c.modules) {
+ mname = m.name
+ check_width_m(m)
+ }
+ if (errors.nonEmpty) throw new PassExceptions(errors)
c
}
}
object CheckInitialization extends Pass with StanzaPass {
def name = "Check Initialization"
+ var mname = ""
+ class RefNotInitialized (info:Info, name:String) extends PassException(s"${info} : [module ${mname} Reference ${name} is not fully initialized.")
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 =
+ def check_init_m (m:InModule) : Unit = {
+ 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 =
+ case (e:WRef) => e.name
+ case (e:WSubField) => get_name(e.exp) + "." + e.name
+ case (e:WSubIndex) => get_name(e.exp) + "[" + e.value + "]"
+ case (e) => error("Shouldn't be here"); ""
+ }
+ }
+ def has_voidQ (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 =
+ case (e:WVoid) => void = true; e
+ case (e) => eMap(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))))
+ case (s:Connect) => {
+ if (has_voidQ(s.exp)) errors += new RefNotInitialized(s.info,get_name(s.loc))
s
- (s) : map(check-init-s,s)
-
- check-init-s(body(m))
+ }
+ case (s) => sMap(check_init_s,s)
+ }
+ }
+ check_init_s(m.body)
+ }
- for m in modules(c) do :
- mname = name(m)
+ for (m <- c.modules) {
+ mname = m.name
(m) match {
- (m:InModule) : check-init-m(m)
- (m) : false
-
- throw(PassExceptions(errors)) when not empty?(errors)
- c
+ case (m:InModule) => check_init_m(m)
+ case (m) => false
+ }
+ }
+
+ if (errors.nonEmpty) throw new PassExceptions(errors)
+ c
}
}
-*/
diff --git a/src/main/scala/firrtl/passes/Passes.scala b/src/main/scala/firrtl/passes/Passes.scala
index 452b994f..18217445 100644
--- a/src/main/scala/firrtl/passes/Passes.scala
+++ b/src/main/scala/firrtl/passes/Passes.scala
@@ -24,7 +24,7 @@ trait Pass extends LazyLogging {
// Error handling
class PassException(message: String) extends Exception(message)
-class PassExceptions(exceptions: Seq[PassException]) extends Exception(exceptions.mkString("\n"))
+class PassExceptions(exceptions: Seq[PassException]) extends Exception("\n" + exceptions.mkString("\n"))
// Trait for migration, trap to Stanza implementation for passes not yet implemented in Scala
trait StanzaPass extends LazyLogging {
@@ -53,13 +53,13 @@ object PassUtils extends LazyLogging {
lazy val mapNameToPass: Map[String, Pass] = listOfPasses.map(p => p.name -> p).toMap
def executePasses(c: Circuit, passes: Seq[Pass]): Circuit = {
- if (passes.isEmpty) c
+ if (passes.isEmpty) {logger.debug(s"Done!"); c}
else {
val p = passes.head
val name = p.name
logger.debug(s"Starting ${name}")
val x = p.run(c)
- //logger.debug(x.serialize())
+ logger.debug(x.serialize())
logger.debug(s"Finished ${name}")
executePasses(x, passes.tail)
}