返回介绍

8.4.1.1 case语句中的模式匹配

发布于 2020-09-09 22:55:47 字数 3526 浏览 1163 评论 0 收藏 0

在一个模式匹配case语句中,圆括号内的表达式紧跟着关键字matches,并且语句包含了一系列“case_pattern_items”。在一个case条目的左侧,“:”之前的部分,包含了一个模式以及一个可选的&&操作符,在&&操作符之后紧跟一个“filter”布尔表达式。case条目的右侧是一条语句。每一个模式都引入了一个新的作用范围,在这个范围中会隐式地声明它的模式标识符;这个作用范围扩展到可选的过滤器表达式以及同一个case条目右侧的语句。因此,不同的case条目可以复用模式标识符。

所有的模式均执行完全静态的类型检查。在模式匹配case语句中进行测试的表达式必须具有已知的类型,它与每个case条目中模式的类型相同。

模式匹配case语句中圆括号内的表达式应该仅计算一次。它的值V应该以指定的顺序一次一个条目地与case条目的左侧进行匹配,如果有default case条目的话,会将其忽略。在这个线性搜索过程中,如果一个case条目被选择,那么它对应的语句会被执行,然后中止这个线性搜索。如果没有case条目被选择,那么会执行default case条目中的语句。如果既没有case条目被选择也没有指定default case条目的话,那么不执行任何语句。

对于一个被选择的case条目,值V必须与模式匹配(模式标识符被赋值为V中对应的成员),并且,布尔过滤器表达式的计算结果必须为“真”(非零的确定值)。

例子:

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

...
VInt v;
...

case (v) matches
    tagged Invalid : $display ("v is Invalid");
    tagged Valid n : $display ("v is Valid with value %d", n);
endcase

在上述的case语句中,如果v当前具有Invalid标签,那么第一个模式形成匹配。否则,它必须具有Valid标签,并且第二个模式形成匹配。标识符n被绑定到Valid成员的值,并且这个值被显示。当标签为Invalid的时候,我们不可能访问整数成员值n

例子:

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 instr;
...
case (instr) matches
    tagged Add {r1,r2,rd} && (rd != 0): rf[rd] = rf[r1] + rf[r2];
    tagged Jmp j : case (j) matches
                       tagged JmpU a : pc = pc + a;
                       tagged JmpC {c,a}: if (rf[c]) pc = a;
                   endcase
endcase

如果instr保存了一个Add指令,那么第一个模式形成匹配,标识符r1r2rd被绑定到嵌套结构体值得三个寄存器域。右侧的语句对寄存器文件rf执行这个指令。如果标签为Jmp,我们不可能访问这些寄存器域。如果instr保存了一个Jmp指令,那么第二个模式形成匹配,并且标识符j被绑定到嵌套的标签联合体值。内层的case语句轮流地将这个值与JmpUJmpC模式进行匹配,依次类推。

下面的例子与前一个例子相同,但使用通佩符和常量模式来排除rd=0的情况(在某些处理器中,寄存器0是一个特殊的“丢弃”寄存器):

case (instr) matches
    tagged Add {.*,.*, .0} : ;   // 无操作
    tagged Add {r1,r2,rd} : rf[rd] = rf[r1] + rf[r2];
    tagged Jmp j : case (j) matches
                       tagged JmpU a : pc = pc + a;
                       tagged JmpC {c,a}: if (rf[c]) pc = a;
                   endcase
endcase

下面的例子与前一个例子相同,但第一个内层case语句仅包含结构体和常量,但不包括标签联合体:

case (instr) matches
    tagged Add s: case (s) matches
                      {.*,.*, .0} : ;   // 无操作
                      {r1,r2,rd} : rf[rd] = rf[r1] + rf[r2];
                  endcase
    tagged Jmp j : case (j) matches
                       tagged JmpU a : pc = pc + a;
                       tagged JmpC {c,a}: if (rf[c]) pc = a;
                   endcase
endcase

下面的例子与前一个相同,但使用嵌套的标签联合体模式:

case (instr) matches
    tagged Add {r1,r2,rd} && (rd != 0): rf[rd] = rf[r1] + rf[r2];
    tagged Jmp (tagged JmpU a) : pc = pc + a;
    tagged Jmp (tagged JmpC {c,a}) : if (rf[c]) pc = a;
endcase

下面的例子与前一个相同,但使用命名的结构体组件:

case (instr) matches
    tagged Add {reg2:r2,regd:rd,reg1:r1} && (rd != 0): rf[rd] = rf[r1] + rf[r2];
    tagged Jmp (tagged JmpU a) : pc = pc + a;
    tagged Jmp (tagged JmpC {addr:a,cc:c}) : if (rf[c]) pc = a;
endcase

casez和casex关键字同样可以用来替代case关键字,并具有相同的语义。换句话说,在模式匹配过程中,无论两个位在哪里比较(无论它们是标签位还是成员位),casez都会忽略z位,casex会忽略z和x位。

priority和unique限定符扮演它们原本的角色。priority意味着某个case条目必须被选择。unique也同样意味着仅仅可以选择一个case条目,所以他们可以并行计算。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文