veryl_analyzer/ir/
ff_table.rs1use crate::HashMap;
2use crate::ir::VarId;
3
4type AssignTarget = (VarId, Option<usize>);
7
8#[derive(Clone, Debug)]
9pub struct FfTableEntry {
10 pub assigned: Option<usize>,
11 pub refered: Vec<(usize, Option<AssignTarget>, bool)>,
16 pub is_ff: bool,
17 pub assigned_comb: Option<usize>,
18}
19
20impl FfTableEntry {
21 fn update_is_ff(&mut self, self_key: (VarId, usize)) {
22 if let Some(assigned_decl) = self.assigned {
23 self.is_ff = self.refered.iter().any(|(decl, assign_target, from_ff)| {
31 if !from_ff {
32 return false;
33 }
34 if *decl != assigned_decl {
35 return true;
36 }
37 match assign_target {
38 Some((target_id, target_idx)) => {
39 if *target_id != self_key.0 {
40 return true;
41 }
42 match target_idx {
45 Some(idx) => *idx != self_key.1,
46 None => true,
47 }
48 }
49 None => true,
50 }
51 });
52 }
53 }
54}
55
56#[derive(Clone, Debug, Default)]
57pub struct FfTable {
58 pub table: HashMap<(VarId, usize), FfTableEntry>,
59}
60
61impl FfTable {
62 pub fn update_is_ff(&mut self) {
63 let keys: Vec<_> = self.table.keys().cloned().collect();
64 for key in keys {
65 self.table.get_mut(&key).unwrap().update_is_ff(key);
66 }
67 }
68
69 pub fn force_all_ff(&mut self) {
72 for entry in self.table.values_mut() {
73 if entry.assigned.is_some() {
74 entry.is_ff = true;
75 }
76 }
77 }
78
79 pub fn is_ff(&self, id: VarId, index: usize) -> bool {
80 if let Some(x) = self.table.get(&(id, index)) {
81 x.is_ff
82 } else {
83 false
84 }
85 }
86
87 pub fn insert_refered(
88 &mut self,
89 id: VarId,
90 index: usize,
91 decl: usize,
92 assign_target: Option<AssignTarget>,
93 from_ff: bool,
94 ) {
95 self.table
96 .entry((id, index))
97 .and_modify(|x| x.refered.push((decl, assign_target, from_ff)))
98 .or_insert(FfTableEntry {
99 assigned: None,
100 refered: vec![(decl, assign_target, from_ff)],
101 is_ff: false,
102 assigned_comb: None,
103 });
104 }
105
106 pub fn insert_assigned(&mut self, id: VarId, index: usize, decl: usize) {
107 self.table
108 .entry((id, index))
109 .and_modify(|x| x.assigned = Some(decl))
110 .or_insert(FfTableEntry {
111 assigned: Some(decl),
112 refered: vec![],
113 is_ff: false,
114 assigned_comb: None,
115 });
116 }
117
118 pub fn insert_assigned_comb(&mut self, id: VarId, index: usize, decl: usize) {
119 self.table
120 .entry((id, index))
121 .and_modify(|x| x.assigned_comb = Some(decl))
122 .or_insert(FfTableEntry {
123 assigned: None,
124 refered: vec![],
125 is_ff: false,
126 assigned_comb: Some(decl),
127 });
128 }
129
130 #[cfg(debug_assertions)]
131 pub fn validate(&self) {
132 for ((id, index), entry) in &self.table {
133 if let (Some(ff_decl), Some(comb_decl)) = (entry.assigned, entry.assigned_comb) {
134 log::warn!(
135 "FfTable: variable {:?}[{}] assigned in both always_ff (decl {}) and always_comb (decl {})",
136 id,
137 index,
138 ff_decl,
139 comb_decl
140 );
141 }
142 }
143 }
144}