How to use convert for creation - type-conversion

Using "Void safety - complete", my code:
class TENSOR_SHAPE
create
default_create,
from_tuple
convert
from_tuple ({TUPLE [INTEGER]})
feature -- Initialization
from_tuple (a_shape: TUPLE [INTEGER])
...
I try to call this with:
local
s: TENSOR_SHAPE
do
s := [2, 4, 3, 5] -- convert from tuple?
I get "source of assignment is not compatible with target."
Target name: s
Target type: detachable TENSOR_SHAPE
Source type: attached TUPLE [INTEGER_32, ...]
on line "s := [2, 4, 3, 5]".
Why does the compiler say `s' is detachable?
Is this not how conversions are used?
thanks,
jjj

TUPLE [INTEGER] convert declaration will be selected when argument is a tuple containing a single INTEGER, for example:
s := [2]
Now in order to handle [2, 4, 3, 5] a matching declaration is required:
convert
from_tuple ({TUPLE [INTEGER, INTEGER, INTEGER, INTEGER]})
feature -- Initialization
from_tuple (a_shape: TUPLE [INTEGER, INTEGER, INTEGER, INTEGER])
Also an interesting moment here is that feature may actually accept a tuple subtype with smaller amount of items, so the following example will also work:
convert
from_tuple ({TUPLE [INTEGER, INTEGER, INTEGER, INTEGER]})
feature -- Initialization
from_tuple (a_shape: TUPLE [INTEGER])

Related

Matlab assignment error: dot indexing is not supported for variables of this type

I would like to create a function that adds a field to a struct with a previously defined value.
I defined:
myValue = [1, 3, 5]
And I wrote this function:
function new_field(myStruct, myName, myValue)
myStruct.(myName) = myValue(:);
end
But I get the error:
"Unable to perform assignment because dot indexing is not supported for variables of this type."
Where did I go wrong?

systemverilog unpacked array concatenation

I'm trying to create an unpacked array like this:
logic [3:0] AAA[0:9];
I'd like to initialize this array to the following values:
AAA = '{1, 1, 1, 1, 2, 2, 2, 3, 3, 4};
For efficiency I'd like to use repetition constructs, but that's when things are falling apart.
Is this not possible, or am I not writing this correctly? Any help is appreciated.
AAA = { '{4{1}}, '{3{2}}, '{2{3}}, 4 };
Firstly, the construct you are using is actually called the replication operator. This might help you in future searches, for example in the SystemVerilog LRM.
Secondly, you are using an array concatenation and not an array assignment in your last block of code (note the missing apostrophe '). The LRM gives the following (simple) example in Section 10.10.1 (Unpacked array concatenations compared with array assignment patterns) to explain the difference:
int A3[1:3];
A3 = {1, 2, 3}; // unpacked array concatenation
A3 = '{1, 2, 3}; // array assignment pattern
The LRM says in the same section that
...unpacked array concatenations forbid replication, defaulting, and
explicit typing, but they offer the additional flexibility of
composing an array value from an arbitrary mix of elements and arrays.
int A9[1:9];
A9 = {9{1}}; // illegal, no replication in unpacked array concatenation
Lets also have a look at the alternative: array assignment. In the same section, the LRM mentions that
...items in an assignment pattern can be replicated using syntax, such as '{ n{element} }, and can be defaulted using the default: syntax. However, every element item in an array assignment pattern must be of the same type as the element type of the target array.
If transforming it to an array assignment (by adding an apostrophe), your code actually translates to:
AAA = '{'{1,1,1,1}, '{2,2,2}, '{3,3}, 4};
This means that the SystemVerilog interpreter will only see 4 elements and it will complain that too few elements were given in the assignment.
In Section 10.9.1 (Array assignment patterns), the LRM says the following about this:
Concatenation braces are used to construct and deconstruct simple bit vectors. A similar syntax is used to support the construction and deconstruction of arrays. The expressions shall match element for element, and the braces shall match the array dimensions. Each expression item shall be evaluated in the context of an assignment to the type of the corresponding element in the array.
[...]
A syntax resembling replications (see 11.4.12.1) can be used in array assignment patterns as well. Each replication shall represent an entire single dimension.
To help interprete the bold text in the quote above, the LRM gives the following example:
int n[1:2][1:3] = '{2{'{3{y}}}}; // same as '{'{y,y,y},'{y,y,y}}
You can't do arbitrary replication of unpacked array elements.
If your code doesn't need to be synthesized, you can do
module top;
typedef logic [3:0] DAt[];
logic [3:0] AAA[0:9];
initial begin
AAA = {DAt'{4{1}}, DAt'{3{2}}, DAt'{2{3}}, 4};
$display("%p",AAA);
end
endmodule
I had another solution but I'm not sure if it is synthesizable. Would a streaming operator work here? I'm essentially taking a packed array literal and streaming it into the data structure AAA. I've put it on EDA Playground
module tb;
logic [3:0] AAA[0:9];
initial begin
AAA = { >> int {
{4{4'(1)}},
{3{4'(2)}},
{2{4'(3)}},
4'(4)
} };
$display("%p",AAA);
end
endmodule
Output:
Compiler version P-2019.06-1; Runtime version P-2019.06-1; Mar 25 11:20 2020
'{'h1, 'h1, 'h1, 'h1, 'h2, 'h2, 'h2, 'h3, 'h3, 'h4}
V C S S i m u l a t i o n R e p o r t
Time: 0 ns
CPU Time: 0.580 seconds; Data structure size: 0.0Mb
Wed Mar 25 11:20:07 2020
Done

How to properly declare an N-dimensional queue inline in SystemVerilog?

If I have 2D queue of ints, I would expect to be able to declare it inline like so:
int my_queue[$][$] = {{1, 2}, {3, 4}};
I have also seen
typedef int int_queue[$];
int_queue my_queue[$] = {{1, 2}, {3, 4}};
Instead, when I compile, VCS provides me with an Incompatible Complex Type error:
Type of source expression is incompatible with type of target expression.
Mismatching types cannot be used in assignments, initializations and
instantiations. The type of the target is 'int$[$][$]', while the type of
the source is 'bit[63:0]'.
Which implies to me that VCS expects the right hand side of the equation to be cast properly. The way around this that I have been using is:
typedef int int_queue[$];
typedef int_queue int_queue_of_queues[$];
int_queue_of_queues my_queue = int_queue_of_queues'{{1, 2}, {3, 4}};
But this adds N extra typedefs and lines for N dimensions, and I would rather do this in one line. If I had a way to cast the right hand side of the declaration without a typedef, then this would be simple, but I don't know if that is possible.
The array concatenation syntax only works on a single dimension. You cannot nest the {}'s because of cases where there is ambiguity between array {} and integral {} concatenation. You need to use array assignment pattern in the outer, or both dimensions. I prefer using assignment patterns for both dimensions making it clearer that these are array elements, not integral concatenations.
int my_queue[$][$] = '{'{1, 2}, '{3, 4}};
See section 10.10 Unpacked array concatenation in the IEEE 1800-2017
LRM.

type char to type num mapping

q)type variable
returns the type num of the arguement variable.
Is there a mapping that can produce the type char from a type num or do I have to create that dictionary myself?
Ideally something like
q)typeChar 1
i
You can use .Q.t.
q).Q.t abs type `test
"s"
q).Q.t abs type 5i
"i"
Edit: Or even better just use .Q.ty
This seems to return upper case for atoms and lower case for lists.
q).Q.ty `test
"S"
q).Q.ty `test`test2
"s"
One option is to use 'key' function :
Reference: http://code.kx.com/q/ref/metadata/#key
Wiki says: Given a simple list, returns the name of the type as a symbol:
So you can make function like:
q) tyeInChar:{key x,()}
q) typeInChar 1i // output `int
q) typeInChar "s" //output `char

Elixir quote record(Turn it into a tuple) and preserve data?

When quoted using quote do: records aren't converted to tuples containing the record fields:
iex(1)> quote do: is_bitstring("blah")
{:is_bitstring, [context: Elixir, import: Kernel], ["blah"]}
iex(2)> quote do: Computer.new("Test")
{{:., [], [{:__aliases__, [alias: false], [:Computer]}, :new]}, [], [[name: "Test"]]}
iex(3)> quote do: Computer.new("Test")
{{:., [], [{:__aliases__, [alias: false], [:Computer]}, :new]}, [], [[name: "Test"]]}
iex(4)> c = Computer.new("Test")
Computer[name: "Test", type: nil, processor: nil, hard_drives: []]
iex(5)> c
Computer[name: "Test", type: nil, processor: nil, hard_drives: []]
iex(6)> quote do: c
{:c, [], Elixir}
Also, when I try doing this in my code:
defmacro computer([do: code]) do
# macro login here
# build computer record based on macro logic
computer = Computer.new(params)
quote do: unquote computer
end
I get an error:
** (CompileError) elixir/test/lib/computer_dsl_test.exs: tuples in quoted expressions must have 2 or 3 items, invalid quoted expression: Computer[name: "", type: nil, processor: nil, hard_drives: []]
I thought that records were just tuples with wrappers functions of some sort. The Elixir Getting Started guide states "A record is simply a tuple where the first element is the record module name." Is there something I am missing? Is there a function I can call on a record to get the tuple representation? I am aware of the raw: true option but I am not sure how to use that on an existing record.
Any insights?
Records are tuples. The output you see on the console is just formatted for easier inspection. You can check that records are tuples if you inspect them with raw: true:
iex(1)> defrecord X, a: 1, b: 2
iex(2)> x = X.new
X[a: 1, b: 2] # This is formatted output. x is really a tuple
iex(3)> IO.inspect x, raw: true
{X, 1, 2}
As can be seen, a record instance is really a tuple. You can also pattern match on it (although I don't recommend this):
iex(4)> {a, b, c} = x
iex(8)> a
X
iex(9)> b
1
iex(10)> c
2
The quote you are mentioning serves completely different purpose. It turns an Elixir expression into AST representation that can be injected into the rest of the AST, most often from the macro. Quote is relevant only in compile time, and as such, it can't even know what is in your variable. So when you say:
quote do: Computer.new("Test")
The result you get is AST representation of the call of the Computer.new function. But the function is not called at this point.
Just reading the error message and the elixir "getting stated" on macro definition it appears that the result of a quote has the form:
In general, each node (tuple) above follows the following format:
{ tuple | atom, list, list | atom }
The first element of the tuple is an atom or another tuple in the same representation;
The second element of the tuple is an list of metadata, it may hold information like the node line number;
The third element of the tuple is either a list of arguments for the function call or an atom. When an atom,
it means the tuple represents a variable.
Besides the node defined above, there are also five Elixir literals that when quoted return themselves (and not a tuple). They are:
:sum #=> Atoms
1.0 #=> Numbers
[1,2] #=> Lists
"binaries" #=> Strings
{key, value} #=> Tuples with two elements
My guess is that the unquote is the reverse function of quote, and so it expects as argument one of the above forms. This is not the case for the computer record.
I think the unquote is not necessary there (although I didn't try to understand the intent of your code...) and that
defmacro computer([do: code]) do %% why do you need this argument?
quote do: Computer.new
end
should be ok.