I'm trying to write VHDL module that calls foreign subprograms and support both the VHDL-2008 VHPI interface and the Modelsim FLI interface. The VHDL-2008 mechanism to tag a foreign subprogram is:
atrribute foreign of some_subprogram : procedure is "VHPI libname;some_subprogram";
But Modelsim's FLI defines it as:
attribute foreign of some_subprogram : procedure is "some_subprogram libname";
I'd like to use the same entity/architecture pair for these since all of the VHDL is identical. All that is different is the foreign subprogram attribute. I've tried something like:
function get_foreign_attribute_string(func_name : in string; libname : in libname) return string;
attribute foreign of some_subprogram : procedure is get_foreign_attribute_string("some_subprogram", "libname");
However Modelsim rejects this saying that the foreign attribute is not a string literal.
I tried pushing the functions into a package, and have the attributes defined in the package body, but it requires that the attribute be attached to the function declaration.
Short of declaring two packages and selectively compiling based on the toolset, I'm not sure how this can be accomplished.
Andy ideas?
Edit: Here's a sample case.
library std; -- for foriegn attribute
use std.all;
entity foo is
generic
(
SIMULATOR : integer range 0 to 1 -- 0 = Modelsim FLI, 1 = VHDL-2008 VHPI
);
end entity foo;
architecture test of foo is
function get_foreign_attribute_string(func_name : in string; libname : in string) return string is
begin
case SIMULATOR is
when 0 =>
return func_name & " " & libname;
when 1 =>
return "VHPI " & libname & ";" & func_name;
end case;
end function;
procedure some_subprogram is
begin
report "some_subprogram";
end procedure;
attribute foreign of some_subprogram : procedure is get_foreign_attribute_string("some_subprogram", "libname");
begin
end architecture test;
Edit: Here's my first cut at a workaround:
library std; -- for foreign attribute
use std.all;
entity foo is
generic
(
SIMULATOR : integer range 0 to 1 -- 0 = Modelsim FLI, 1 = VHDL-2008 VHPI
);
end entity foo;
architecture test of foo is
procedure some_subprogram_mti is
begin
assert false;
end procedure some_subprogram_mti;
attribute foreign of some_subprogram_mti : procedure is "some_subprogram libname";
procedure some_subprogram_vhpi is
begin
assert false;
end procedure some_subprogram_vhpi;
attribute foreign of some_subprogram_vhpi : procedure is "VHPI libname;some_subprogram";
procedure some_subprogram is
begin
case SIMULATOR is
when 0 =>
some_subprogram_mti;
when 1 =>
some_subprogram_vhpi;
end case;
end procedure;
begin
end architecture test;
Unfortunately, this too fails since the simulator tries to bind the foreign functions during elaboration. And the _vhpi
versions will not bind.
Not really an answer, but too long for a comment:
This seems to be a special behaviour of the foreign
attribute. So, this code works fine on Modelsim:
entity ATTRIBUTE_TEST is
end entity ATTRIBUTE_TEST;
architecture ATTRIBUTE_TEST of ATTRIBUTE_TEST is
function get_foreign_attribute_string(func_name : in string; libname : in string) return string is
begin
return func_name & " " & libname;
end function;
procedure some_subprogram is
begin
report "some_subprogram";
end procedure;
attribute not_foreign : string;
attribute not_foreign of some_subprogram : procedure is get_foreign_attribute_string("some_subprogram", "libname");
begin
process
begin
report "process";
wait;
end process;
end architecture ATTRIBUTE_TEST;
Section 14.4.1 of the 1076-2008 states:
The elaboration of a declarative part consists of the elaboration of the declarative items, if any, in the order in which they are given in the declarative part. This rule holds for all declarative parts, with the following three exceptions:
...
c) A subprogram declarative part whose subprogram is decorated with the 'FOREIGN attribute defined in package STANDARD.
For these cases, the declarative items are not elaborated; instead, the design entity or subprogram is subject to implementation-dependent elaboration.
Which seems to be relevant here.