vhdl包从另一个包导出它包含的符号

vhdl包从另一个包导出它包含的符号,vhdl,Vhdl,假设我有一个导出函数的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 excit

假设我有一个导出函数的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;
你有斯特伦,还有令人兴奋的新运营商。 如何从子包重新导出函数/类型导入? 缺少一个新名称的虚拟实现,它只调用要导入的实现

function strlen(s: string) return natural is
    return strkern.strlen(s);
end function strlen;

您不能从一个包中的另一个包中重新导出任何内容。唯一的选择是同时使用strkern包和stdstring包

使用work.strkern.all; 使用work.stdstring.all; 我建议不要创建虚拟实现,因为如果用户同时包含这两个包,重复的函数签名将导致这两个包都不可见,因为编译器不知道使用哪一个。用户必须明确使用哪个函数:

work.strkern.strlenHello世界; work.stdstring.strlenHello世界; 您可以为第一个程序包中的函数创建别名,但它们不能与原始程序包同名:

alias str_len is strlen[string];
也许您想研究VHDL2008中的上下文子句。这些允许您在单个上下文中使用多个库和包,并且可以包含在其他地方以包含上下文中的所有子句。这里唯一的问题是不允许使用work,因为work仅表示当前的工作库。如果要在另一个库中包含上下文,则工作引用现在不正确

上下文我的\u字符串\u包是 库我的字符串库; 使用my_string_lib.strkern.all; 使用my_string_lib.stdstring.all; 结束上下文我的字符串包; 库我的字符串库; 上下文my_string_lib.my_string_包;
您不能从一个包中的另一个包中重新导出任何内容。唯一的选择是同时使用strkern包和stdstring包

使用work.strkern.all; 使用work.stdstring.all; 我建议不要创建虚拟实现,因为如果用户同时包含这两个包,重复的函数签名将导致这两个包都不可见,因为编译器不知道使用哪一个。用户必须明确使用哪个函数:

work.strkern.strlenHello世界; work.stdstring.strlenHello世界; 您可以为第一个程序包中的函数创建别名,但它们不能与原始程序包同名:

alias str_len is strlen[string];
也许您想研究VHDL2008中的上下文子句。这些允许您在单个上下文中使用多个库和包,并且可以包含在其他地方以包含上下文中的所有子句。这里唯一的问题是不允许使用work,因为work仅表示当前的工作库。如果要在另一个库中包含上下文,则工作引用现在不正确

上下文我的\u字符串\u包是 库我的字符串库; 使用my_string_lib.strkern.all; 使用my_string_lib.stdstring.all; 结束上下文我的字符串包; 库我的字符串库; 上下文my_string_lib.my_string_包;
通过提供一个最小、完整且可验证的示例:

包裹strkern是 函数strlens:字符串返回自然值; 端包strkern; 包体strkern是 函数strlens:string返回自然值 开始 返回s的长度; 末端功能; 端部封装体; 使用work.strkern.all;-未在本缩短示例中使用 包标准字符串是 -雷克斯波特斯特伦酒店 -定义令人兴奋的新操作符 别名strlen为work.strkern.strlen[string return natural]; 端包标准串; 使用work.stdstring.all; 实体foo是 终端实体; foo is的建筑风格 开始 断言错误 abcde的报告strlen为&integer'imagestrlenabcde 严重性说明; 终端架构; 我们可以演示如何在包中使用别名,以提供在另一个包中找到的函数声明的可见性

ghdl-r foo std_flub_up.vhdl:25:5:@0ms:assertion注:abcde的strlen为5 问题代码片段没有演示任何“令人兴奋的新运算符”,其中运算符特定于VHDL中预定义的运算符。参见IEEE标准1076-2008 9.2运营商

使用别名使名称可见的方法如中所示 6.6.3非对象别名。请注意,子程序的别名需要签名

一些读者可能会好奇,为什么选定的名称后缀strlen在上述MCVe别名中可见。见12.3能见度:

可见性可以通过选择或直接设置。通过选择可在定义如下的位置看到声明:

a表示库中包含的主要单元:在选定名称的后缀位置,其前缀表示库。 ... f对于包声明中给出的声明,而不是定义未实例化包的包声明中给出的声明:在前缀表示包的选定名称的后缀位置。 .


基本上,选定名称work.strkern.strlen后缀strlen声明出现在由前缀定义的单独名称空间中,前缀将在库工作中指定主要单元包strkern。程序包声明由规则a显示。后缀由规则f显示。通过隐式库声明使库工作可见,请参见13.2设计库。

通过提供一个最小、完整和可验证的示例:

包裹strkern是 函数strlens:字符串返回自然值; 端包strkern; 包体strkern是 函数strlens:string返回自然值 开始 返回s的长度; 末端功能; 端部封装体; 使用work.strkern.all;-未在本缩短示例中使用 包标准字符串是 -雷克斯波特斯特伦酒店 -定义令人兴奋的新操作符 别名strlen为work.strkern.strlen[string return natural]; 端包标准串; 使用work.stdstring.all; 实体foo是 终端实体; foo is的建筑风格 开始 断言错误 abcde的报告strlen为&integer'imagestrlenabcde 严重性说明; 终端架构; 我们可以演示如何在包中使用别名,以提供在另一个包中找到的函数声明的可见性

ghdl-r foo std_flub_up.vhdl:25:5:@0ms:assertion注:abcde的strlen为5 问题代码片段没有演示任何“令人兴奋的新运算符”,其中运算符特定于VHDL中预定义的运算符。参见IEEE标准1076-2008 9.2运营商

使用别名使名称可见的方法如中所示 6.6.3非对象别名。请注意,子程序的别名需要签名

一些读者可能会好奇,为什么选定的名称后缀strlen在上述MCVe别名中可见。见12.3能见度:

可见性可以通过选择或直接设置。通过选择可在定义如下的位置看到声明:

a表示库中包含的主要单元:在选定名称的后缀位置,其前缀表示库。 ... f对于包声明中给出的声明,而不是定义未实例化包的包声明中给出的声明:在前缀表示包的选定名称的后缀位置。


基本上,选定名称work.strkern.strlen后缀strlen声明出现在由前缀定义的单独名称空间中,前缀将在库工作中指定主要单元包strkern。程序包声明由规则a显示。后缀由规则f显示。库工作通过隐式库声明可见,请参见13.2设计库。

包stremo的别名为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;
这是斯特克恩的完整列表

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;

包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;
这是斯特克恩的完整列表

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;

再出口用词不当。来自包的声明通过use子句可见。对于子程序,这些声明在包体中也有一个子程序定义,该定义在过程调用或函数调用期间动态细化和执行。重新导出是一个误称。来自包的声明通过use子句可见。对于子程序,这些声明在包体中也有一个子程序定义,该定义在过程调用或函数调用期间动态细化和执行。下面我的回答表明我的strlen并不像你想象的那么简单,下面可以看到一些令人兴奋的新操作符。它们是由python脚本生成的,所以我只设置了一些脚本,以保持其可读性。谢谢,这对我来说很好。下面我的回答表明我的strlen并不像你想象的那么简单,下面可以看到一些令人兴奋的新操作符。它们是由python脚本生成的,所以我只设置了一些脚本来保持可读性