hneemann / Digital

A digital logic designer and circuit simulator.
GNU General Public License v3.0
4.28k stars 435 forks source link

External File HDL generation fails with out-of-file line numbers #1045

Open SonoSooS opened 1 year ago

SonoSooS commented 1 year ago

More often than not, when I'm trying to import a complex HDL code into the simulation, and I get a popup with a bunch of errors for a file which is only the extension (.v or .vhdl is the filename in the popup), and the line numbers are always outside of the last line of the file I'm trying to import.

Having temporarily replaced GHDL with a blocking program allowed me to inspect the actual line numbers in the TEMP folder before they got deleted, and all I can see is that Digital fails to parse the file, even though it is a valid HDL. Instead of stopping the assembly process with an error message, it is silently using the empty component name instead with a default port mapping, which ends up failing to assembly due to syntax error caused by the missing component name.

This happens both with VHDL and Verilog.

image

hneemann commented 1 year ago

The parser used to extract the interface definition directly from the hdl code has some weaknesses. It does not cope with every file. In these cases, you can simply enter the interface definition into the corresponding fields by hand.

If errors occur that have larger line numbers than used in the file, it is because the interface definition is not correct. Special code is attached to the hdl code, which handles the data exchange between the simulator and the running hdl code, which is done via stdio, similar to piping applications on the console. If the interface definition is not correct, this interface code cannot exchange data with the actual hdl code.

SonoSooS commented 1 year ago

Ah, you're right! I tried to instantiate a generic Verilog module, and as long as I type in the port mapping manually so it matches the default parameters then I can get it to work. But if I specify a different port size, then it fails (for obvious reasons, because I can't specify generic parameters).

As for the VHDL code, I'm really pushing the limitations of both VHDL, GHDL, and the UI of the External File module. Because I can't do

`ifndef EDA_SIMULATION_TOOL
`include "whatever_dependency.v"
`endif

in VHDL, I figured I could specify the dependency list via an at-file (that is, @listfile.txt containing filenames on each line). However the problem is that passing that at-file to the first command works as expected, but passing that same at-file to the 2nd invocation causes an error, because it tries to interpret the filenames as a module names (-e expects a module name as opposed to a filename), so that's where I got stuck. If I manually run the commands properly (that is, I pass the parameters as-is, except I also pass the at-file in the -a invocation) then I do get to a run interface (although GHDL does crash, but that is an issue in GHDL).

I could get it to work manually (without a crash) if I made a dummy relay (that is, just connect every input and output of a given module), GHDL -a every file into a fixed --workdir (including the one specified by the External File module), put the filename of the dummy relay into the Program code field, and put the --workdir into the GHDL Options textbox.

I guess I'm maybe pushing the limits of the Exernal File module a bit too much 😅

It would be great if I could at least somehow specify generic parameters (tried a generic init code, I guess it doesn't work for Exeternal File), and I'm fine with entering inputs and outputs by hand (due to the parser's limitations).

Oh also, it was really complicated to debug the issue, because any generated output is suppressed, and/or instantly deleted as soon as they are no longer needed. It would be great if there was an option to either redirect the output of GHDL/IVerilog to console/log file, and/or to keep generated files when an error occurs, so I can investigate what I did wrong without having to tediously run the commands manually, and also without replacing ghdl.exe with cmd.exe so I could copy off the generated files before they got deleted.

DTSchotanus commented 2 weeks ago

Hi I've had some issues with the usage of external files that use port mapping in VHDL. Say for example byte_2hex.vhd has two entities of decoder4_7segment.vhd.

byte_2hex.vhd

library ieee;
use ieee.std_logic_1164.all;

entity byte_2hex is 

    port 
    (
        a: in std_logic_vector (7 downto 0);
        y: out std_logic_vector (13 downto 0)
    );
end byte_2hex;

architecture beh of byte_2hex is
    component decoder4_7segment
        port(
            a:  in std_logic_vector(3 downto 0);
            y: out std_logic_vector(6 downto 0)
        );

    end component decoder4_7segment;

    begin
        msb:    decoder4_7segment port map(a(7 downto 4), y(13 downto 7));
        lsb:    decoder4_7segment port map(a(3 downto 0), y(6 downto 0));
end beh;

decoder4_7segment.vhd

library ieee;
use ieee.std_logic_1164.all;

entity decoder4_7segment is 

    port 
    (
        a: in  std_logic_vector(3 downto 0);
        y: out std_logic_vector(6 downto 0)
    );
end decoder4_7segment;

architecture beh of decoder4_7segment is

begin
    process(all) begin
        case a is
            when "0000" => y <= "1111110"; --0
            when "0001" => y <= "0110000"; --1
            when "0010" => y <= "1101101"; --2
            when "0011" => y <= "1111001"; --3
            when "0100" => y <= "0110011"; --4
            when "0101" => y <= "1011011"; --5
            when "0110" => y <= "1011111"; --6
            when "0111" => y <= "1110000"; --7
            when "1000" => y <= "1111111"; --8
            when "1001" => y <= "1111011"; --9
            when "1010" => y <= "1110111"; --A
            when "1011" => y <= "0011111"; --B
            when "1100" => y <= "1001110"; --C
            when "1101" => y <= "0111101"; --D
            when "1110" => y <= "1001111"; --E
            when "1111" => y <= "1000111"; --F
            when others => y <= "0000000"; --
        end case;
    end process;

end beh;

Digital seems to make a temporary copy of my byte_2hex.vhd file which it uses in the simulation, but since it does not automatically copy decoder4_7segment.vhd it cannot get to that file in runtime. This causes an issue:

afbeelding

I've been able to work around this issue by having a separate work-obj08.cf file which includes the paths to the original byte_2hex.vhd and decoder4_7segment.vhd. For the people that run into this issue as well: you can generate this file using ghdl analyze on both files. Then using the following GHDL options (options tab) --std=08 --ieee=synopsys --workdir="<path to work-obj08.cf>" --warn-no-library You should be able to import the byte_2hex.vhd component correctly. Be aware that since Digital still makes a copy of the byte_2hex.vhd, You need to add the --warn-no-library option to it, in order to suppress that error.

Please let me know whether there are more elegant workarounds. Otherwise it would be appreciated if there was a feature within Digital to make it easier to import entities that contain for example port mappings.