top level naming in chisel3 - scala

class generator(options: Map[String, Any]) {
trait for_module extends abstractModule {
//generates trait with params
}
class my_module extends abstractModule with for_module
def exec = {
...
Driver.execute(Array("-tn", "SomeName", "-td", "SomePath"), () => new my_module)
...
}
}
object generator {
def main(args: Array[String]) = {
...
val a = generator(someopts)
a.exec
}
}
In this code flag -tn should change name of top-level circuit, but it changes only top-level filename. Top module names like "module generatormy_module", but i wants to generate name dynamically from params.
Is dat bug? Or how i can change a top-level module name?
PS: suggestName method doesn't works too!

The flag -tn is not intended to change the top-level circuit, only to specify it and use it as a default in filenames. The way to specify the name of a Chisel module is to override the desiredName method. You can override it with an argument to the Module constructor to make it more programmable. Modifying the above example:
class generator(options: Map[String, Any]) {
trait for_module extends abstractModule {
//generates trait with params
}
class my_module(name: String) extends abstractModule with for_module {
override def desiredName = name
}
def exec = {
val topName = "SomeName"
Driver.execute(Array("-tn", topName, "-td", "SomePath"), () => new my_module(topName))
...
}
}
object generator {
def main(args: Array[String]) = {
...
val a = generator(someopts)
a.exec
}
}

Related

scala: How to obtain class name through complex polymorphism with compile time macros?

When attempting to get the name of a class via a WeakTypeTag reference when defining a macro implementation, I can't seem to get the proper info if multiple layers of polymorphism are applied.
For example if I have the following setup:
object MacroSupport {
def get_name_impl[A: c.WeakTypeTag](c: blackbox.Context): c.Expr[String] = {
val nameOfA: String = weakTypeOf[A].toString
...
}
def getName[A] = macro get_name_impl[A]
}
abstract class GenericInterface[T] {
def getName: String = MacroSupport.getName[T]
}
case class ContainerA(
someValue: String
)
class FunctionalClass extends GenericInterface[ContainerA] {
val containerName: String = getName
}
What I hope to achieve is having any number of FunctionalClass's, each with their own Container class, and they can report the name of their container, which is used for some meta configuration. Basically MacroSupport and GenericInterface will exist in a library I'm writing while the FunctionalClass and Container levels will be written by others using the library.
The issue I'm having, due to the pass through type in the GenericInterface, FunctionalClass.containerName == "t", and attempts to access Type declarations yield nothing. How can I get the type information from the FunctionalClass declaration to the MacroSupport level?
Try materialization of type class
https://docs.scala-lang.org/overviews/macros/implicits.html#implicit-materializers
import scala.reflect.macros.blackbox
import scala.language.experimental.macros
object MacroSupport {
def getName[A](implicit gn: GetName[A]): String = gn()
trait GetName[A] {
def apply(): String
}
object GetName {
implicit def materializeGetName[A]: GetName[A] = macro materializeGetNameImpl[A]
def materializeGetNameImpl[A: c.WeakTypeTag](c: blackbox.Context): c.Expr[GetName[A]] = {
import c.universe._
c.Expr[GetName[A]] {
q"""
new MacroSupport.GetName[${weakTypeOf[A]}] {
override def apply(): _root_.java.lang.String = ${weakTypeOf[A].toString}
}
"""
}
}
}
}
import MacroSupport.GetName
abstract class GenericInterface[T: GetName] {
def getName: String = MacroSupport.getName[T]
}
case class ContainerA(
someValue: String
)
class FunctionalClass extends GenericInterface[ContainerA] {
val containerName: String = getName
}
(new FunctionalClass).containerName // ContainerA
By the way, shapeless.Typeable does the job. Typeable[A].describe is like our MacroSupport.getName[A].

How to access a Scala object instance given it's full qualified name?

So I have defined a Scala object using the following code:
trait SomeTrait {
def someMethod(): Unit
}
package somepackage1 {
object Impl1 extends SomeTrait {
def someMethod(): Unit = { }
}
object Impl2 extends SomeTrait {
def someMethod(): Unit = { }
}
}
I want to access the object given its fully qualified name i.e. somepackage1.Impl2. A method something like following:
package object somewhereElse {
def getImpl(qualifiedName: String): SomeTrait = {
???
}
}
What should be the code as part of getImpl method?
Here is a solution that uses the Java Reflection API (you might want to use the newer Scala Reflection API instead):
trait SomeTrait {
def someMethod(): Unit
}
package somepackage1 {
object Impl1 extends SomeTrait {
def someMethod(): Unit = { println("impl 1") }
}
object Impl2 extends SomeTrait {
def someMethod(): Unit = { println("impl 2") }
}
}
package object somewhereElse {
def getImpl(qualifiedName: String): SomeTrait = {
val clazz = Class.forName(qualifiedName + "$")
clazz
.getField("MODULE$")
.get(clazz)
.asInstanceOf[SomeTrait]
}
}
object Demo {
def main(args: Array[String]): Unit = {
somewhereElse.getImpl("somepackage1.Impl2").someMethod()
}
}
It's quite similar to Dima's comment above, with two minor differences: note the '$' appended to class name, and also the .get(clazz) instead of just .get() (without the clazz, it throws java.lang.NoSuchFieldException: MODULE$).
When saved to file f.scala, and compiled and invoked using
scalac f.scala && scala Demo
it prints:
impl 2

Using structural types as "trait argument"

I'm building my code using traits as modules in a way that I can plug them interchangeably and as needed, something like the following example:
trait Module1 { def method1 = "method1" }
trait Module2 { def method2 = "method2" }
abstract class BaseClass {
def doWork: Unit
}
class ClassImpl extends BaseClass with Module1 with Module2 {
def doWork: Unit = {
println(method1)
println(method2)
}
}
However, some of my modules depend on some configuration variables (user-defined, runtime arguments), something I would pass as constructor parameters if they were classes. As traits do not accept parameters my idea for this was by using structural types:
trait Module1 {
this: {
val config1: Int
val config2: Int
} =>
def method1 = s"method1 c1=$config1 c2=$config2"
}
trait Module2 { def method2 = "method2" }
abstract class BaseClass {
def doWork: Unit
}
case class Config(c1: Int, c2: Int)
class ClassImpl(config: Config) extends BaseClass with Module1 with Module2 {
protected val config1 = config.c1
protected val config2 = config.c2
def doWork: Unit = {
println(method1)
println(method2)
}
}
Is it a good strategy for configuring my modules or there is something better?
Structural types involves reflection and are there is a better solution indeed, consider the following example:
trait Module[F,S] { this: Config[F,S] =>
def method = s"method1 c1=$config1 c2=$config2"
}
trait Config[F,S] {
def config1: F
def config2: S
}
case class DefaultConfig[T,S](config1: T, config2: S) extends Config[T,S]
case class ConfigCls(c1: Int, c2: Int)
class ClassImpl(config: ConfigCls) extends DefaultConfig(config.c1, config.c2) with Module[Int,Int] {
def doWork(): Unit = {
println(method)
}
}
This way you avoid using structural types, doing basically the same thing as in your original post.

Using trait method in the class constructor

I have a trait and a class that extends the trait. I can use the methods from the trait as follows:
trait A {
def a = ""
}
class B(s: String) extends A {
def b = a
}
However, when I use the trait's method in the constructor like this:
trait A {
def a = ""
}
class B(s: String) extends A {
def this() = this(a)
}
then the following error appears:
error: not found: value a
Is there some way to define default parameters for the construction of classes in the trait?
EDIT: To clarify the purpose: There is the akka-testkit:
class TestKit(_system: ActorSystem) extends { implicit val system = _system }
And each test looks like this:
class B(_system: ActorSystem) extends TestKit(_system) with A with ... {
def this() = this(actorSystem)
...
}
because I want to create common creation of the ActorSystem in A:
trait A {
val conf = ...
def actorSystem = ActorSystem("MySpec", conf)
...
}
It's a little bit tricky because of Scala initialization order. The simplest solution I found is to define a companion object for your class B with apply as factory method:
trait A {
def a = "aaaa"
}
class B(s: String) {
println(s)
}
object B extends A {
def apply() = new B(a)
def apply(s: String) = new B(s)
}

Scala implicit type class dependency injection

I'd like some help sorting out this scenario. I have an Akka actor where I want to inject a dependency, in this case RemoteFetcher, which I would also like mock in my tests. Like so:
main/src/scala/mypackage/Services.scala
package mypackage
import RemoteFetcherFileSystem._
trait RemoteFetcher {
def fetch( path:String ): Future[Stream[String]]
}
class MyRemoteResourceActor extends Actor with ActorLogging {
def fetchRemote( path:String ) = implicitly[RemoteFetcher].fetch( path )
def receive = {
case FetchRemoteResource( path ) => fetchRemote( path ).map( _.foreach( sender ! _ ) )
}
}
For this to work I have an implicit object that I import into the file above. Would look something like this:
implicit object RemoteFetcherFileSystem extends RemoteFetcher {
def fetchRemote( path:String ) = Future[Stream[String]] { ... reading from file system ... }
}
Now in my tests I have TestActor from the akka-testkit. Here I want to instead import my mock dependency:
implicit object RemoteFetcherMock extends RemoteFetcher {
def fetchRemote( path:String ) = Future[Stream[String]] { ... mock implementation ... }
}
My problem is that to compile Services.scala I need to import the implicit object. But how do I go about to shadow/override this in my test-files. The reason I'm not using implicit arguments is that I want to avoid having to modify all my actors constructor arguments.
I when looking around and reading up on the type class dependency injection pattern and I get it to work according to the tutorials, but I don't get it to work when I want to test and override like in my example.
I'm not sure how to do it with implicits, but typically one could inject instead like so:
trait RemoteFetcherComponent {
def remoteFetcher: RemoteFetcher
trait RemoteFetcher {
def fetch(path: String): Future[Stream[String]]
}
}
trait RemoteFetcherFileSystemComponent extends RemoteFetcherComponent {
val remoteFetcher = RemoteFetcherFileSystem
object RemoteFetcherFileSystem extends RemoteFetcher {
def fetch(path: String): Future[Stream[String]] = ???
}
}
class MyRemoteResourceActor extends Actor with ActorLogging with RemoteFetcherFileSystemComponent {
def fetchRemote(path: String) = remoteFetcher.fetch(path)
def receive = {
case FetchRemoteResource(path) => fetchRemote(path).map( _.foreach(sender ! _))
}
}
val myRemoteResourceActor = new MyRemoteResourceActor()
And then a test value would be defined like so:
trait RemoteFetcherMockComponent extends RemoteFetcherComponent {
def remoteFetcher = RemoteFetcherMock
object RemoteFetcherMock extends RemoteFetcher {
def fetch(path: String): Future[Stream[String]] = ???
}
}
val myMockedResourceActor = new MyRemoteResourceActor with RemoteFetcherMockComponent {
override val remoteFetcher = super[RemoteFetcherMockComponent].remoteFetcher
}
The reason you are having an issue with implicits is because the way you're using it is no different from simply using def fetchRemote(path: String) = RemoteFetcherFileSystem.fetch(path). With the import, you've defined the implementation, rather than allowed it to be injected later.
You could also change the implicitly to an implicit parameter:
trait RemoteFetcher {
def fetch(path: String): Future[Stream[String]]
}
object RemoteFetcher {
implicit val fetcher = RemoteFetcherFileSystem
}
class MyRemoteResourceActor extends Actor with ActorLogging {
def fetchRemote(path: String)(implicit remoteFetcher: RemoteFetcher) = remoteFetcher.fetch(path)
def receive = {
case FetchRemoteResource(path) => fetchRemote(path).map( _.foreach(sender ! _))
}
}
Then you could override the implicit that is resolved in the companion object of RemoteFetcher by simply importing RemoteFetcherMock.
See this post for more information about implicit parameter resolution precedence rules.