假设我有一个包strkern (我有),它导出函数: strlen
package strkern is
function strlen(s: string) return natural;
end package strkern;我写了一个新的包stdstring,它定义了许多令人兴奋的新操作符,但也想重新导出strlen
use work.strkern.all;
package stdstring is
-- rexport strlen
-- define exciting new operators
end package stdstring所以如果一个代码
use work.stdstring.all;你得到strlen()和令人兴奋的新操作符。如何从子包“重新导出”函数/类型导入?没有使用新名称的虚拟实现,而只是调用“要导入的”实现
function strlen(s: string) return natural is
return strkern.strlen(s);
end function strlen;发布于 2020-11-26 00:52:34
通过提供一个最小的、完整的和可验证的示例:
package strkern is
function strlen(s: string) return natural;
end package strkern;
package body strkern is
function strlen(s: string) return natural is
begin
return s'length;
end function;
end package body;
use work.strkern.all; -- NOT USED in this foreshortened example
package stdstring is
-- rexport strlen
-- define exciting new operators
alias strlen is work.strkern.strlen [string return natural];
end package stdstring;
use work.stdstring.all;
entity foo is
end entity;
architecture fum of foo is
begin
assert false
report "strlen of ""abcde"" is " & integer'image(strlen("abcde"))
severity NOTE;
end architecture;我们可以演示如何在包中使用别名,以提供在另一个包中找到的函数声明的可见性。
ghdl -r foo
std_flub_up.vhdl:25:5:@0ms:(assertion note): strlen of "abcde" is 5问题代码片段没有演示任何“令人兴奋的新运算符”,其中运算符特定于VHDL中的预定义运算符。请参阅IEEE标准1076-2008 9.2运算符。
使用别名使名称可见的方法如6.6.3非对象别名所示。请注意,子程序的别名需要签名。
有些读者可能会好奇,为什么在上面的MCVe别名中可以看到所选的名称后缀strlen。请参见12.3可见性:
可见性是通过选择或直接实现的。在定义如下的位置,可通过选择来查看声明:
a)对于库中包含的主单元:在所选名称中的后缀的位置,其前缀表示库。
..。
f)对于在包声明中给出的声明,而不是在定义未实例化的包的包声明中:在其前缀表示包的选定名称中的后缀的位置。
...
基本上,选定的名称(work.strkern.strlen)后缀(strlen)声明出现在由前缀定义的单独名称空间中,该名称空间将指定一个主要单元(这里是库strkern中的package work)。通过规则a使包声明可见。通过规则f使后缀可见。通过隐式库声明使库work可见(请参见13.2设计库)。
发布于 2020-11-25 23:55:13
不能将一个包中的任何内容重新导出到另一个包中。唯一的选择是同时使用strkern包和stdstring包。
use work.strkern.all;
use work.stdstring.all;我建议不要创建虚拟实现,因为如果用户同时包含两个包,重复的函数签名将导致两者都不可见,因为编译器将不知道使用哪一个。用户必须明确说明要使用哪个函数:
work.strkern.strlen("Hello world");
work.stdstring.strlen("Hello world");您可以为第一个包中的函数创建别名,但它们不能与原始函数同名:
alias str_len is strlen[string];也许您想研究一下VHDL2008中的上下文子句。它们允许您在单个上下文中使用多个库和包,并且可以包含在其他地方以包括上下文中的所有子句。这里唯一的问题是你不能使用work,因为work只意味着“当前工作库”。如果要将上下文包含在另一个库中,则工作参考现在是不正确的。
context my_string_packages is
library my_string_lib;
use my_string_lib.strkern.all;
use my_string_lib.stdstring.all;
end context my_string_packages;
library my_string_lib;
context my_string_lib.my_string_packages;发布于 2020-11-26 17:39:34
包strdemo是strlen,strncpy的别名
package strdemo is
alias strlen is work.strkern.strlen[string return natural];
alias strncpy is work.strkern.strncpy [string, string, integer, natural, natural, boolean];
function "+"(a:string; b:string) return string;
function "-"(a:string; b:string) return boolean;
function "*"(a:integer; b:character) return string;
function "*"(a:boolean; b:string) return string;
end package strdemo;下面是strkern的完整清单
package strkern is
constant STRING_EOF : character := nul; -- \0 string termination from c
-- We can't assign strings but can easily assign string_segments to variables
-- Making a record instead of array because a record has no operators defined for it.
-- An array already has the & operator.
type string_segment is record
start, stop: natural;
end record string_segment;
-- We have 3 kinds of string: string, cstring, vstring. All export functions return vstring
-- There is no functionality difference between the 3, just implementation.
-- All functions accept string and return vstring. They can accept any string type but will
-- always return a vstring.
subtype cstring is string; -- null terminated c strlen <= 'length 'left = 1
subtype vstring is string; -- vhdl string strlen = 'length 'left >= 1
function strlen(s: string) return natural;
function safeseg(s: string; ss: string_segment := (0, 0); doreport: boolean := false) return vstring;
procedure strncpy(dest: out cstring; src: string; n: integer := -2; at: natural := 1; from: natural := 1; doreport: boolean := false);
end package strkern;
package body strkern is
-- Error messages
constant safeseg_left: string := "right operand: ";
constant safeseg_right: string := " overflows strlen: ";
-- Borrow integer whenelse() from stdlib
function whenelse(a: boolean; b, c: integer) return integer is begin
if a then return b; else return c;
end if;
end function whenelse;
function ii(i: integer) return vstring is begin
return integer'image(i);
end function ii;
-- These 4 are the only functions/procedures that use & = or segment/index strings
-- strlen is fundamental. It gives the correct answer on any type of string
function strlen(s: string) return natural is
variable i: natural := s'left;
begin
while i < s'right and s(i) /= STRING_EOF loop
i := i+1;
end loop;
if s'length = 0 then
return 0;
elsif s(i) = STRING_EOF then
return i-s'left;
else
return i+1-s'left;
end if;
end function strlen;
-- safely segment a string. if a=0 convert a cstring to vhdl string
-- otherwise use strlen and 'left to return correct segment string.
function safeseg(s: string; ss: string_segment := (0, 0); doreport: boolean := false) return vstring is
constant len: natural := strlen(s); -- strlen is an expensive function with long strings
-- This is the reason for stdstring. Debug reports get very verbose.
impure function dump return vstring is begin
return " safeseg(s, (" & ii(ss.start) & ", " & ii(ss.stop) & ")) s'left=" & ii(s'left) & " strlen(s)=" & ii(len);
end function dump;
begin
if doreport then -- debug. invokers can switch on doreport
report dump;
end if;
if ss.start = 0 then -- if ss.start=0 return the entire string as defined by strlen()
if len=0 then -- cannot use whenelse here
return "";
else
return s(s'left to s'left + len-1);
end if;
else
assert ss.stop <= len report safeseg_left & natural'image(ss.stop) & safeseg_right & dump;
return s(s'left + ss.start-1 to s'left + whenelse(ss.stop=0, s'length, ss.stop) -1);
end if;
end function safeseg;
-- The only way to assign strings
-- strncpy(dest, src) is effectively strcpy(dest, src) from C
-- It will non fail assert on overflow followed by an array out of bounds error
procedure strncpy(dest: out cstring; src: string; n: integer := -2; at: natural := 1; from: natural := 1; doreport: boolean := false) is
constant srclen: natural := strlen(src);
constant destspace: integer := dest'length + 1 - at;
variable copylen: integer := srclen + 1 - from;
impure function dump return vstring is begin
return " strncpy(str(" & ii(dest'length) & "), str(" & ii(srclen) & "), " & ii(n) & ", " & ii(at) & ", " & ii(from) & ")";
end function dump;
begin
if doreport then
report dump;
end if;
if n >= 0 and copylen > n then
copylen := n;
end if;
if n = -1 and copylen > destspace then
copylen := destspace;
end if;
assert copylen <= destspace report "overrun" & dump;
if copylen > 0 then
dest(at to at + copylen - 1) := src(from to from + copylen - 1);
end if;
if copylen < destspace then
dest(at + copylen) := STRING_EOF;
end if;
end procedure strncpy;
end package body strkern;https://stackoverflow.com/questions/65006385
复制相似问题