1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use crate::{ir::prelude::*, opt::prelude::*};
pub struct ProcessLowering;
impl Pass for ProcessLowering {
fn run_on_cfg(ctx: &PassContext, unit: &mut UnitBuilder) -> bool {
if !unit.is_process() || !is_suitable(ctx, &unit) {
return false;
}
info!("ProcLower [{}]", unit.name());
unit.data().kind = UnitKind::Entity;
unit.delete_inst(unit.terminator(unit.entry()));
unit.insert_at_end();
unit.ins().halt();
true
}
}
fn is_suitable(_ctx: &PassContext, unit: &Unit) -> bool {
if unit.blocks().count() != 1 {
trace!("Skipping {} (not just one block)", unit.name());
return false;
}
let bb = unit.entry();
let term = unit.terminator(bb);
match unit[term].opcode() {
Opcode::Wait | Opcode::WaitTime | Opcode::Halt => (),
op => {
trace!("Skipping {} (wrong terminator {})", unit.name(), op);
return false;
}
}
for inst in unit.insts(bb) {
if inst == term {
continue;
}
if !unit[inst].opcode().valid_in_entity() {
trace!(
"Skipping {} ({} not allowed in entity)",
unit.name(),
inst.dump(&unit)
);
return false;
}
}
match unit[term].opcode() {
Opcode::Wait | Opcode::WaitTime => {
for arg in unit.sig().inputs() {
let value = unit.arg_value(arg);
if unit.has_uses(value) && !unit[term].args().contains(&value) {
trace!(
"Skipping {} ({} not in wait sensitivity list)",
unit.name(),
value.dump(&unit)
);
return false;
}
}
}
_ => (),
}
true
}