# Signals in objects vs. function arguments or method calls

**URL:** <https://discourse.myhdl.org/t/signals-in-objects-vs-function-arguments-or-method-calls/237>\
**Category:** Support\
**Created:** [October 27, 2017, 5:41pm UTC](https://discourse.myhdl.org/t/signals-in-objects-vs-function-arguments-or-method-calls/237 "2017-10-27T17:41:40Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![jsyk](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/jsyk/32/76_2.png) [@jsyk](https://discourse.myhdl.org/u/jsyk)\
**Post date:** [October 27, 2017, 5:41pm UTC](https://discourse.myhdl.org/t/signals-in-objects-vs-function-arguments-or-method-calls/237/1 "2017-10-27T17:41:40Z")

</div>

Hello,  
I am new to MyHDL and trying to understand what’s possible to do with it compared to VHDL. In the past I did some work in VHDL on FPGAs.  
My question: I want to put signals into objects and use them as interfaces between modules (similar like the class Ififobus in rhea). I want to define methods in the class that would take care of common operations on the signals. Of course in the end I want to export everything to VHDL and run on FPGA 🙂  
But my code experiments indicate MyHDL code generator does not understand method calls, nor function calls with object arguments.  
This is my testing code:

```
from myhdl import Signal, delay, Simulation, always_comb, instance, intbv, bin, toVerilog, modbv, ResetSignal, always_seq, toVHDL, block

m = 8

@block
def IncStru3(count, enable, clock, reset):
    class Subcluster:
        cnt2 = Signal(modbv(0)[m:])

    class Cluster:
        cnt1 = Signal(modbv(0)[m:])
        sc = Subcluster()

        # experiment 1
        def doThingMethod(self):
            self.cnt1.next = r.cnt1 + 1
            self.sc.cnt2.next = r.sc.cnt2 - 1

    # experiment 2
    def doThingClassArg(r):
        r.cnt1.next = r.cnt1 + 1
        r.sc.cnt2.next = r.sc.cnt2 - 1

    # experiment 3
    def doThingSignalArg(cnt1, cnt2):
        cnt1.next = cnt1 + 1
        cnt2.next = cnt2 - 1

    r = Cluster()

    @always_seq(clock.posedge, reset=reset)
    def incLogic():
        if enable:
            # experiment 4: works fine
            # r.cnt1.next = r.cnt1 + 1
            # r.sc.cnt2.next = r.sc.cnt2 - 1
            # 
            doThingSignalArg(r.cnt1, r.sc.cnt2) # works fine
            # doThingClassArg(r) # error: Unsupported attribute: cnt1
            # r.doThingMethod() # error: Not supported: method call: 'doThingMethod'

    @always_comb
    def outLogic():
        count.next = r.cnt1 | r.sc.cnt2

    return incLogic, outLogic

count = Signal(modbv(0)[m:])
enable = Signal(bool(0))
clock = Signal(bool(0))
reset = ResetSignal(0, active=0, async=True)

inc_inst = IncStru3(count, enable, clock, reset)
inc_inst.convert(hdl="VHDL", path="inc_sy")
inc_inst.convert(hdl="Verilog", path="inc_sy")

```

I use MyHDL 1.0dev (from github). In the example the functions doThingClassArg() and doThingMethod() fail in convertsion. Am I doing something wrong?

Regards,  
Jaroslav

---

<div class="post-metadata">

**Author:** ![josyb](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/josyb/32/5_2.png) [@josyb](https://discourse.myhdl.org/u/josyb)\
**Post date:** [October 28, 2017, 10:17am UTC](https://discourse.myhdl.org/t/signals-in-objects-vs-function-arguments-or-method-calls/237/2 "2017-10-28T10:17:34Z")

</div>

Can you post the _converted_ VHDL code?

---

<div class="post-metadata">

**Author:** ![josyb](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/josyb/32/5_2.png) [@josyb](https://discourse.myhdl.org/u/josyb)\
**Post date:** [October 28, 2017, 3:43pm UTC](https://discourse.myhdl.org/t/signals-in-objects-vs-function-arguments-or-method-calls/237/3 "2017-10-28T15:43:32Z")

</div>

I checked it twice (first in my local tree which is both behind and leading the _official_ repo) and with a freshly installed _official_ package.  
This line in the code:

```python
            doThingSignalArg(r.cnt1, r.sc.cnt2) # works fine

```

does convert to VHDL, but the VHDL itself is not OK. The _function called_ gets converted to

```auto
procedure MYHDL2_doThingSignalArg(
    cnt1: inout unsigned;
    cnt2: inout unsigned) is
begin
    cnt1 <= (cnt1 + 1);
    cnt2 <= (cnt2 - 1);
end procedure MYHDL2_doThingSignalArg;

```

If nothing specified the arguments to a procedure are variables and then we need the `:=` to assign values. Or we need to qualify the arguments as a `signal`

```auto
procedure MYHDL2_doThingSignalArg(
    signal cnt1: inout unsigned;
    signal cnt2: inout unsigned) is
begin
    cnt1 <= (cnt1 + 1);
    cnt2 <= (cnt2 - 1);
end procedure MYHDL2_doThingSignalArg;

```

As you want to modify the arguments, the `signal` is appropriate.

---

<div class="post-metadata">

**Author:** ![jsyk](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/jsyk/32/76_2.png) [@jsyk](https://discourse.myhdl.org/u/jsyk)\
**Post date:** [October 28, 2017, 3:50pm UTC](https://discourse.myhdl.org/t/signals-in-objects-vs-function-arguments-or-method-calls/237/4 "2017-10-28T15:50:01Z")

</div>

Hi,  
this is the converted code with just the function doThingSignalArg() used.

```
-- File: inc_sy/IncStru3.vhd
-- Generated by MyHDL 1.0dev
-- Date: Sat Oct 28 17:40:50 2017

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use std.textio.all;

use work.pck_myhdl_10.all;

entity IncStru3 is
    port (
        count: out unsigned(7 downto 0);
        enable: in std_logic;
        clock: in std_logic;
        reset: in std_logic
    );
end entity IncStru3;

architecture MyHDL of IncStru3 is

signal r_sc_cnt2: unsigned(7 downto 0);
signal r_cnt1: unsigned(7 downto 0);

procedure MYHDL2_doThingSignalArg(
    cnt1: inout unsigned;
    cnt2: inout unsigned) is
begin
    cnt1 <= (cnt1 + 1);
    cnt2 <= (cnt2 - 1);
end procedure MYHDL2_doThingSignalArg;

begin

INCSTRU3_INCLOGIC: process (clock, reset) is
begin
    if (reset = '0') then
    elsif rising_edge(clock) then
        if bool(enable) then
            MYHDL2_doThingSignalArg(r_cnt1, r_sc_cnt2);
        end if;
    end if;
end process INCSTRU3_INCLOGIC;

count <= (r_cnt1 or r_sc_cnt2);

end architecture MyHDL;

```

The other ones (doThingClassArg(), doThingMethod()) throw exceptions during codegen, therefore there is no code output. I would like that all three ways of writing the code would generate essentially the identical code which is shown above.

```
        doThingClassArg(r) # --> exception Unsupported attribute: cnt1
        r.doThingMethod() # --> exception Not supported: method call: 'doThingMethod'

```

Regards,  
Jaroslav

---

<div class="post-metadata">

**Author:** ![josyb](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/josyb/32/5_2.png) [@josyb](https://discourse.myhdl.org/u/josyb)\
**Post date:** [October 28, 2017, 4:16pm UTC](https://discourse.myhdl.org/t/signals-in-objects-vs-function-arguments-or-method-calls/237/5 "2017-10-28T16:16:51Z")

</div>

I guess our replies crossed …  
Yes, but that VHDL code is not valid. It should be like the second one in my reply.  
So **none** of the 3 approaches work.  
doThingClassArg() fails:

```auto
myhdl.ConversionError: in file C:\Users\josy\myhdlsupport\jsyk\jsyk.py, line 27:
    Unsupported attribute: cnt1

```

This is difficult to fix as the object `r` can not be uniquely identified. This is a major flaw in the `interface` type as used in MyHDL. as it simply inherits from the base object type.

doThingMethod() throws:

```auto
myhdl.ConversionError: in file C:\Users\josy\myhdlsupport\jsyk\jsyk.py, line 46:
    Not supported: method call: 'doThingMethod'

```

This looks easy to correct as in \_analyze.py (lines 614 to 650) we could copy/paste/modify the code as under `elif isinstance(f, FunctionType):`, which I tried (quite q while back) but didn’t succeed yet. As I don’t use _procedures_ in my code, I must have abandoned that path (lack of time, or lost focus).

Regards,

Josy

---

<div class="post-metadata">

**Author:** ![jsyk](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/jsyk/32/76_2.png) [@jsyk](https://discourse.myhdl.org/u/jsyk)\
**Post date:** [October 28, 2017, 6:06pm UTC](https://discourse.myhdl.org/t/signals-in-objects-vs-function-arguments-or-method-calls/237/6 "2017-10-28T18:06:48Z")

</div>

Hi,  
In the case of doThingSignalArg() we can fix the code-gen in \_toVHDL.py - lines 1938-1942:

```
--- a/myhdl/conversion/_toVHDL.py
+++ b/myhdl/conversion/_toVHDL.py
@@ -1935,8 +1935,11 @@ class _ConvertTaskVisitor(_ConvertVisitor):
             input = name in self.tree.inputs
             inout = input and output
             dir = (inout and "inout") or (output and "out") or "in"
+ kind = ""
+ if isinstance(obj, _Signal):
+ kind += "signal"
             self.writeline()
- self.writeDeclaration(obj, name, dir=dir, constr=False, endchar="")
+ self.writeDeclaration(obj, name, kind=kind, dir=dir, constr=False, endchar="")
 
     def visit_FunctionDef(self, node):
         self.write("procedure %s" % self.tree.name)

```

Then I get correct VHDL code with signals:

```
procedure MYHDL2_doThingSignalArg(
    signal cnt1: inout unsigned;
    signal cnt2: inout unsigned) is
begin
    cnt1 <= (cnt1 + 1);
    cnt2 <= (cnt2 - 1);
end procedure MYHDL2_doThingSignalArg;

```

So that was rather easy 🙂

Regarding the doThingClassArg( r): I have added a print into \_AnalyzeVisitor.getAttr():

`print("getAttr: obj=%s, dir(obj)={%s}" % (obj, dir(obj)))`

It is the function which throws the exception. I get this output just before the exception:

`getAttr: obj=< __main__.IncStru3.<locals>.Cluster object at 0x7fbfb3be34e0>, dir(obj)={[' __class__', ' __delattr__', ' __dict__', ' __dir__', ' __doc__', ' __eq__', ' __format__', ' __ge__', ' __getattribute__', ' __gt__', ' __hash__', ' __init__', ' __le__', ' __lt__', ' __module__', ' __ne__', ' __new__', ' __reduce__', ' __reduce_ex__', ' __repr__', ' __setattr__', ' __sizeof__', ' __str__', ' __subclasshook__', ' __weakref__', 'cnt1', 'doThingMethod', 'sc']}`

Python tells me to which object the variable `obj` is bound to. Therefore I think identification of instance should be easy. - hmm…

Regards,  
Jaroslav

---

<div class="post-metadata">

**Author:** ![josyb](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/josyb/32/5_2.png) [@josyb](https://discourse.myhdl.org/u/josyb)\
**Post date:** [October 28, 2017, 6:21pm UTC](https://discourse.myhdl.org/t/signals-in-objects-vs-function-arguments-or-method-calls/237/7 "2017-10-28T18:21:25Z")

</div>

That is one fix. But you may only want to prefix `signal` on _inout_ and _out_ arguments 😟

> [@jsyk](#):
>
> Python tells me to which object the variable obj is bound to. Therefore I think identification of instance should be easy. - hmm…

hmm … As _Cluster_ is derived from `object` there is no way that the MyHDL code can _in a positive way_ find out about your intentions.  
If Cluster was derived from a known class in MyHDL (like my experimental `StructType`) we can test for that property.

Regards,  
Josy

---

<div class="post-metadata">

**Author:** ![jsyk](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/jsyk/32/76_2.png) [@jsyk](https://discourse.myhdl.org/u/jsyk)\
**Post date:** [October 31, 2017, 7:43pm UTC](https://discourse.myhdl.org/t/signals-in-objects-vs-function-arguments-or-method-calls/237/8 "2017-10-31T19:43:05Z")

</div>

Hi,  
I don’t understand why IN arguments couldn’t be SIGNALs? This modified code with one IN signal and one OUT signal:

```
# experiment 3
def doThingSignalArg(cnt1, cnt2): # cnt1 in, cnt2 out
    cnt2.next = cnt1 - 1

```

Generates:

```
procedure MYHDL2_doThingSignalArg(
    signal cnt1: in unsigned;
    signal cnt2: out unsigned) is
begin
    cnt2 <= (cnt1 - 1);
end procedure MYHDL2_doThingSignalArg;

```

which seems to me just fine.

Then I tried making the IN argument a computed value (not a signal):

```
doThingSignalArg(r.cnt1 | r.sc.cnt2, r.sc.cnt2)

```

generates:

```
procedure MYHDL2_doThingSignalArg(
    cnt1: in integer;
    signal cnt2: out unsigned) is
begin
    cnt2 <= to_unsigned(cnt1 - 1, 8);
end procedure MYHDL2_doThingSignalArg;
...
 MYHDL2_doThingSignalArg((r_cnt1 or r_sc_cnt2), r_sc_cnt2);

```

which also seems fine - the function argument becomes now a variable (through a process I don’t understand at the moment 😕). The last VHDL code has a different problem: there should be a conversion to integer in the procedure call: `to_integer(r_cnt1 or r_sc_cnt2)`.

Regards,  
Jaroslav

---

<div class="post-metadata">

**Author:** ![josyb](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/josyb/32/5_2.png) [@josyb](https://discourse.myhdl.org/u/josyb)\
**Post date:** [November 1, 2017, 10:26am UTC](https://discourse.myhdl.org/t/signals-in-objects-vs-function-arguments-or-method-calls/237/9 "2017-11-01T10:26:50Z")

</div>

> [@jsyk](#):
>
> I don’t understand why IN arguments couldn’t be SIGNALs?

There is one observation with the code: (perhaps) it should also handle the _variable_ case.  
It is not necessary to specify the nature of the `in` argument. And the direction defaults to `in`as well.  
See also the next section

> [@jsyk](#):
>
> ```auto
> doThingSignalArg(r.cnt1 | r.sc.cnt2, r.sc.cnt2)
> 
> ```
> 
> generates:
> 
> ```auto
> procedure MYHDL2_doThingSignalArg(
> cnt1: in integer;
> signal cnt2: out unsigned) is
> begin
> cnt2 &lt;= to_unsigned(cnt1 - 1, 8);
> end procedure MYHDL2_doThingSignalArg;
> ...
> MYHDL2_doThingSignalArg((r_cnt1 or r_sc_cnt2), r_sc_cnt2);
> 
> ```
> 
> which also seems fine - the function argument becomes now a variable

Actually the `cnt1` argument is a constant, but the classes of procedure/function arguments in VHDL are somewhat obscure matter:

- [http://www.vhdl.renerta.com/mobile/source/vhd00052.htm](http://www.vhdl.renerta.com/mobile/source/vhd00052.htm)
- [Lesson three: functions, procedures, packages, ..](http://www.pldworld.com/_hdl/1/www.ireste.fr/fdl/vcl/lesd/les_3.htm)
- [http://www.ics.uci.edu/~jmoorkan/vhdlref/procedur.html](http://www.ics.uci.edu/~jmoorkan/vhdlref/procedur.html)

Let’s look at the generated VHDL call:

```auto
MYHDL2_doThingSignalArg((r_cnt1 or r_sc_cnt2), r_sc_cnt2);

```

In VHDL `(r_cnt1 or r_sc_cnt2)` produces an `unsigned` which is then passed on to the procedure. So `cnt1` should be declared to be an `unsigned` argument rather than an `integer`. I don’t have an idea whether this produced `unsigned` is a signal, a variable, or even something else, so leaving out the class specifier in the procedure declaration for this `in` argument seems the plausible thing to do.  
Simulating in MyHDL is different, it effectively computes integer values which are then passed to the function. In fact for any Signal (or variable or constant) it will pass the integer value. Unfortunately the conversion follows this way of thinking.  
So you can’t use expressions inside a function or procedure call.

Regards,  
Josy
