P
Paul Uiterlinden
Recently I ran into a problem regarding dependencies between pakcages.
It has always been my understanding (and still is, until proven
otherwise) that dependencies between VHDL design units is governed by
USE clauses. Furthermore, secondary design units depend on their
primary design units.
So if a package pkg_a has a USE work.pkg_b.ALL clause, package pkg_a
depends on package pkg_b. This means that package pkg_b must have
been analyzed before package pkg_a can be analyzed.
Further, if the package body of pkg_b has a USE work.pkg_a.ALL clause,
the package body of pkg_b depends on package pkg_a. Note that it is
not the PACKAGE, but the PACKAGE BODY of pkg_b that becomes dependent
on package pkg_a.
So in this case, the analyze order should be pkg_b, pkg_a, followed by
analyzing the package bodies in any order. There is no circular
dependency. Hence analyzing these packages and their bodies using
modelsim is OK.
Things change when you try to elaborate an architecture using one or
more of the mentioned packages. It turns out that using just pkg_a is
not OK, just pkg_b is OK. When using both packages, the order of use
clauses becomes important! This is something that I have not seen
before. I always thought that the order of use clauses does not
matter in VHDL (unlike the #include nightmare in C).
Below is the file that I sent to Mentor Graphics. I got a reply from
an AE with which I am not quite satisfied. He questions the semantics
of the provided packages and makes a false (IMHO) claim about
visibility rules. He is also fairly confident NC or VCS would also
detect the same dependency cycles and would not elaborate the
architectures.
So I would like to hear opinions about this behavior and whether it is
my understanding of VHDL or ModelSim's understanding that needs
adjustment. I would also like to know what happens if you try to load
and run the four architectures in other simulators, such as NC and
VCS (which I do not have acces to). I would be much obliged if
somebody could run this in NC and/or VCS and post the outcome here.
If the file below is malformed by word wrapping, it can be downloaded
from here: http://www.xs4all.nl/~puiterl/circular_dependency.vhd
----------------------------------------------------------------------
--
-- File : circular_dependency.vhd
--
-- Author(s) : Paul Uiterlinden
-- Email :
--
-- Creation Date : 2003-11-13
--
-- Simulator : ModelSim 6.2d
--
-- Contents : Demonstrates erroneously (IMHO) reporting of
-- cicular dependecies by ModelSim at elaboration
-- time (error vsim-3385) and a case where the order
-- of USE clauses makes a diffence.
--
-- In my opinion, these error should not have been
-- reported in the first place. Making a package
-- visible by a USE clause creates a dependency to
-- the package, never to the package body.
--
-- Furthermore, the order of USE clauses now makes a
-- difference! Depending on the order of USE clauses,
-- the circular dependency is reported or not.
-- Different behaviour caused by order of USE clause
-- should never happen.
--
----------------------------------------------------------------------
-- Copyright
----------------------------------------------------------------------
--
-- Copyright (C) 2006 AimCom B.V. Hilversum
-- AimCom - PROPRIETARY
--
-- Disclosure to third parties or reproduction in any form what-
-- soever), without prior written consent), is strictly forbidden
--
----------------------------------------------------------------------
----------------------------------------------------------------------
-- Package pkg_b
----------------------------------------------------------------------
PACKAGE pkg_b IS
TYPE b_type IS (b1, b2, b3);
PROCEDURE subpgm_b(i : b_type);
END PACKAGE pkg_b;
----------------------------------------------------------------------
-- Package pkg_a
----------------------------------------------------------------------
USE work.pkg_b.ALL;
PACKAGE pkg_a IS
PROCEDURE subpgm_a(i : b_type);
END PACKAGE pkg_a;
----------------------------------------------------------------------
-- Package body pkg_b
----------------------------------------------------------------------
USE work.pkg_a.ALL;
PACKAGE BODY pkg_b IS
PROCEDURE subpgm_b(i : b_type) IS
BEGIN
-- This call seems to be needed to cause a circular dependency
--
subpgm_a(i);
END PROCEDURE subpgm_b;
END PACKAGE BODY pkg_b;
----------------------------------------------------------------------
-- Package body pkg_a
----------------------------------------------------------------------
PACKAGE BODY pkg_a IS
PROCEDURE subpgm_a(i : b_type) IS
BEGIN
REPORT b_type'IMAGE(i);
END PROCEDURE subpgm_a;
END PACKAGE BODY pkg_a;
----------------------------------------------------------------------
-- Entity
----------------------------------------------------------------------
ENTITY ent IS
END ENTITY ent;
----------------------------------------------------------------------
-- Architecture, just using package pkg_a
----------------------------------------------------------------------
-- # Loading /mnt/appl/iccadm/MTI/mti_6.2d/linux/../std.standard
-- # Loading work.pkg_b (Header)
-- # Loading work.pkg_a (Header)
-- # Loading work.pkg_b(body)
-- # ** Fatal: (vsim-3385) Illegal circular dependency between
-- packages 'work.pkg_b' and 'work.pkg_a'.
-- # Time: 0 ps Iteration: 0 Instance: / File: NOFILE Line:
-- UNKNOWN
-- # FATAL ERROR while loading design
-- # Error loading design
USE work.pkg_a.ALL;
ARCHITECTURE arch_a OF ent IS
BEGIN
END ARCHITECTURE arch_a;
----------------------------------------------------------------------
-- Architecture, just using pkg_b
----------------------------------------------------------------------
-- # ** Note: b1
-- # Time: 0 ps Iteration: 0 Instance: /ent
USE work.pkg_b.ALL;
ARCHITECTURE arch_b OF ent IS
BEGIN
do_sim: PROCESS IS
BEGIN
subpgm_b(b1);
WAIT;
END PROCESS do_sim;
END ARCHITECTURE arch_b;
----------------------------------------------------------------------
-- Architecture, using pkg_a and then pkg_b
----------------------------------------------------------------------
-- # Loading /mnt/appl/iccadm/MTI/mti_6.2d/linux/../std.standard
-- # Loading work.pkg_b (Header)
-- # Loading work.pkg_a (Header)
-- # Loading work.pkg_b(body)
-- # ** Fatal: (vsim-3385) Illegal circular dependency between
-- packages 'work.pkg_b' and 'work.pkg_a'.
-- # Time: 0 ps Iteration: 0 Instance: / File: NOFILE Line:
-- UNKNOWN
-- # FATAL ERROR while loading design
-- # Error loading design
USE work.pkg_a.ALL;
USE work.pkg_b.ALL;
ARCHITECTURE arch_ab OF ent IS
BEGIN
do_sim: PROCESS IS
BEGIN
subpgm_a(b1);
subpgm_b(b1);
WAIT;
END PROCESS do_sim;
END ARCHITECTURE arch_ab;
----------------------------------------------------------------------
-- Architecture, using pkg_b and then pkg_a
----------------------------------------------------------------------
-- # ** Note: b1
-- # Time: 0 ps Iteration: 0 Instance: /ent
-- # ** Note: b1
-- # Time: 0 ps Iteration: 0 Instance: /ent
USE work.pkg_b.ALL;
USE work.pkg_a.ALL;
ARCHITECTURE arch_ba OF ent IS
BEGIN
do_sim: PROCESS IS
BEGIN
subpgm_a(b1);
subpgm_b(b1);
WAIT;
END PROCESS do_sim;
END ARCHITECTURE arch_ba;
It has always been my understanding (and still is, until proven
otherwise) that dependencies between VHDL design units is governed by
USE clauses. Furthermore, secondary design units depend on their
primary design units.
So if a package pkg_a has a USE work.pkg_b.ALL clause, package pkg_a
depends on package pkg_b. This means that package pkg_b must have
been analyzed before package pkg_a can be analyzed.
Further, if the package body of pkg_b has a USE work.pkg_a.ALL clause,
the package body of pkg_b depends on package pkg_a. Note that it is
not the PACKAGE, but the PACKAGE BODY of pkg_b that becomes dependent
on package pkg_a.
So in this case, the analyze order should be pkg_b, pkg_a, followed by
analyzing the package bodies in any order. There is no circular
dependency. Hence analyzing these packages and their bodies using
modelsim is OK.
Things change when you try to elaborate an architecture using one or
more of the mentioned packages. It turns out that using just pkg_a is
not OK, just pkg_b is OK. When using both packages, the order of use
clauses becomes important! This is something that I have not seen
before. I always thought that the order of use clauses does not
matter in VHDL (unlike the #include nightmare in C).
Below is the file that I sent to Mentor Graphics. I got a reply from
an AE with which I am not quite satisfied. He questions the semantics
of the provided packages and makes a false (IMHO) claim about
visibility rules. He is also fairly confident NC or VCS would also
detect the same dependency cycles and would not elaborate the
architectures.
So I would like to hear opinions about this behavior and whether it is
my understanding of VHDL or ModelSim's understanding that needs
adjustment. I would also like to know what happens if you try to load
and run the four architectures in other simulators, such as NC and
VCS (which I do not have acces to). I would be much obliged if
somebody could run this in NC and/or VCS and post the outcome here.
If the file below is malformed by word wrapping, it can be downloaded
from here: http://www.xs4all.nl/~puiterl/circular_dependency.vhd
----------------------------------------------------------------------
--
-- File : circular_dependency.vhd
--
-- Author(s) : Paul Uiterlinden
-- Email :
--
-- Creation Date : 2003-11-13
--
-- Simulator : ModelSim 6.2d
--
-- Contents : Demonstrates erroneously (IMHO) reporting of
-- cicular dependecies by ModelSim at elaboration
-- time (error vsim-3385) and a case where the order
-- of USE clauses makes a diffence.
--
-- In my opinion, these error should not have been
-- reported in the first place. Making a package
-- visible by a USE clause creates a dependency to
-- the package, never to the package body.
--
-- Furthermore, the order of USE clauses now makes a
-- difference! Depending on the order of USE clauses,
-- the circular dependency is reported or not.
-- Different behaviour caused by order of USE clause
-- should never happen.
--
----------------------------------------------------------------------
-- Copyright
----------------------------------------------------------------------
--
-- Copyright (C) 2006 AimCom B.V. Hilversum
-- AimCom - PROPRIETARY
--
-- Disclosure to third parties or reproduction in any form what-
-- soever), without prior written consent), is strictly forbidden
--
----------------------------------------------------------------------
----------------------------------------------------------------------
-- Package pkg_b
----------------------------------------------------------------------
PACKAGE pkg_b IS
TYPE b_type IS (b1, b2, b3);
PROCEDURE subpgm_b(i : b_type);
END PACKAGE pkg_b;
----------------------------------------------------------------------
-- Package pkg_a
----------------------------------------------------------------------
USE work.pkg_b.ALL;
PACKAGE pkg_a IS
PROCEDURE subpgm_a(i : b_type);
END PACKAGE pkg_a;
----------------------------------------------------------------------
-- Package body pkg_b
----------------------------------------------------------------------
USE work.pkg_a.ALL;
PACKAGE BODY pkg_b IS
PROCEDURE subpgm_b(i : b_type) IS
BEGIN
-- This call seems to be needed to cause a circular dependency
--
subpgm_a(i);
END PROCEDURE subpgm_b;
END PACKAGE BODY pkg_b;
----------------------------------------------------------------------
-- Package body pkg_a
----------------------------------------------------------------------
PACKAGE BODY pkg_a IS
PROCEDURE subpgm_a(i : b_type) IS
BEGIN
REPORT b_type'IMAGE(i);
END PROCEDURE subpgm_a;
END PACKAGE BODY pkg_a;
----------------------------------------------------------------------
-- Entity
----------------------------------------------------------------------
ENTITY ent IS
END ENTITY ent;
----------------------------------------------------------------------
-- Architecture, just using package pkg_a
----------------------------------------------------------------------
-- # Loading /mnt/appl/iccadm/MTI/mti_6.2d/linux/../std.standard
-- # Loading work.pkg_b (Header)
-- # Loading work.pkg_a (Header)
-- # Loading work.pkg_b(body)
-- # ** Fatal: (vsim-3385) Illegal circular dependency between
-- packages 'work.pkg_b' and 'work.pkg_a'.
-- # Time: 0 ps Iteration: 0 Instance: / File: NOFILE Line:
-- UNKNOWN
-- # FATAL ERROR while loading design
-- # Error loading design
USE work.pkg_a.ALL;
ARCHITECTURE arch_a OF ent IS
BEGIN
END ARCHITECTURE arch_a;
----------------------------------------------------------------------
-- Architecture, just using pkg_b
----------------------------------------------------------------------
-- # ** Note: b1
-- # Time: 0 ps Iteration: 0 Instance: /ent
USE work.pkg_b.ALL;
ARCHITECTURE arch_b OF ent IS
BEGIN
do_sim: PROCESS IS
BEGIN
subpgm_b(b1);
WAIT;
END PROCESS do_sim;
END ARCHITECTURE arch_b;
----------------------------------------------------------------------
-- Architecture, using pkg_a and then pkg_b
----------------------------------------------------------------------
-- # Loading /mnt/appl/iccadm/MTI/mti_6.2d/linux/../std.standard
-- # Loading work.pkg_b (Header)
-- # Loading work.pkg_a (Header)
-- # Loading work.pkg_b(body)
-- # ** Fatal: (vsim-3385) Illegal circular dependency between
-- packages 'work.pkg_b' and 'work.pkg_a'.
-- # Time: 0 ps Iteration: 0 Instance: / File: NOFILE Line:
-- UNKNOWN
-- # FATAL ERROR while loading design
-- # Error loading design
USE work.pkg_a.ALL;
USE work.pkg_b.ALL;
ARCHITECTURE arch_ab OF ent IS
BEGIN
do_sim: PROCESS IS
BEGIN
subpgm_a(b1);
subpgm_b(b1);
WAIT;
END PROCESS do_sim;
END ARCHITECTURE arch_ab;
----------------------------------------------------------------------
-- Architecture, using pkg_b and then pkg_a
----------------------------------------------------------------------
-- # ** Note: b1
-- # Time: 0 ps Iteration: 0 Instance: /ent
-- # ** Note: b1
-- # Time: 0 ps Iteration: 0 Instance: /ent
USE work.pkg_b.ALL;
USE work.pkg_a.ALL;
ARCHITECTURE arch_ba OF ent IS
BEGIN
do_sim: PROCESS IS
BEGIN
subpgm_a(b1);
subpgm_b(b1);
WAIT;
END PROCESS do_sim;
END ARCHITECTURE arch_ba;