From 95e8073cdafb6df9ebf156ba29d7e89ec07b2f0e Mon Sep 17 00:00:00 2001 From: Thomas Suckow Date: Wed, 14 Mar 2012 01:25:36 -0700 Subject: [PATCH] Complete layout for generator Begin generating verilog --- .../codingwell/weave/CommandLine/Main.scala | 3 +- .../scala/net/codingwell/weave/Symbols.scala | 17 +++-- .../net/codingwell/weave/WeaveCompiler.scala | 10 +++ .../weave/languages/silk/ASTVisitor.scala | 4 +- .../weave/languages/silk/Semantic.scala | 9 +-- .../weave/languages/silk/SymbolTable.scala | 38 +++++----- .../weave/languages/verilog/Generator.scala | 76 ++++++++++++++++--- samples/test3.silk | 4 +- 8 files changed, 114 insertions(+), 47 deletions(-) diff --git a/command-line/src/main/scala/net/codingwell/weave/CommandLine/Main.scala b/command-line/src/main/scala/net/codingwell/weave/CommandLine/Main.scala index 507ad3a..63da95e 100644 --- a/command-line/src/main/scala/net/codingwell/weave/CommandLine/Main.scala +++ b/command-line/src/main/scala/net/codingwell/weave/CommandLine/Main.scala @@ -53,7 +53,8 @@ object Main { println(".") - compiler.compile( files ) + Timed("Total Compilation")( compiler.compile( files ) ) + println("Done Compiling...") var system:ActorSystem = injector.getInstance(classOf[ActorSystem]) system shutdown diff --git a/core-api/src/main/scala/net/codingwell/weave/Symbols.scala b/core-api/src/main/scala/net/codingwell/weave/Symbols.scala index 90e54c6..2db081a 100644 --- a/core-api/src/main/scala/net/codingwell/weave/Symbols.scala +++ b/core-api/src/main/scala/net/codingwell/weave/Symbols.scala @@ -19,6 +19,9 @@ trait ConnectionSignal { def doSomething():Unit = { } } +case class Gate_XOR ( val a:ConnectionSignal, val b:ConnectionSignal ) extends ConnectionSignal { } +case class Gate_AND ( val a:ConnectionSignal, val b:ConnectionSignal ) extends ConnectionSignal { } +case class Gate_OR ( val a:ConnectionSignal, val b:ConnectionSignal ) extends ConnectionSignal { } /** * \brief This represents a logical wire. @@ -41,27 +44,25 @@ case class Connection () extends ConnectionSignal { def isDriven() = { ! input.isEmpty } } -case class ModuleInput () extends ConnectionSignal {} +case class ModuleInput ( val name:String ) extends ConnectionSignal {} -class ModuleInstance ( module:ModuleSymbol ) { +class ModuleInstance ( val module:ModuleSymbol ) { //TODO: The key should really be a ModuleInput, but we currently don't have access to that type without extending ModuleParameter to be //direction specific val inputs = new mu.HashMap[ConnectionSignal,ConnectionSignal] } -class ModuleConnection( instance:ModuleInstance, instanceConnection:ConnectionSignal ) extends ConnectionSignal { +case class ModuleConnection( instance:ModuleInstance, instanceConnection:ConnectionSignal ) extends ConnectionSignal {} -} - -case class ModuleParameter( direction:String, signal:ConnectionSignal ) +case class ModuleParameter( name:String, direction:String, signal:ConnectionSignal ) class ModuleParameters() { val orderedParameters = new mu.ArrayBuffer[ModuleParameter] val namedParameters = new mu.HashMap[String,ModuleParameter] - def appendParameter( name:String, parameter:ModuleParameter ) = { + def appendParameter( parameter:ModuleParameter ) = { orderedParameters += parameter - namedParameters += ( ( name, parameter ) ) + namedParameters += ( ( parameter.name, parameter ) ) } } diff --git a/core-api/src/main/scala/net/codingwell/weave/WeaveCompiler.scala b/core-api/src/main/scala/net/codingwell/weave/WeaveCompiler.scala index e5d4202..858ba94 100644 --- a/core-api/src/main/scala/net/codingwell/weave/WeaveCompiler.scala +++ b/core-api/src/main/scala/net/codingwell/weave/WeaveCompiler.scala @@ -110,6 +110,16 @@ case class WeaveModule() extends AbstractModule { } +object Timed { + + def apply[R](blockName:String)(block: =>R) = { + val start = System.currentTimeMillis + val result = block + println("Block (" + blockName + ") took " + (System.currentTimeMillis - start) + "ms.") + result + } +} + class WeaveCompiler @Inject() ( @Named("WeaveActor") val weaveActor:ActorRef ) { def compile( files:Seq[WeaveFile] ):Unit = { diff --git a/lang-silk/src/main/scala/net/codingwell/weave/languages/silk/ASTVisitor.scala b/lang-silk/src/main/scala/net/codingwell/weave/languages/silk/ASTVisitor.scala index e0d9044..ec911c4 100644 --- a/lang-silk/src/main/scala/net/codingwell/weave/languages/silk/ASTVisitor.scala +++ b/lang-silk/src/main/scala/net/codingwell/weave/languages/silk/ASTVisitor.scala @@ -98,7 +98,7 @@ class ASTRTLVisitor(val symbols:SymbolTable) { //We use this to enforce the directionality val (moduleconnection, scopeconnection) = parameter.direction.value match { case "in" => - val connectionin = new ModuleInput() + val connectionin = new ModuleInput(parameter.identifier.name) val connectionout = new Connection() connectionout.connectSignal( connectionin ) ( connectionin, connectionout ) @@ -110,6 +110,6 @@ class ASTRTLVisitor(val symbols:SymbolTable) { } symbols.getScope().addSymbol( parameter.identifier.name, DeclarationSymbol( scopeconnection ) ) - moduleparameters.appendParameter( parameter.identifier.name, ModuleParameter( parameter.direction.value, moduleconnection ) ) + moduleparameters.appendParameter( ModuleParameter( parameter.identifier.name, parameter.direction.value, moduleconnection ) ) } } diff --git a/lang-silk/src/main/scala/net/codingwell/weave/languages/silk/Semantic.scala b/lang-silk/src/main/scala/net/codingwell/weave/languages/silk/Semantic.scala index 22af4a7..7d8a5e7 100644 --- a/lang-silk/src/main/scala/net/codingwell/weave/languages/silk/Semantic.scala +++ b/lang-silk/src/main/scala/net/codingwell/weave/languages/silk/Semantic.scala @@ -42,9 +42,6 @@ class Connection () extends ConnectionSignal { //class TemporaryConnection () extends ConnectionSignal {} -class Gate_XOR ( val a:ConnectionSignal, val b:ConnectionSignal ) extends ConnectionSignal { } -class Gate_AND ( val a:ConnectionSignal, val b:ConnectionSignal ) extends ConnectionSignal { } -class Gate_OR ( val a:ConnectionSignal, val b:ConnectionSignal ) extends ConnectionSignal { } trait ExpressionState { @@ -106,6 +103,7 @@ class ExpressionModuleHalfState( val machine:ExpressionStateMachine, val module: val aModuleParameter = module.parameters.orderedParameters(0) aModuleParameter.direction match { case "in" => + println( "Connecting lhs on Module: " + module.name + " Input: " + aModuleParameter.name + " Signal: " + aModuleParameter.signal + '@' + Integer.toHexString(hashCode()) ) instance.inputs += ( ( aModuleParameter.signal, connection ) ) case "out" => connection.connectSignal( new ModuleConnection( instance, aModuleParameter.signal ) ) @@ -115,7 +113,8 @@ class ExpressionModuleHalfState( val machine:ExpressionStateMachine, val module: val bModuleParameter = module.parameters.orderedParameters(1) bModuleParameter.direction match { case "in" => - instance.inputs += ( ( aModuleParameter.signal, rhs ) ) + println( "Connecting rhs on Module: " + module.name + " Input: " + bModuleParameter.name+ " Signal: " + bModuleParameter.signal + '@' + Integer.toHexString(hashCode()) ) + instance.inputs += ( ( bModuleParameter.signal, rhs ) ) case unknown => throw InvalidDirectionException(unknown) } @@ -146,7 +145,7 @@ class ExpressionModuleHalfState( val machine:ExpressionStateMachine, val module: val bModuleParameter = module.parameters.orderedParameters(1) bModuleParameter.direction match { case "in" => - instance.inputs += ( ( aModuleParameter.signal, rhs ) ) + instance.inputs += ( ( bModuleParameter.signal, rhs ) ) case unknown => throw InvalidDirectionException(unknown) } diff --git a/lang-silk/src/main/scala/net/codingwell/weave/languages/silk/SymbolTable.scala b/lang-silk/src/main/scala/net/codingwell/weave/languages/silk/SymbolTable.scala index 91343de..f493ced 100644 --- a/lang-silk/src/main/scala/net/codingwell/weave/languages/silk/SymbolTable.scala +++ b/lang-silk/src/main/scala/net/codingwell/weave/languages/silk/SymbolTable.scala @@ -43,54 +43,54 @@ case class ModuleSymbol( val name:String, val parameters:ModuleParameters ) exte */ object built_in { def get_&():ModuleSymbol = { - val a = new Connection - val b = new Connection + val a = new ModuleInput("a") + val b = new ModuleInput("b") val result = new Connection result.connectSignal( new Gate_AND( a, b ) ) val parameters = new ModuleParameters - parameters.appendParameter( "a", ModuleParameter("in", a) ) - parameters.appendParameter( "b", ModuleParameter("in", b) ) - parameters.appendParameter( "result", ModuleParameter("ret", result) ) + parameters.appendParameter( ModuleParameter("a", "in", a) ) + parameters.appendParameter( ModuleParameter("b", "in", b) ) + parameters.appendParameter( ModuleParameter("result", "ret", result) ) new ModuleSymbol( "&", parameters ) } def get_|():ModuleSymbol = { - val a = new Connection - val b = new Connection + val a = new ModuleInput("a") + val b = new ModuleInput("b") val result = new Connection result.connectSignal( new Gate_OR( a, b ) ) val parameters = new ModuleParameters - parameters.appendParameter( "a", ModuleParameter("in", a) ) - parameters.appendParameter( "b", ModuleParameter("in", b) ) - parameters.appendParameter( "result", ModuleParameter("ret", result) ) + parameters.appendParameter( ModuleParameter("a", "in", a) ) + parameters.appendParameter( ModuleParameter("b", "in", b) ) + parameters.appendParameter( ModuleParameter("result", "ret", result) ) new ModuleSymbol( "|", parameters ) } def get_^():ModuleSymbol = { - val a = new Connection - val b = new Connection + val a = new ModuleInput("a") + val b = new ModuleInput("b") val result = new Connection result.connectSignal( new Gate_XOR( a, b ) ) val parameters = new ModuleParameters - parameters.appendParameter( "a", ModuleParameter("in", a) ) - parameters.appendParameter( "b", ModuleParameter("in", b) ) - parameters.appendParameter( "result", ModuleParameter("ret", result) ) + parameters.appendParameter( ModuleParameter("a", "in", a) ) + parameters.appendParameter( ModuleParameter("b", "in", b) ) + parameters.appendParameter( ModuleParameter("result", "ret", result) ) new ModuleSymbol( "^", parameters ) } def get_=():ModuleSymbol = { val a = new Connection - val b = new Connection + val b = new ModuleInput("b") a.connectSignal( b ) val parameters = new ModuleParameters - parameters.appendParameter( "a", ModuleParameter("out", a) ) - parameters.appendParameter( "b", ModuleParameter("in", b) ) - parameters.appendParameter( "result", ModuleParameter("ret", a) ) + parameters.appendParameter( ModuleParameter("a", "out", a) ) + parameters.appendParameter( ModuleParameter("b", "in", b) ) + parameters.appendParameter( ModuleParameter("result", "ret", a) ) new ModuleSymbol( "=", parameters ) } diff --git a/lang-verilog/src/main/scala/net/codingwell/weave/languages/verilog/Generator.scala b/lang-verilog/src/main/scala/net/codingwell/weave/languages/verilog/Generator.scala index 3158a0b..ba6d968 100644 --- a/lang-verilog/src/main/scala/net/codingwell/weave/languages/verilog/Generator.scala +++ b/lang-verilog/src/main/scala/net/codingwell/weave/languages/verilog/Generator.scala @@ -6,11 +6,12 @@ package net.codingwell.weave.languages.verilog import net.codingwell.weave._ -import scala.collection.{ mutable => mu } +import scala.collection.{ mutable => mu, immutable => im } -class SymbolTable () { +class GeneratorState () { var identifierSalt:Int = 0 + var genout:String = "// Generated by WEAVE\n\n" def generateIdentifier():String = { @@ -29,34 +30,89 @@ class SymbolTable () { } } +case class TopLevelInput ( val name:String ) extends ConnectionSignal {} + class VerilogGeneratorVisitor() extends GeneratorVisitor { def generate( toplevel:ModuleSymbol ):Unit = { - val symbolTable = new SymbolTable + val state = new GeneratorState println("Generating TopLevel: " + toplevel.name) - toplevel.parameters.namedParameters foreach { case (k,v) => { - println("Parameter: " + k) + state.genout += "module " + toplevel.name + "( " + + var outputs:im.List[ModuleParameter] = im.List.empty + var topInstance = new ModuleInstance( toplevel ) + + var first = true; + toplevel.parameters.orderedParameters foreach { v => { + println("Parameter: " + v.name) + if( !first ) state.genout += ", " + first = false; + if( (v.direction equals "out") || (v.direction equals "ret") ) { - handleSignal( v.signal, symbolTable ) + state.genout += "output wire " + v.name + outputs = v :: outputs + } else if( v.direction equals "in" ) { + state.genout += "input wire " + v.name + topInstance.inputs += ( ( v.signal, new TopLevelInput( v.name ) ) ) + } else { + throw new Exception( "Unknown Parameter" ) } }} + + state.genout += ");\n\n" + + outputs foreach { v => + handleSignal( v.signal )( state, im.List( topInstance ) ) + } + + state.genout += "endmodule" + + println( "Generated: \n\n" ) + println( state.genout ) + println( "\n\n" ) } - def handleSignal( connectionSignal:ConnectionSignal, symbolTable:SymbolTable ):Unit = { + def handleSignal(connectionSignal:ConnectionSignal)( implicit state:GeneratorState, moduleStack:im.List[ModuleInstance] ):Unit = { connectionSignal match { case connection @ Connection() => - println("Connection assigned symbol: " + symbolTable.generateIdentifier) + println("Connection assigned symbol: " + state.generateIdentifier) connection.input match { case Some( signal ) => - handleSignal( signal, symbolTable ) + handleSignal( signal ) case None => println( "ERR: Connection has no signal!" ) } + case ModuleConnection( instance, instanceConnection ) => + println("Module Connection (" + instance.module.name + ") assigned symbol: " + state.generateIdentifier) + handleSignal( instanceConnection )( state, instance :: moduleStack ) + case moduleInput @ ModuleInput(name) => + val instance = moduleStack.head + println("Module: " + instance.module.name + " Input: " + name ) + instance.inputs lift ( moduleInput ) match { + case Some( signal ) => + handleSignal( signal )( state, moduleStack drop 1 ) + case None => + throw new Exception("Input is not connected") + } + case Gate_OR( a, b ) => + println( "OR-GATE" ) + handleSignal( a ) + handleSignal( b ) + case Gate_AND( a, b ) => + println( "AND-GATE" ) + handleSignal( a ) + handleSignal( b ) + case Gate_XOR( a, b ) => + println( "XOR-GATE" ) + handleSignal( a ) + handleSignal( b ) + case TopLevelInput( name ) => + println( "Traced ouptut to toplevel input: " + name ) case unknown => - println("Unknown ConnectionSignal: " + unknown) + println("** Unknown ConnectionSignal: " + unknown) } } diff --git a/samples/test3.silk b/samples/test3.silk index 7ed9e9f..6009d50 100644 --- a/samples/test3.silk +++ b/samples/test3.silk @@ -13,7 +13,7 @@ module fulladder sum = s1^ c_in; c_out = ( a & b ) | (s1&c_in); } - +/* module halfadder in bit a; in bit b; @@ -22,4 +22,4 @@ module halfadder { sum = a ^ b; c_out = a & b; -} +}*/