How to type cast a list of uint to a list of vr_ahb_data in Specman? - casting

I have A which is a list of uint(bits:20) and B which is a list of vr_ahb_data. I also have a method that takes in 2 lists of vr_ahb_data and compares each item between the two lists.
type vr_ahb_data : uint(bits: VR_AHB_DATA_WIDTH); // defined in vr_ahb_types.e
// below are in my test bench environment
A : list of uint(bits:20);
B : list of vr_ahb_data;
data_check(act: list of vr_ahb_data, exp: list of vr_ahb_data) is {
// compare each item in both lists
};
How do I type cast A to make it acceptable to the data_check() method ? I cannot change the method since it is a common utility.

assuming that vr_ahb_data is some kind of an int, that is - defined something like this -
type vr_ahb_data : uint(bits : VR_AHB_DATA_WIDTH);
you can do the casting in the call
data_check(A.as_a(list of vr_ahb_data), B);

Related

How to use type-level functions to create static types, dynamically?

In TypeScript, there are type-level functions that allow creating new types based on given literal types/specifications (see Mapped Types, Conditional Types, etc.).
For instance, here is such a function, let say provided by a lib author:
type FromSpec<S> = {
[K in keyof S]: S[K] extends "foo" ? ExampleType : never
};
Its purpose is, given a specification S in the form of a map of string keys and arbitrary literals, it creates a new type in the form of a map with the same set of keys and with values transformed. If a the value is the literal "foo" then it becomes the type ExampleType, otherwise the value is rejected by transforming it into the bottom type never.
Then, an end-user can make use of this function to create new types following the above explanation:
type Example = FromSpec<{some_key: "foo", another_key: "bar"}>
// = {some_key: ExampleType, another_key: never}
It's noteworthy that the lib author doesn't know about what exact type a given end-user may want, and thus provides him with a function to create the ones he needs. On the other hand, the end-user can create an infinite set of new types as long as he complies with the function's capabilities.
You can play around this simple example, here.
The question is about how this kind of "dynamism" is expressible in other typed languages (e.g., ReasonML/OCaml, Scala, Haskell). Or how, as an end-user, to create new types, at compile-time, by using type-level functions, provided by a lib author (as one would usually do at runtime with value-level functions)?
It's important to note that the question is not about which language is better, etc. It's about finding the most straightforward and explicit way to express such capabilities. Here we saw an example in TypeScript, but is there any more natural way in any other language?
Given Scala is one of the tagged languages, here is a solution in Dotty (aka. Scala 3). Take this with a grain of salt, since Dotty is still under development. Tested with Dotty version 0.24.0-RC1, here is a Scastie that proves this actually compiles.
Scala doesn't have the same sort of built-in type machinery as TypeScript for manipulating records. Not to fear, we can roll our own!
import deriving._
// A field is literally just a tuple of field name and value
type Field[K, V] = (K, V)
// This just helps type-inference infer singleton types in the right places
def field[K <: String with Singleton, V <: Singleton](
label: K,
value: V
): Field[K, V] = label -> value
// Here is an example of some records
val myRec1 = ()
val myRec2 = field("key1", "foo") *: field("key2", "foo") *: ()
val myRec3 =
field("key1", 1) *: field("key2", "foo") *: field("key3", "hello world") *: ()
Then, FromSpec can be implemented using a match-type. The never type in TypeScript is called Nothing in Scala/Dotty.
// Could be defined to be useful - `trait` is just an easy way to bring a new type in
trait ExampleType
val exampleValue = new ExampleType {}
type FromSpec[S <: Tuple] <: Tuple = S match {
case Field[k, "foo"] *: rest => Field[k, ExampleType] *: FromSpec[rest]
case Field[k, v] *: rest => Field[k, Nothing] *: FromSpec[rest]
case Unit => Unit
}
Finally, let's use FromSpec:
def myRec1Spec: FromSpec[myRec1.type] = ()
def myRec2Spec: FromSpec[myRec2.type] =
field("key1", exampleValue) *: field("key2", exampleValue) *: ()
def myRec3Spec: FromSpec[myRec3.type] = ??? // no non-diverging implementation
Is it possible to express the same kind of "dynamism" or something close to it in another typed language (e.g., ReasonML/OCaml, Scala, Haskell).
Yes, dynamic types are fully supported by the OCaml/ReasonML type system and are widely used. You can express quite complex dynamic typing rules, e.g., build your hierarchies, implement ad-hoc polymorphism and so on. The main ingredients of the solution is using extensible GADT, first-class modules, and existentials. See this answer as one of the example or this discussion for the general case of universal values, there are also multiple libraries that provide various dynamic typing capabilities in OCaml. Another example is BAP's Core Theory library that has a very complex type hierarchy for value sorts, which includes precise type specifications for various number representations, including floating-point numbers, memories, etc.
To make the answer complete, this is how you can implement your fromSpec in OCaml, first we define type that will be bearing the tag for dynamic typing, underneath the hood this is just an integer, but with associated type which it is witnessing,
type 'a witness = ..
To create a new witness (basically incrementing this id) we will use first class modules and append a new constructor using +=
module type Witness = sig
type t
type _ witness += Id : t witness
end
type 'a typeid = (module Witness with type t = 'a)
let newtype (type u) () =
let module Witness = struct
type t = u
type _ witness += Id : t witness
end in
(module Witness : Witness with type t = u)
The type equality proof (the value that proofs to the compiler that two types are the same since they are both using the constructor with the same identity), is commonly represented as ('a,'b) eq type,
type ('a,'b) eq = Equal : ('a,'a) eq
And this is how we implement the cast function,
let try_cast : type a b. a typeid -> b typeid -> (a,b) eq option =
fun x y ->
let module X : Witness with type t = a = (val x) in
let module Y : Witness with type t = b = (val y) in
match X.Id with
| Y.Id -> Some Equal
| _ -> None
finally, your fromSpec,
type spec {
data : 'a;
rtti : 'a typeid
}
let example_type = newtype ()
let example = {
data = 42;
rtti = example_type; (* witnesses that data is `int` *)
}
let fromSpec = try_cast example_type
Disclaimer: I'm not a C++ programmer, so don't take this answer to be the proper way to do it in C++. It is just one way to do it that is extremely brittle and is probably mostly wrong.
//I've used char pointers below, because it's not possible to directly write string //literals in templates without doing some more complex stuff that isn't relevant here
//field1 and field2 are the names of the fields/keys
const char field2[] = "field2";
const char field1[] = "field1";
//foo and bar are the strings that determine what the
//type of the fields will be
const char foo[] = "foo";
const char bar[] = "bar";
//This represents a key and the determining string (foo/bar)
template <const char * name, const char * det>
struct Named {};
//What the type of the field will be if it maps to "foo"
struct ExampleType {
std::string msg;
};
//The end of a cons structure
struct End{};
//A cons-like structure, but for types
template <typename T, typename N>
struct Cons {
typedef T type;
typedef N Next;
};
//This'll be used to create new types
//While it doesn't return a type, per se, you can access the
//"created" type using "FromSpec<...>::type" (see below)
template <typename T>
struct FromSpec;
//This will handle any Named template where the determining string
//is not "foo", and gives void instead of ExampleType
template <const char * name, const char * det, typename rest>
struct FromSpec<Cons<Named<name, det>, rest>> {
//Kinda uses recursion to find the type for the rest
typedef Cons<void, typename FromSpec<rest>::type> type;
};
//This will handle cases when the string is "foo"
//The first type in the cons is ExampleType, along with the name
//of the field
template <const char * name, typename rest>
struct FromSpec<Cons<Named<name, foo>, rest>> {
typedef Cons<ExampleType, typename FromSpec<rest>::type> type;
};
//This deals with when you're at the end
template <>
struct FromSpec<End> {
typedef End type;
};
Now you can use it like this:
typedef Cons<Named<field1, foo>, Cons<Named<field2, bar>, End>> C;
//Notice the "::type"
typedef FromSpec<C>::type T;
T is equivalent to Cons<ExampleType, Cons<void, End>>
You can then access the types inside like so:
typedef T::type E; //Equivalent to ExampleType
typedef T::type::Next N; //Equivalent to Cons<void, End>
typedef N::type v; //Equivalent to void
Example usage
int main() {
ExampleType et = { "This is way too complicated!" };
//You can kinda have values of type "void", unfortunately,
//but they're really just null
// v
N inner = { nullptr, new End() };
T obj = { &et, &inner };
Cons<ExampleType, Cons<void, End>> obj2 = obj;
std::cout << et.msg << std::endl;
}
Prints "This is way too complicated!"
Link to repl.it
Feel free to edit my answer if it has mistakes or if it could be otherwise improved. I mostly just tried to translate the answer by #Alec into C++.

Safely convert enum class from underlying type

Let's say I have a strongly typed enum type like this:
enum class message : int {
JOIN = 0,
LEAVE = 4,
SPAWN = 1,
}
And I need to safely (safely in this case means discarding invalid variants) convert it from it's underlying type (int).
For this purpose, I have a function to convert it for me:
std::optional<message> get_message(int num) {
return num == (int)message::JOIN || num == (int)message::LEAVE || num == (int)message::SPAWN ? (message)num : {};
}
This works, but is long to write and prone to mistakes, especially for enums with a larger number of variants.
Is there a way to automate this process in C++17?
Talking about underlying type, we notice that this class merely obtains a type using another type as model, but it does not transform values or objects between those types.
As an option to simplify the function you could work by iterating in the enum,or as others said before with some type of container, by iterating the same enum as an example here: How can I iterate over an enum?
and more information about enum just in case: https://learn.microsoft.com/en-us/cpp/cpp/enumerations-cpp?view=vs-2019

Modifiable set of multisets: two-level sorting container

I have the following three-level data structure (bottom to top):
object C: {string, T, float} (where T is also an object)
sorted container B of objects C with same string by highest float first
sorted container A of objects B by lowest max(C.float) (i.e. B[0]) first
So at the beginning I'll have a bunch of C with pre-computed float values and my data structure should look like this:
A:
B:
C:
string: "one"
T: {object}
float: 10
C:
string: "one"
T: {object} # different from the above of course
float: 8.3
C:
string: "one"
T: {object}
float: -4
B:
C:
string: "two"
T: {object}
float: 15
C:
string: "two"
T: {object}
float: 2
C:
string: "two"
T: {object}
float: 0
No difficult problem up to now, as I could just simply put all of this into a set of sets (/multisets) and be done with it. Here is where it get's difficult: I will have to extract a subset of these to compute a solution of my problem (the first C of every B). If there is no solution, then remove the topmost C and extract the new subset to try again. In python pseudo-code:
def get_list():
c_list = []
for b in A:
c_list.append(b[0]) # element in B with highest float value
return c_list
def solve():
for i in range(1, 3): # three tries
c_list = get_list()
# do stuff with c_list
if fail:
del A[0][0] # the topmost C element in the first B
continue
But when I delete this A[0][0] (i.e. the C with {"one", T, 10}), I need the whole thing to re-sort itself. Therefore I can't use sets as I'd be modifying A[0], which a STL set/multiset doesn't allow.
The other solution would be to create classes, define the operator() or operator< for each of the two levels I need to do a comparison on (B and C) for std::sort() and stuff everything into a two-level STL vector. However this just seems overly complicated/my non-professional C++ intuition tells the there should be an easier way to code this neatly.
Performance is important as it's a "real-time" application for a robot, but not of topmost priority as I'll only have say up to 30 C.
It seems that you are indexing by position, rather than value. The simplest data structure to use when you don't need efficient lookup by key is std::vector. I believe that would address your problems.
The std::set container is an ordered set of values.
Following David's suggestion to use std::vector nevertheless and this post, the simplest solution seems to be using the std::sort with a lambda expression. That way one doesn't need to define any additional classes (like B in this case) or any operator overloads.
class C {
string type;
T obj;
float sat;
};
And then:
vector<vector<C>> c_list = getData();
// Sort Bs
auto b_sort = [] (const C& lhs, const C& rhs) { return lhs.sat > rhs.sat; };
for (auto&& b : c_set) {
sort(b.begin(), b.end(), b_sort);
}
// Sort A
sort(c_set.begin(), c_set.end(),
[] (const vector<C>& lhs, const vector<C>& rhs) { return lhs[0].sat < rhs[0].sat; });
The main caveat in this solution is that the container is not inherently sorted when a C is removed. So the sorting above has to be called manually.

c++ - sorting a vector of custom structs based on frequency

I need to find the most frequent element in an array of custom structs. There is no custom ID to them just matching properties.
I was thinking of sorting my vector by frequency but I have no clue how to do that.
I'm assuming by frequency you mean the number of times an identical structure appears in the array.
You probably want to make a hash function (or overload std::hash<> for your type) for your custom struct. Then iterate over your array, incrementing the value on an unordered_map<mytype, int> for every struct in the array. This will give you the frequency in the value field. Something like the below would work:
std::array<mytype> elements;
std::unordered_map<mytype, int> freq;
mytype most_frequent;
int max_frequency = 0;
for (const mytype &el : elements) {
freq[el]++;
if (freq[el] > max_frequency) {
most_frequent = el;
}
}
For this to work, the map will need to be able to create a hash for the above function. By default, it tries to use std::hash<>. You are expressly allowed by the standard to specialize this template in the standard namespace for your own types. You could do this as follows:
struct mytype {
std::string name;
double value;
};
namespace std {
template <> struct hash<mytype> {
size_t operator()(const mytype &t) const noexcept {
// Use standard library hash implementations of member variable types
return hash<string>()(t.name) ^ hash<double>()(t.value)
}
}
}
The primary goal is to ensure that any two variables that do not contain exactly the same values will generate a different hash. The above XORs the results of the standard library's hash function for each type together, which according to Mark Nelson is probably as good as the individual hashing algorithms XOR'd together. An alternative algorithm suggested by cppreference's hash reference is the Fowler-Noll-Vo hash function.
Look at std::sort and the example provided in the ref, where you actually pass your own comparator to do the trick you want (in your case, use the frequencies). Of course, a lambda function can be used too, if you wish.

Convert STL map into a struct

I have a std::map<string, double> whose members look something like:
X = [{"N", 200}, {"sigma", 1.0}, {"T", .2}]
Now, given the struct foo Y:
struct foo {
int N;
double T;
};
Can I programmatically map the key/value pairs X -> Y without writing a custom class for each X -> Y type mapping? Note that:
X["sigma"] is not in Y, i.e. the mapping is not necessarily one-to-one
The type of Y.N is an int while X["N"] is a double.
I suspect the answer is no, unless some trickery is done at compile time.
Edit: It may not be clear what I'm looking for. A pseudo-code version for this example would look something like:
if("N" in X) -> Y.N = X["N"];
if("T" in X) -> Y.T = X["T"];
Or programmatically:
for key in Y:
if (key in X) -> Y.key = X[key]
No. C++ has no concept of reflection. At compile time, there's no "foo::N" string anymore. The compiler has converted all occurances of foo::N in the source code to a 0 byte offset within Foo objects. Also, you cannot enumerate class members at compile time.
You want to set a field in an object of structure type based on the value of key in the map's elements (which is a string). So, no it cannot be done at compile time.