ghdl / ghdl

VHDL 2008/93/87 simulator
GNU General Public License v2.0
2.39k stars 363 forks source link

Error when entity name is the same as port name #542

Open Bamban opened 6 years ago

Bamban commented 6 years ago

Hi, I have a problem with entity name clashing with port name. My code is compiling with Modelsim but not GHDL. Here is the component interface:

entity ami_write is
    port(
                clk               : in std_logic;
                resetn            : in std_logic;
                ami_write         : out std_logic
            );
end ami_write;

The compilation fails when declaring component then instantiating. In vhdl93, it fails at the declaration with:

ghdl -a -g ../rtl_src/ami_write.vhd ../rtl_src/write_loop.vhd ../rtl_src/fifo.vhd ../rtl_src/tb_write_loop.vhd
../rtl_src/write_loop.vhd:71:18:error: identifier "ami_write" already used for a declaration
../rtl_src/write_loop.vhd:26:32:error: previous declaration: port "ami_write"
../rtl_src/write_loop.vhd:99:26:error: component name expected, found port "ami_write"

In vhdl08, it fails at the instantiation with:

ghdl -a -g --std=08 ../rtl_src/ami_write.vhd ../rtl_src/write_loop.vhd ../rtl_src/fifo.vhd ../rtl_src/tb_write_loop.vhd
../rtl_src/write_loop.vhd:116:60:error: component "ami_write" not allowed in an expression
../rtl_src/write_loop.vhd:116:60:error: can't associate error with signal interface "ami_write"
../rtl_src/write_loop.vhd:116:60:error: (type of error is unknown)
../rtl_src/write_loop.vhd:88:40:error: (type of signal interface "ami_write" is std_logic)

The compilation works when using direct instantiation via "dut : entity work.ami_write(behavior)". I'm using this for the moment.

Is there something wrong I'm doing?

tgingold commented 6 years ago

It would be nice to have a reproducer, as it isn't easy to guess the details.

Bamban commented 6 years ago

Here it is. I commented the source code in wrapper.vhd to make it a little more clear what are the hacks to do depending on the std.

wrapper.vhd:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity wrapper is
    port(
    clk   : in std_logic;
    reset : in std_logic;
    write : in std_logic;
    ack   : out std_logic
);
end wrapper;

architecture a of wrapper is

    -- compiling with std=93 produces an error here
    component write is
        port(
                    clk   : in std_logic;
                    reset : in std_logic;
                    write : in std_logic;
                    ack   : out std_logic
                );
    end component;

begin

    --dut : entity work.write(a) -- compilation works with this type of instanciation/declaration, std=08 and component declaration on line 17 commented
    dut: component write
        port map(
                    clk   => clk,
                    reset => reset,
                    write => write, --compiling with std=08 produces a error here
                    ack   => ack
                );

end architecture;

write.vhd:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity write is
    port(
    clk   : in std_logic;
    reset : in std_logic;
    write : in std_logic;
    ack   : out std_logic
);
end write;

architecture a of write is
begin
    process (clk, reset) is
    begin
        if reset = '1' then
            ack <= '0';
        elsif rising_edge(clk) then
            if write = '1' then
                ack <= '1';
            else
                ack <= '0';
            end if;
        end if;
    end process;
end architecture;

wrapper.vhd.txt write.vhd.txt

First try, std=93

Source code as it is How I try to analyze it and the error:

$ ghdl -a -g write.vhd wrapper.vhd 
wrapper.vhd:16:18:error: identifier "write" already used for a declaration
wrapper.vhd:9:8:error: previous declaration: port "write"
wrapper.vhd:27:23:error: component name expected, found port "write"
ghdl:error: compilation error

Second try, std=08

Source code as it is. How I try to analyze it and the error:

$ ghdl -a -g --std=08 write.vhd wrapper.vhd 
wrapper.vhd:32:49:error: component "write" not allowed in an expression
wrapper.vhd:32:49:error: can't associate error with signal interface "write"
wrapper.vhd:32:49:error: (type of error is unknown)
wrapper.vhd:21:40:error: (type of signal interface "write" is std_logic)
ghdl:error: compilation error

Thrid try and success

Still std=08, remove component declaration (lines 17 to 24 in wrapper.vhd) and use component "direct" instantiation on line 28, remove line 29.

$ ghdl -a -g --std=08 write.vhd wrapper.vhd

No errors!

Some detail

$ ghdl --version
GHDL 0.35-dev (2017-03-01-340-gf802fc15) [Dunoon edition]
 Compiled with GNAT Version: 6.3.0
 llvm code generator
Written by Tristan Gingold.
tgingold commented 6 years ago

This is a little bit subtile as the rules have changed with vhdl 2002. Before vhdl 2002, the architecture and its entity forms one declarative region. As write is already declared as a port in wrapper, you cannot redeclare it as a component later. Hence the error message.

After vhdl 2002, the architecture is a nested declarative region. So the component 'write' overrides the port 'write'. But then in the component instantiation you use 'write' which refers to the component. Hence the error message.

I will try to make the error message more readable.

Bamban commented 6 years ago

Thanks for taking this into account.

So you're saying that m***lsim does not respect the VHDL standard because it does not issue any warning or errors for any of the 3 precedent cases?

Paebbels commented 6 years ago

@Bamban ModelSim has a commanline switch to enable a more strict mode. Have you tried this?

-pedanticerrors (optional) Forces display of an error message (rather than a warning) on a variety of conditions. Refer to “Enforcing Strict 1076 Compliance” for a complete list of these conditions. This argument overrides -nocasestaticerror and -noothersstaticerror (refer above).
You can also view a complete list of errors by executing the command: verror -kind vcom -pedanticerrors

tgingold commented 6 years ago

Yes, I don't see how this could be valid. Have you tried with another simulator ?

Paebbels commented 6 years ago

Aldec Riviera-PRO 2017.10 reports the following messages:

vcom -93 ...

C:\git\GitHub\Paebbels\ghdl\testsuite\gna\issue542 [paebbels/master ≡ +2 ~0 -0 !]> vcom -93 -work issue542 .\wrapper.vhd
Aldec, Inc. VHDL Compiler, build 2017.10.67
VLM Initialized with path: "C:\git\GitHub\Paebbels\ghdl\testsuite\gna\issue542\library.cfg".
DAGGEN WARNING DAGGEN_0523: "The source is compiled without the -dbg switch. Line breakpoints and assertion debug will not be available."
COMP96 File: .\wrapper.vhd
COMP96 Compile Entity "wrapper"
COMP96 Compile Architecture "a" of Entity "wrapper"
COMP96 ERROR COMP96_0122: "Symbol "write" has already been declared in this scope." ".\wrapper.vhd" 17 2
COMP96 Compile failure 1 Errors 0 Warnings  Analysis time :  0.0 [ms]

vcom ... (default = 2002)

C:\git\GitHub\Paebbels\ghdl\testsuite\gna\issue542 [paebbels/master ≡ +2 ~0 -0 !]> vcom -work issue542 .\wrapper.vhd
Aldec, Inc. VHDL Compiler, build 2017.10.67
VLM Initialized with path: "C:\git\GitHub\Paebbels\ghdl\testsuite\gna\issue542\library.cfg".
DAGGEN WARNING DAGGEN_0523: "The source is compiled without the -dbg switch. Line breakpoints and assertion debug will not be available."
COMP96 File: .\wrapper.vhd
COMP96 Compile Entity "wrapper"
COMP96 Compile Architecture "a" of Entity "wrapper"
COMP96 ERROR COMP96_0122: "Symbol "write" has already been declared in this scope." ".\wrapper.vhd" 17 2
COMP96 Compile failure 1 Errors 0 Warnings  Analysis time :  16.0 [ms]

vcom -2008 ...

C:\git\GitHub\Paebbels\ghdl\testsuite\gna\issue542 [paebbels/master ≡ +2 ~0 -0 !]> vcom -2008 -work issue542 .\wrapper.vhd
Aldec, Inc. VHDL Compiler, build 2017.10.67
VLM Initialized with path: "C:\git\GitHub\Paebbels\ghdl\testsuite\gna\issue542\library.cfg".
DAGGEN WARNING DAGGEN_0523: "The source is compiled without the -dbg switch. Line breakpoints and assertion debug will not be available."
COMP96 File: .\wrapper.vhd
COMP96 Compile Entity "wrapper"
COMP96 Compile Architecture "a" of Entity "wrapper"
COMP96 ERROR COMP96_0122: "Symbol "write" has already been declared in this scope." ".\wrapper.vhd" 17 2
COMP96 Compile failure 1 Errors 0 Warnings  Analysis time :  16.0 [ms]
Bamban commented 6 years ago

Here is the result for Modelsim Intel FPGA Edition.

vcom -2008 *.vhd
Model Technology ModelSim - Intel FPGA Edition vcom 10.5c Compiler 2017.01 Jan 23 2017
Start time: 15:26:36 on Mar 20,2018
vcom -2008 wrapper.vhd write.vhd 
-- Loading package STANDARD
-- Loading package TEXTIO
-- Loading package std_logic_1164
-- Loading package NUMERIC_STD
-- Compiling entity wrapper
-- Compiling architecture a of wrapper
** Error: wrapper.vhd(17): (vcom-1294) Declaration with designator "write" already exists in this region.
** =====> Prior declaration of "write" is at wrapper.vhd(9).
** Error: wrapper.vhd(33): ** Error: (vcom-1590) Bad expression in actual part of association element 'write'.
** Error: wrapper.vhd(37): VHDL Compiler exiting
End time: 15:26:37 on Mar 20,2018, Elapsed time: 0:00:01
Errors: 3, Warnings: 0

My first attempt with Modelsim Altera Edition did not raised any errors because ... it is complicated. I use Platform Designer (ex-Qsys) to create a subsystem. I then use the simulation scripts generated by Quartus for this system to analyze and elaborate my subsystem. In this case, the vcom command that concerns my faulty component (nested far away from my own simulation script) does not raise any errors, even in pedantic mode. I don't know why yet.

vicencb commented 6 years ago

Hi Tristan, in an earlier post you said: After vhdl 2002, the architecture is a nested declarative region.

but in the VHDL-08 LRM it says: A single declarative region is formed by the text of each of the following: a) An entity declaration, together with a corresponding architecture body

Aren't "nested" and "single" in contradiction? If no, where should I look in the LRM to get this clarified?

Regards,   Vicenç.

tgingold commented 6 years ago

You're right. I haven't remarked that this has changed again in vhdl 2008. So they are nested only in vhdl 2002...

tgingold commented 6 years ago

This is even more fun: there is no bar change in the vhdl LRM 2008, so it looks it was not intentional...

Bamban commented 6 years ago

A last question: Is it eventually correct to use the third method from VHDL 2008 or should I definitely avoid this naming clash in the future ?