diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/antlr4/FIRRTL.g4 | 16 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Emitter.scala | 20 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Visitor.scala | 16 | ||||
| -rw-r--r-- | src/main/scala/firrtl/ir/IR.scala | 29 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/ConvertFixedToSInt.scala | 2 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/memlib/ReplaceMemMacros.scala | 2 | ||||
| -rw-r--r-- | src/test/resources/blackboxes/ParameterizedExtModule.v | 15 | ||||
| -rw-r--r-- | src/test/resources/blackboxes/ParameterizedExtModuleTester.fir | 40 | ||||
| -rw-r--r-- | src/test/resources/blackboxes/RenamedExtModuleTester.fir | 22 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/ExtModuleSpec.scala | 4 |
10 files changed, 157 insertions, 9 deletions
diff --git a/src/main/antlr4/FIRRTL.g4 b/src/main/antlr4/FIRRTL.g4 index 4ceed9f0..f4d9d3f8 100644 --- a/src/main/antlr4/FIRRTL.g4 +++ b/src/main/antlr4/FIRRTL.g4 @@ -63,7 +63,7 @@ circuit module : 'module' id ':' info? INDENT port* moduleBlock DEDENT - | 'extmodule' id ':' info? INDENT port* DEDENT + | 'extmodule' id ':' info? INDENT port* defname? parameter* DEDENT ; port @@ -89,6 +89,16 @@ field : 'flip'? id ':' type ; +defname + : 'defname' '=' id NEWLINE + ; + +parameter + : 'parameter' id '=' IntLit NEWLINE + | 'parameter' id '=' StringLit NEWLINE + | 'parameter' id '=' DoubleLit NEWLINE + ; + moduleBlock : simple_stmt* ; @@ -291,6 +301,10 @@ IntLit | '"' 'h' ( HexDigit )+ '"' ; +DoubleLit + : ( '+' | '-' )? Digit+ '.' Digit+ ( 'E' Digit+ )? + ; + fragment Nondigit : [a-zA-Z_] diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala index 405019b7..e3a146e2 100644 --- a/src/main/scala/firrtl/Emitter.scala +++ b/src/main/scala/firrtl/Emitter.scala @@ -82,6 +82,14 @@ class VerilogEmitter extends Emitter { } case _ => error("Shouldn't be here") } + /** Turn Params into Verilog Strings */ + def stringify(param: Param): String = param match { + case IntParam(name, value) => s".$name($value)" + case DoubleParam(name, value) => s".$name($value)" + case StringParam(name, value) => + val strx = "\"" + VerilogStringLitHandler.escape(value) + "\"" + s".${name}($strx)" + } def emit(x: Any)(implicit w: Writer) { emit(x, 0) } def emit(x: Any, top: Int)(implicit w: Writer) { def cast(e: Expression): Any = e.tpe match { @@ -237,7 +245,7 @@ class VerilogEmitter extends Emitter { } } - def emit_verilog(m: Module)(implicit w: Writer): DefModule = { + def emit_verilog(m: Module, moduleMap: Map[String, DefModule])(implicit w: Writer): DefModule = { val netlist = mutable.LinkedHashMap[WrappedExpression, Expression]() val addrRegs = mutable.HashSet[WrappedExpression]() val namespace = Namespace(m) @@ -448,8 +456,13 @@ class VerilogEmitter extends Emitter { simulate(sx.clk, sx.en, printf(sx.string, sx.args), Some("PRINTF_COND")) sx case sx: WDefInstanceConnector => + val (module, params) = moduleMap(sx.module) match { + case ExtModule(_, _, _, extname, params) => (extname, params) + case Module(_, name, _, _) => (name, Seq.empty) + } val es = create_exps(WRef(sx.name, sx.tpe, InstanceKind, MALE)) - instdeclares += Seq(sx.module, " ", sx.name, " (") + val ps = if (params.nonEmpty) params map stringify mkString ("#(", ", ", ") ") else "" + instdeclares += Seq(module, " ", ps, sx.name ," (") (es zip sx.exprs).zipWithIndex foreach {case ((l, r), i) => val s = Seq(tab, ".", remove_root(l), "(", r, ")") if (i != es.size - 1) instdeclares += Seq(s, ",") @@ -581,8 +594,9 @@ class VerilogEmitter extends Emitter { def run(c: Circuit, w: Writer) = { emit_preamble(w) + val moduleMap = (c.modules map (m => m.name -> m)).toMap c.modules foreach { - case (m: Module) => emit_verilog(m)(w) + case (m: Module) => emit_verilog(m, moduleMap)(w) case (m: ExtModule) => } } diff --git a/src/main/scala/firrtl/Visitor.scala b/src/main/scala/firrtl/Visitor.scala index d45283c6..03be0c4e 100644 --- a/src/main/scala/firrtl/Visitor.scala +++ b/src/main/scala/firrtl/Visitor.scala @@ -105,7 +105,11 @@ class Visitor(infoMode: InfoMode) extends FIRRTLBaseVisitor[FirrtlNode] { if (ctx.moduleBlock() != null) visitBlock(ctx.moduleBlock()) else EmptyStmt) - case "extmodule" => ExtModule(info, ctx.id.getText, ctx.port.map(visitPort)) + case "extmodule" => + val defname = if (ctx.defname != null) ctx.defname.id.getText else ctx.id.getText + val ports = ctx.port map visitPort + val params = ctx.parameter map visitParameter + ExtModule(info, ctx.id.getText, ports, defname, params) } } @@ -113,6 +117,16 @@ class Visitor(infoMode: InfoMode) extends FIRRTLBaseVisitor[FirrtlNode] { Port(visitInfo(Option(ctx.info), ctx), ctx.id.getText, visitDir(ctx.dir), visitType(ctx.`type`)) } + private def visitParameter[FirrtlNode](ctx: FIRRTLParser.ParameterContext): Param = { + val name = ctx.id.getText + (ctx.IntLit, ctx.StringLit, ctx.DoubleLit) match { + case (int, null, null) => IntParam(name, string2BigInt(int.getText)) + case (null, str, null) => StringParam(name, visitStringLit(str)) + case (null, null, dbl) => DoubleParam(name, dbl.getText.toDouble) + case _ => throw new Exception(s"Internal error: Visiting impossible parameter ${ctx.getText}") + } + } + private def visitDir[FirrtlNode](ctx: FIRRTLParser.DirContext): Direction = ctx.getText match { case "input" => Input diff --git a/src/main/scala/firrtl/ir/IR.scala b/src/main/scala/firrtl/ir/IR.scala index f5b80ac6..b9b31427 100644 --- a/src/main/scala/firrtl/ir/IR.scala +++ b/src/main/scala/firrtl/ir/IR.scala @@ -440,6 +440,24 @@ case class Port( def serialize: String = s"${direction.serialize} $name : ${tpe.serialize}" + info.serialize } +/** Parameters for external modules */ +sealed abstract class Param extends FirrtlNode { + def name: String + def serialize: String = s"parameter $name = " +} +/** Integer (of any width) Parameter */ +case class IntParam(name: String, value: BigInt) extends Param { + override def serialize: String = super.serialize + value +} +/** IEEE Double Precision Parameter (for Verilog real) */ +case class DoubleParam(name: String, value: Double) extends Param { + override def serialize: String = super.serialize + value +} +/** String Parameter */ +case class StringParam(name: String, value: StringLit) extends Param { + override def serialize: String = super.serialize + value.serialize +} + /** Base class for modules */ abstract class DefModule extends FirrtlNode with IsDeclaration { val info : Info @@ -464,9 +482,16 @@ case class Module(info: Info, name: String, ports: Seq[Port], body: Statement) e /** External Module * * Generally used for Verilog black boxes + * @param defname Defined name of the external module (ie. the name Firrtl will emit) */ -case class ExtModule(info: Info, name: String, ports: Seq[Port]) extends DefModule { - def serialize: String = serializeHeader("extmodule") +case class ExtModule( + info: Info, + name: String, + ports: Seq[Port], + defname: String, + params: Seq[Param]) extends DefModule { + def serialize: String = serializeHeader("extmodule") + + indent(s"\ndefname = $defname\n" + params.map(_.serialize).mkString("\n")) def mapStmt(f: Statement => Statement): DefModule = this def mapPort(f: Port => Port): DefModule = this.copy(ports = ports map f) def mapString(f: String => String): DefModule = this.copy(name = f(name)) diff --git a/src/main/scala/firrtl/passes/ConvertFixedToSInt.scala b/src/main/scala/firrtl/passes/ConvertFixedToSInt.scala index 8cf0b890..e334b94f 100644 --- a/src/main/scala/firrtl/passes/ConvertFixedToSInt.scala +++ b/src/main/scala/firrtl/passes/ConvertFixedToSInt.scala @@ -108,7 +108,7 @@ object ConvertFixedToSInt extends Pass { val newPorts = m.ports.map(p => Port(p.info,p.name,p.direction,toSIntType(p.tpe))) m match { case Module(info, name, ports, body) => Module(info,name,newPorts,body) - case ExtModule(info, name, ports) => ExtModule(info,name,newPorts) + case ext: ExtModule => ext.copy(ports = newPorts) } } newModules.foreach(m => moduleTypes(m.name) = module_type(m)) diff --git a/src/main/scala/firrtl/passes/memlib/ReplaceMemMacros.scala b/src/main/scala/firrtl/passes/memlib/ReplaceMemMacros.scala index 5fc99b9c..91e4efea 100644 --- a/src/main/scala/firrtl/passes/memlib/ReplaceMemMacros.scala +++ b/src/main/scala/firrtl/passes/memlib/ReplaceMemMacros.scala @@ -96,7 +96,7 @@ class ReplaceMemMacros(writer: ConfWriter) extends Pass { (m.writers flatMap (w => adaptWriter(portRef(w), createSubField(bbRef, w), hasMask, fillMask))) ++ (m.readwriters flatMap (rw => adaptReadWriter(portRef(rw), createSubField(bbRef, rw), hasMask, fillMask))) val wrapper = Module(NoInfo, wrapperName, wrapperIoPorts, Block(stmts)) - val bb = ExtModule(NoInfo, m.name, bbIoPorts) + val bb = ExtModule(NoInfo, m.name, bbIoPorts, m.name, Seq.empty) // TODO: Annotate? -- use actual annotation map // add to conf file diff --git a/src/test/resources/blackboxes/ParameterizedExtModule.v b/src/test/resources/blackboxes/ParameterizedExtModule.v new file mode 100644 index 00000000..ee6e3ec3 --- /dev/null +++ b/src/test/resources/blackboxes/ParameterizedExtModule.v @@ -0,0 +1,15 @@ + +module ParameterizedExtModule( + input [15:0] foo, + output [15:0] bar +); + parameter VALUE = 0; + parameter STRING = "one"; + parameter REAL = 1.0; + wire [15:0] fizz; + wire [15:0] buzz; + assign bar = foo + VALUE + fizz + buzz; + assign fizz = (STRING == "two")? 2 : (STRING == "one")? 1 : 0; + assign buzz = (REAL > 2.5E50)? 2 : (REAL < 0.0)? 1 : 0; +endmodule + diff --git a/src/test/resources/blackboxes/ParameterizedExtModuleTester.fir b/src/test/resources/blackboxes/ParameterizedExtModuleTester.fir new file mode 100644 index 00000000..29769e84 --- /dev/null +++ b/src/test/resources/blackboxes/ParameterizedExtModuleTester.fir @@ -0,0 +1,40 @@ +circuit ParameterizedExtModuleTester : + extmodule ParameterizedExtModule_1 : + input foo : UInt<16> + output bar : UInt<16> + + defname = ParameterizedExtModule + parameter VALUE = 1 + parameter STRING = "one" + parameter REAL = -1.7 + + extmodule ParameterizedExtModule_2 : + input foo : UInt<16> + output bar : UInt<16> + + defname = ParameterizedExtModule + parameter VALUE = 2 + parameter STRING = "two" + parameter REAL = 2.6E50 + + module ParameterizedExtModuleTester : + input clk : Clock + input reset : UInt<1> + + inst dut1 of ParameterizedExtModule_1 + inst dut2 of ParameterizedExtModule_2 + + dut1.foo <= UInt(1000) + dut2.foo <= UInt(1000) + + when not(reset) : + when neq(dut1.bar, UInt(1003)) : + printf(clk, not(reset), "Assertion failed\nTest Failed!\n") + stop(clk, not(reset), 1) + else : + when neq(dut2.bar, UInt(1006)) : + printf(clk, not(reset), "Assertion failed\nTest Failed!\n") + stop(clk, not(reset), 1) + else : + stop(clk, not(reset), 0) + diff --git a/src/test/resources/blackboxes/RenamedExtModuleTester.fir b/src/test/resources/blackboxes/RenamedExtModuleTester.fir new file mode 100644 index 00000000..48b0886c --- /dev/null +++ b/src/test/resources/blackboxes/RenamedExtModuleTester.fir @@ -0,0 +1,22 @@ +circuit RenamedExtModuleTester : + extmodule ThisIsJustTheFirrtlName : + input foo : UInt<16> + output bar : UInt<16> + + defname = SimpleExtModule + + module RenamedExtModuleTester : + input clk : Clock + input reset : UInt<1> + + inst dut of ThisIsJustTheFirrtlName + + dut.foo <= UInt(1234) + + when not(reset) : + when neq(dut.bar, UInt(1234)) : + printf(clk, not(reset), "Assertion failed\nTest Failed!\n") + stop(clk, not(reset), 1) + else : + stop(clk, not(reset), 0) + diff --git a/src/test/scala/firrtlTests/ExtModuleSpec.scala b/src/test/scala/firrtlTests/ExtModuleSpec.scala index ba36e5f2..b7866de1 100644 --- a/src/test/scala/firrtlTests/ExtModuleSpec.scala +++ b/src/test/scala/firrtlTests/ExtModuleSpec.scala @@ -31,4 +31,8 @@ class SimpleExtModuleExecutionTest extends ExecutionTest("SimpleExtModuleTester" Seq("SimpleExtModule")) class MultiExtModuleExecutionTest extends ExecutionTest("MultiExtModuleTester", "/blackboxes", Seq("SimpleExtModule", "AdderExtModule")) +class RenamedExtModuleExecutionTest extends ExecutionTest("RenamedExtModuleTester", "/blackboxes", + Seq("SimpleExtModule")) +class ParameterizedExtModuleExecutionTest extends ExecutionTest( + "ParameterizedExtModuleTester", "/blackboxes", Seq("ParameterizedExtModule")) |
