Disclaimer: I'm not super familiar with Scala. I have used Spinal/Chisel some to test out what I want to do, as well as create some simple HW, so please forgive me if these questions are "entry-level" from a Scala perspective.
I'm planning to use SpinalHDL for some connection automation. We have a bunch of IP that we can't/won't convert to SpinalHDL and much of it is mixed-signal. Because of this, I have some situations where additional signal information would allow me to further automate the design process. As an example, there are cases where some signals are on various power domains and their connections either need to be limited to said specific power domain or we would have to insert some logic like a level shifter.
Let's say I have a bundle of signals for some IP (this Bundle is on one of my BlackBoxes)
class MyBundle extends Bundle{
val data = in UInt(8 bits)
val valid = in Bool
val pwr800mV = in Bool
val pwr1800mv= in Bool
val gnd = in Bool
}
MyBundle is on a BlackBox, and I instantiate several of these in a Component. My idea is to be able to walk through the IOs/Signals in the Bundle and connect them to the appropriate higher level power/ground signal. Example:
class PwrSignal(v : Double = 1.8) extends Bool{
val voltage = v
}
class MyBundle extends Bundle{
val data = in UInt(8 bits)
val valid = in Bool
val pwr800mV = in PwrSignal(0.8)
val pwr1800mv= in PwrSignal(1.8)
val gnd = in Bool
}
class MyComponent extends Component{
//IO creation
//pseudo...
walkBundleSignals{
if (signal.voltage == 1.8){ signal := top_level_power_1p8v}
}
}
At first I tried to create a PwrSignal class that extends Bool, however this fails since PwrSignal is not a part of spinal.core.in.
Is there anyway to go about doing this?
Thanks
Derp Alert: Since the default data types override the constructor, you just need to "new" the user defined data type.
class PwrSignal(v : Double = 1.8) extends Bool{
val voltage = v
}
class MyBundle extends Bundle{
val data = in UInt(8 bits)
val valid = in Bool
val pwr800mV = in (new PwrSignal(0.8))
val pwr1800mv= in (new PwrSignal(1.8))
val gnd = in Bool
}
Related
I have these two objects A and B I want to use these objects interchangeably in the digit class like shown in this snippet code
internal object A {
internal const val ZERO = "ZERO"
internal const val ONE = "ONE"
}
internal object B {
internal const val ZERO = "ZERO"
internal const val ONE = "UN"
}
class Digit(Lang: String) {
private var X: Any? = null
init {
when (Lang) {
"eng" -> X = A
"fr" -> X = B
}
}
fun spell() {
println(X.ZERO)
}
}
I want inside the Digit class to use both objects, not at the same time, only when I want the English language the Digit class use object A and when I want french language the Digit class use the object B.
I should use reflection? or is there a better design?
The simplest answer is to have your objects all implement the same interface, e.g.:
interface Language {
val ZERO: String
val ONE: String
}
internal object A: Language {
override val ZERO = "ZERO"
override val ONE = "ONE"
}
// …
You can then set a Language reference to any object implementing that interface.
A related (and more concise) approach might be to use an enum:
enum class Language(val ZERO: String, val ONE: String) {
A("ZERO", "ONE"), B("ZERO", "UN")
}
You can then refer to the objects as Language.A &c.
But in practice, none of these approaches scale well. You're likely to end up with a good number of language strings, and probably quite a few languages to support, and those methods will get long-winded. And hard-coding all the strings will make it much more awkward to manage.
So it's more usual to store all the language strings in resource files and load them in at runtime. You could do that manually, e.g. storing the strings in a map — but many platforms and frameworks support standard ways to select the right language, load the strings, and use them. There are many existing questions about this.
data class Translation(val ZERO: String, val ONE: String)
val a = Translation(ZERO = "ZERO", ONE = "ONE")
val b = Translation(ZERO = "ZERO", ONE = "UN")
class Digit(Lang: Translation) {
private val x = Lang
fun spell() {
println(x.ONE)
}
}
Digit(a).spell()
Digit(b).spell()
There's an already built in way that fulfill my request?
I know Set are unordered
I need to do a vector based Set.
I need to know the position of any value of a generic type to place them in the corresponding index of the array, So I can avoid duplications of the elements.
I'm not ordering or defining an order of the Set.
I don't have any operators that missbehave or break any Set Costraint
Please note that I know this implementation is not efficient for any types that seems infinite like Integers.
I need to do it for an educational purpose.
I have already implemented List Ordered and Hash Table based ones.
For now I have this class, that works flawlessy:
package ads
class MySet<E : Enum<E>> {
//More details for clarify
private val maxSet = 127
private var myset = arrayOfNulls<Boolean>(maxSet)
private fun getOrdinal(eelement : E) : Int{
return eelement.ordinal
}
/*
more set operators that needs of getOrdinal
*/
fun insert(xelement: E){
myset[getOrdinal(xelement)] = true
}
}
import ads.MySet as RawSet
enum class MyColors{
Red,
Green,
Blue,
Yellow,
Black,
Mint;
}
fun main() {
val myfavc = RawSet<MyColors>()
val yourfavc = RawSet<MyColors>()
//Following operations...
myfavc.insert(MyColors.Red)
yourfavc.insert(MyColors.Blue)
}
I need now to make another class in the same way but working with whatever abstract type already defined in kotlin.
package ads
class MySet<T> {
//More details for clarify
private val maxSet = 127
private var myset = arrayOfNulls<Boolean>(maxSet)
private fun getOrdinal(telement : T) : Int{
/*
For any abstract type return the order of any element
checks if the integer is not greater than maxSet otherwhise it
throws an Exception or manages this istance in other way
*/
}
/*
more set operators that needs of getOrdinal
*/
fun insert(xelement: T){
myset[getOrdinal(xelement)] = true
}
}
import ads.MySet as RawSeT
//Istance using Int
fun main() {
val myfav = RawSet<Int>()
val yourfav = RawSet<Int>()
//Following operations...
myfav.insert(11)
yourfav.insert(123)
}
I guess there's no built-in way to do so in a generic way.
but I'm still learning kotlin, so maybe I'm missing something useful.
I'm not asking to do my paper.
I don't need a full alternative solutions that I should find out by myself but
I'm opened to read about any tips or resources that can help me to clarify how abstract types works in Kotlin(or Programming Languages) infos like :
How are ordered.
If any value of any type can be compared based on their position
(like c > a for chars).
Range of values/Max values represented for any "apparently
infinite" type like Integers.
Thanks you!
P.S. = Please consider that I'm not an english native, be patient!
Enums are implicitly ordered in declaration order and amount of instances of each enum is finite, so they could be ordered globally and their ordinal could be represented as Int.
Ints (as well as Bytes and Chars) are naturally ordered and have ranges (Int.MIN_VALUE..Int.MAX_VALUE, etc.), so each of them could have an ordinal represented as Int too.
All types implementing Comparable interface could be compared in pairs and any subset of their instances could be ordered, but it doesn't mean that each of them have some global Int ordinal among all possible instances, because set of Ints is finite (2^32 items), and set of all unique instances of generic type T could be countably infinite (like BigInteger) or even uncountable (like Double) (see wiki about cardinality).
All other types couldn't be even compared in pairs (without respectful Comparator<T>).
So you need to manually limit instances of each T that are about to be added in your set and either maually order them or provide respectful Comparator<T> to construct a Map<T, Int> which you'll need to use for subsequent ordinal evaluation:
class SetOfSomehowOrderedInstancesOfType<T>(private val order: Map<T, Int>) {
private val maxSet = order.size
private var myset = BooleanArray(order.size)
private fun getOrdinal(eelement: T): Int {
return order[eelement] ?: throw RuntimeException("Order unknown")
}
fun insert(xelement: T) {
myset[getOrdinal(xelement)] = true
}
}
Usage:
fun main() {
val myFavouriteRealNumbersInMyFavouriteOrder =
listOf(99.2123, -2355.12, 1.1, 3.14, 100.0, 123214214215.123331322145)
val myfavc = SetOfSomehowOrderedInstancesOfType<Double>(myFavouriteRealNumbersInMyFavouriteOrder.mapToIndex())
myfavc.insert(99.2123) //will be inserted with ordinal = 0
val myFavouriteRealNumbersInNaturalOrder = myFavouriteRealNumbersInMyFavouriteOrder.sorted()
val yourfavc = SetOfSomehowOrderedInstancesOfType<Double>(myFavouriteRealNumbersInNaturalOrder.mapToIndex())
yourfavc.insert(99.2123) //will be inserted with ordinal = 3
}
Alternatively you may define Orderable and Ordinator<T> interfaces (similar to Comparable<T> and Comparator<T>) and determine ordinal using them:
fun interface Ordinator<T> {
fun getOrderOf(x : T) : Int
}
interface Orderable {
val order : Int
}
class MySet<T>(private val ordinator: Ordinator<T>? = null) {
private val maxSet = 127
private var myset = BooleanArray(maxSet)
private fun getOrdinal(eelement: T) = when {
eelement is Orderable -> eelement.order
ordinator != null -> ordinator.getOrderOf(eelement)
else -> throw RuntimeException()
}
fun insert(xelement: T) {
myset[getOrdinal(xelement)] = true
}
}
Also you may define auxilary function, generalizing previous approach:
fun <T> ordinatorOf(order: List<T>) = object : Ordinator<T> {
private val order = order.mapToIndex()
override fun getOrderOf(x: T) = this.order[x] ?: throw RuntimeException()
}
Usage:
val stringsOrderedByTheirLength = MySet<String> { it.length }
stringsOrderedByTheirLength.insert("aaa") //will be inserted with ordinal = 3
val myFavouriteRealNumbersInMyFavouriteOrder =
listOf(99.2123, -2355.12, 1.1, 3.14, 100.0, 123214214215.123331322145)
val myfavc = MySet(ordinatorOf(myFavouriteRealNumbersInMyFavouriteOrder))
myfavc.insert(99.2123) //will be inserted with ordinal = 0
As somebody pointed out to me that some abstract types representing for an istance Real Numbers can't be done so easily.
The implementation with the enum class works flawlessy but it's been refused from my university professor because I need to use the same syntax for every implementation of the same Data Structure.
Other implementation I have
- HashTableSet<T>
- OrderedListSet<T>
they ask only for an abstract type that can be whatever type, they will work without problem.
I need to do it the same with the
ArraySet<E : Enum<E>>
So if this can't be done easily with Generics, directly...
I'm thinking about mixing them.
Like whatever T type I have
it creates an object called "Domain" so whatever element it insert, before placing them in the array of the set, it place them inside there in a specific order so it simulates what enum it was doing.
I guess that Enumerations can't be defined during the runtime, dinamically.
Then probably I have to define Domain<T> as a private class/object(not sure) that :
Collect the element of the istance of ArraySet(above MySet) inserts with its opeator .insert()
It orders the element comparing to the ones that are already inside
Once is ordered delete all the duples
Re-arrange the whole Boolean Array everytime insert is used based on how Domain grows. (or find out a different algo that partially re-arrange the boolean array)
What do you think?
Advice me more, thanks.
I am writing a Graph class in Kotlin. Here's my code so far:
import java.util.*
class Graph<Class>(connectionProb: Double) {
// a general network class
val nodes = mutableListOf<Class>()
val connectionProb = connectionProb
val connections = hashMapOf<Class, MutableList<Class>>()
var nextID = 0
private fun createNode() {
// Here is where I need help
}
}
I want to be able to specify the node type for each Graph. The code above will compile, but I'm unsure how to initialize new nodes. The only argument I want to pass into each node, regardless of its type, is nextID.
Thanks!
First thing you should do is define a class for your graph node, and instead of maintaining a map for connections, let every node maintain a list of its connections.
So your code would look like this
class Graph<T>(connectionProb: Double) {
var nextId = 0
val nodes = mutableListOf<Node<T>>()
// Define a node class, so if you have graph of Integer then you want a node of Integer
class Node<T>(var id: Int){
val connections = mutableListOf<Node<T>>()
fun addConnection(newConnection: Node<T>){
connections.add(newConnection)
}
override fun toString() = "$id"
/** add other functions, such as remove etc */
}
fun createNode(){
var newNode = Node<T>(nextId++)
nodes.add(newNode)
}
}
Now to use this graph you will do followig
fun main(){
var myGraph = Graph<Integer>(10.9)
myGraph.createNode()
myGraph.createNode()
myGraph.nodes[0].addConnection(myGraph.nodes[1])
/* Print all nodes in graph */
for(node in myGraph.nodes) print(" $node")
/* Print connections of first node */
for(node in myGraph.nodes[0].connections) print("\n\nConnection id: $node")
}
Please note that this will give you a general idea of how to go about implementing graph and there are many things that you can improve in the implementation. To learn more I suggest you read a good book, such as Data Structures and Algorithms in Java
Preface: Google+SO+docu search did not appear to give relevant information.
Domain Model:
My domain model tries to picture an ProductionPlan, containing a List of Machines.
Each Machine has a list of chained jobs, thus a job which has a getNextEntry():Job Method, creating a list of jobs.
I tried to solve this problem with chained PlanningVariables, but apparently do not understand the concept of chainedVariables/shadowVariables/anchorVariables.
With my understanding, all jobs are getting chained and the anchorShadowVariable points to the beginning of the list, thus the machine.
To implement chaining, Job and Machine need to implement an interface or extend superclass, thus i created ChainSuperClass. Additionally i do not know if i have to overwrite getter/setter to set Annotations in Machine-Class, my guess was that because Machine extends ChainSuperClass, those Annotations carry over.
Edit: Kotlin specific improvements are also appreciated.
The full error log of my code execution is now:
Exception in thread "main" java.lang.IllegalArgumentException: The entityClass (class optaplanner.productionPlan.domain.ChainSuperClass) has a InverseRelationShadowVariable annotated property (nextEntry) which does not return a Collection with sourceVariableName (machine) which is not chained. Only a chained variable supports a singleton inverse.
ChainSuperClass:
#PlanningEntity
abstract class ChainSuperClass {
#PlanningId
open val id = Random.nextInt().toString()
#InverseRelationShadowVariable(sourceVariableName = "machine")
abstract fun getNextEntry(): Job?
abstract fun setNextEntry(job: Job)
}
Job:
#PlanningEntity
class Job(
val jobType: JobType,
val itemNumber: String,
val orderNumber: String,
val setupTime: Int,
val productionTime: Int
) : ChainSuperClass() {
#AnchorShadowVariable(sourceVariableName = "machine")
var machine: Machine? = null
private var nextEntry: Job? = null
#PlanningVariable(
valueRangeProviderRefs = ["jobList"],
graphType = PlanningVariableGraphType.CHAINED
)
override fun getNextEntry(): Job? {
return nextEntry
}
override fun setNextEntry(job: Job) {
this.nextEntry = nextEntry
}
}
Machine:
class Machine(override val id: String, val jobTypes: List<JobType>) : ChainSuperClass() {
private var nextEntry: Job? = null
override fun setNextEntry(job: Job) {
this.nextEntry = job
}
override fun getNextEntry(): Job? {
return nextEntry!!
}
}
I think the most important thing to realize with chained variables is this: When you have an entity, say Job A and solver assigns a value (job/machine) to its variable, it's not like the chain is being built forward starting from Job A. It's the other way around. By assigning a value to Job A's planning variable, Job A gets connected at the end of an existing chain.
Please take a look at the documentation to find more details about chaining and examples of valid chains.
By having understood this it should be clear that Job's planning variable name should be something like previousJobOrMachine (you'll probably want something simpler, for example previousStep) whereas the nextJob property is an inverse relation shadow variable derived from that (so when Job X gets connected to an existing chain ending with Job C by assigning Job X.previousStep=Job C, an inverse relation is established automatically: Job C.nextJob=Job X).
Based on that information, your model should look more like this:
#PlanningEntity
abstract class ChainSuperClass {
#PlanningId
open val id = Random.nextInt().toString()
// changed sourceVariableName to point to the planning variable
#InverseRelationShadowVariable(sourceVariableName = "previousStep")
abstract fun getNextEntry(): Job?
abstract fun setNextEntry(job: Job)
}
#PlanningEntity
class Job(
val jobType: JobType,
val itemNumber: String,
val orderNumber: String,
val setupTime: Int,
val productionTime: Int
) : ChainSuperClass() {
// changed sourceVariableName to point to the planning variable
#AnchorShadowVariable(sourceVariableName = "previousStep")
var machine: Machine? = null
// added planning variable
private var previousStep: ChainSuperClass? = null
private var nextEntry: Job? = null
#PlanningVariable(
// added machineList value range provider
valueRangeProviderRefs = ["jobList", "machineList"],
graphType = PlanningVariableGraphType.CHAINED
)
// getter for the new planning variable
fun getPreviousStep(): ChainSuperClass {
return previousStep
}
override fun getNextEntry(): Job? {
return nextEntry
}
override fun setNextEntry(job: Job) {
this.nextEntry = nextEntry
}
}
Notice that I added machineList as the source of possible values of the previousStep planning variable as previous step might be either a Job at the end of a non-empty chain or a Machine representing an empty chain.
Your domain is very similar to the vehicle routing domain, where you can see a working example of chaining. With good understanding of chaining principles you should be able to replicate it on your domain.
I need to check if any variables inside of my data class are null. To do this I need retrieve them first but I can't access them directly (e.g. myDataClass.name) because I need it to be generic. Is there a way to access these variables without directly naming them. For example, like accessing a member of an array (myArray[0]).
The mechanism you're looking for is called "reflection" and it allows to introspect objects at runtime. You'll find a lot of information on the internet, but just to give you a link you may want to check this answer.
In your case you could do something like this:
data class MyDataClass(
val first: String?,
val second: String?,
val third: Int?
)
fun main() {
val a = MyDataClass("firstValue", "secondValue", 1)
val b = MyDataClass("firstValue", null, null)
printProperties(a)
printProperties(b)
}
fun printProperties(target: MyDataClass) {
val properties = target::class.memberProperties
for (property in properties) {
val value = property.getter.call(target)
val propertyName = property.name
println("$propertyName=$value")
}
}
Note that for this code to work you must add kotlin-reflect package as a dependency.