From bb5f68948c6d75d1f02c614f3e0ae4ef9bc6e689 Mon Sep 17 00:00:00 2001 From: azidar Date: Tue, 9 Feb 2016 14:48:12 -0800 Subject: Added remaining check passes. Ready for open sourcing --- Makefile | 4 +- src/main/antlr4/FIRRTL.g4 | 3 + src/main/scala/firrtl/Compiler.scala | 6 +- src/main/scala/firrtl/Utils.scala | 11 +- src/main/scala/firrtl/Visitor.scala | 7 +- src/main/scala/firrtl/passes/Checks.scala | 280 +++++++++++++++--------------- src/main/scala/firrtl/passes/Passes.scala | 6 +- test/features/Stop.fir | 4 +- test/parser/dshl.fir | 14 ++ test/parser/mux.fir | 14 ++ 10 files changed, 196 insertions(+), 153 deletions(-) create mode 100644 test/parser/dshl.fir create mode 100644 test/parser/mux.fir diff --git a/Makefile b/Makefile index 94ac0598..e299abcb 100644 --- a/Makefile +++ b/Makefile @@ -53,7 +53,7 @@ build-fast: make set-stanza check: - cd $(test_dir) && lit -v . --path=$(root_dir)/utils/bin/ + cd $(test_dir) && lit -j 2 -v . --path=$(root_dir)/utils/bin/ regress: cd $(regress_dir) && firrtl -i rocket.fir -o rocket.v -X verilog @@ -77,7 +77,7 @@ errors: cd $(test_dir)/errors && lit -v . --path=$(root_dir)/utils/bin/ features: - cd $(test_dir)/features && lit -v . --path=$(root_dir)/utils/bin/ + cd $(test_dir)/features && lit -j 2 -v . --path=$(root_dir)/utils/bin/ chirrtl: cd $(test_dir)/chirrtl && lit -v . --path=$(root_dir)/utils/bin/ 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) } diff --git a/test/features/Stop.fir b/test/features/Stop.fir index bef64f0f..888da3d7 100644 --- a/test/features/Stop.fir +++ b/test/features/Stop.fir @@ -13,8 +13,8 @@ circuit Top : stop(clk,UInt(1),1) stop(clk,UInt(1),3) -;CHECK: stop(clk, and(p, UInt<1>("h1")), 0) -;CHECK: stop(clk, and(q, UInt<1>("h1")), 1) +;CHECK: stop(clk, p, 0) +;CHECK: stop(clk, q, 1) ;CHECK: stop(clk, UInt<1>("h1"), 3) ;CHECK: Done! diff --git a/test/parser/dshl.fir b/test/parser/dshl.fir new file mode 100644 index 00000000..99a6ec7d --- /dev/null +++ b/test/parser/dshl.fir @@ -0,0 +1,14 @@ +; RUN: firrtl -i %s -o %s.out -X firrtl && cat %s.out | FileCheck %s +circuit GCD : + module GCD : + input a : UInt<63> + input b : UInt<63> + input sign : UInt<1> + output d : UInt + ;wire T_205 : UInt + node T_203 = UInt<6>("h3f") + node normCount = not(T_203) + node absIn = mux(sign, a, b) + node T_205 = dshl(absIn, normCount) + d <= T_205 + diff --git a/test/parser/mux.fir b/test/parser/mux.fir new file mode 100644 index 00000000..4705aa75 --- /dev/null +++ b/test/parser/mux.fir @@ -0,0 +1,14 @@ +; RUN: firrtl -i %s -o %s.out -X firrtl && cat %s.out | FileCheck %s +circuit GCD : + module GCD : + input e : UInt<1> + input f : UInt<1> + input g : UInt<1> + output o : UInt<1> + node y = f + node z = f + node x = mux(UInt<1>(0),y,z) + o <= x + + + -- cgit v1.2.3