【IEEE_SV-7.3】联合体的使用方法

7.3 Unions

联合体是一种使用指定成员数据类型,表示可以被访问的单个存储块的数据类型。一次只能使用联合体中的一种数据类型。默认情况下,联合体是非合并的,这意味着没有必要表示该联合体成员的存储方式。动态类型和chandle类型只能在标记的联合体中使用。
联合声明的语法见语法7-2。

13)当struct或union为合并时,也应使用合并关键字。
16)只有在带标签的联合体中声明一个void struct_union_member才是合法的。仅在未合并的结构中声明random_qualifier是合法的。
例子:

typedef union { int i; shortreal f; } num; // 命名联合数据类型
num n;
n.f = 0.0; // 将n设置为浮点数格式
typedef struct {
bit isfloat;
union { int i; shortreal f; } n; // 匿名联合体类型
} tagged_st;

如果在非合并联合体类型的变量声明中没有指定初始值,则该变量应初始化为该联合类型声明顺序中第一个成员类型的变量的默认初始值。
有一项特殊规定是为了简化非合并联合体的使用: 如果一个非合并联合体包含共享一个共同的初始序列的几个非合并结构体, 并且如果非合并联合体对象当前包含这些结构中的一个,它允许在可见联合体的完整类型的声明任何地方检查共同的初始部分,一个完整的类型的联盟宣言是可见的。如果一个或多个初始成员序列的对应成员具有相同的类型,则两个结构体共享一个共同的初始序列。

7.3.1 Packed unions

合并联合体应只包含整型数据类型的成员。合并的、无标签的联合体都应该是相同的大小(与非合并联合体或合并的、有标签的联合体相比,成员可以是不同的大小)。因此,被写入作为另一个成员的联合体成员可以被读回。合并联合体与非合并联合体的区别在于,当一个合并联合体作为一个主向量出现时,它将被视为一个单一向量。
合并联合体还可以作为一个整体与算术和逻辑操作符一起使用,它的行为由其有符号性决定,默认为unsigned。可以像选择范围为[n-1:0]的合并数组一样选择合并联合体的一个或多个位。
只有表6-8(见6.11)中总结的合并数据类型和整数数据类型在合并联合体中是合法的。
如果一个合并结构体包含一个2态成员和一个4态成员,则整个联合体是4态成员。在读取时,有一个从4态到2态的隐式转换,在写入2态成员时,有一个从2态到4态的隐式转换。
例如,一个联合体可以被不同的访问宽度访问:

typedef union packed { // default unsigned
s_atmcell acell;
bit [423:0] bit_slice;
bit [52:0][7:0] byte_slice;
} u_atmcell;
u_atmcell u1;
byte b; bit [3:0] nib;
b = u1.bit_slice[415:408]; // same as b = u1.byte_slice[51];
nib = u1.bit_slice [423:420]; // same as nib = u1.acell.GFC;

对于合并联合体,写一个成员和读另一个成员是独立于机器的字节顺序的,这与非合并结构体不同,非合并结构体兼容c语言,成员按升序地址顺序排列。

7.3.2 Tagged unions

在联合体中标记的限定符将其声明为标记的联合体,这是一个类型检查联合体。 普通(untagged)联合体可以使用一个成员类型的值进行更新,然后读取为另一个成员类型的值,这是一个潜在的类型漏洞。标记的联合体存储成员值和标记,即表示当前成员名的附加位。标签和值只能使用静态类型检查标记的联合体表达式一致地一起更新(见11.9)。成员值只能用与当前标记值(即成员名)一致的类型读取。因此,存储一种类型的值并(错误地)将其解释为另一种类型是不可能的。
动态类型和chandle类型不应用于无标签的联合体,但可以用于有标签的联合体。
带标记的联合体的成员可以作为带标记的表达式引用。见11.9。
除了类型安全之外,使用成员名作为标记也使代码比那些必须使用显式标记跟踪联合体的代码更简单、更小。标记的联合体也可以用于模式匹配(见12.6),这进一步提高了可读性。
在带标签的联合体中,当所有信息都在标签本身中时,成员可以用void类型声明,就像下面的例子,一个整数和一个有效位:

typedef union tagged {
void Invalid;
int Valid;
} VInt;

VInt类型的值要么是Invalid(不包含任何内容),要么是Valid(包含一个int类型)。第11.9节描述了如何构造这种类型的值,还描述了如何不可能从当前具有Invalid标记的VInt值中读取整数。
例如:

typedef union tagged {
struct {
bit [4:0] reg1, reg2, regd;
} Add;
union tagged {
bit [9:0] JmpU;
struct {
bit [1:0] cc;
bit [9:0] addr;
} JmpC;
} Jmp;
} Instr;

Instr类型的值要么是Add指令(在这种情况下它包含三个5位寄存器字段),要么是Jmp指令。在后一种情况下,它要么是无条件跳转(在这种情况下它包含一个10位的目的地址),要么是条件跳转(在这种情况下它包含一个2位的条件码寄存器字段和一个10位的目的地址)。第11.9节描述了如何构造Instr类型的值,以及如何,为了读取cc字段,例如,指令必须具有操作码Jmp和子操作码JmpC。
当在带标签的联合体上使用合并限定符时,所有成员都应该具有合并类型,但它们的大小不必相同。合并标签的联合体的(标准)表示如下:
— 其大小总是等于表示标签所需的位数加上成员的最大size。
— 标签的大小是为所有成员名编码所需的最小位数(例如,5到8个成员需要3个标签位)。
— 标签位总是左对齐的(即朝向msb)。
— 对于每个成员,成员位总是右对齐的[即,朝向最低有效位(lbs)]。
— 标签位和成员位之间的位是未定义的。在void成员的极端情况下,只有标签是有意义的,其余的位都是未定义的。
表示方案递归地应用于任何嵌套标记的联合体。
例如,如果VInt类型定义有合并的限定符,Invalid和Valid值将分别具有如图7-1所示的布局。

例如,如果Instr类型有合并的限定符,它的值将有如图7-2所示的布局。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值