1use crate::analyzer_error::{AnalyzerError, ExceedLimitKind};
2use crate::conv::instance::{InstanceHistory, InstanceHistoryError};
3use crate::ir::{
4 Component, Comptime, Declaration, Expression, FfClock, FfReset, FuncPath, Function, Interface,
5 IrResult, ShapeRef, Signature, Type, VarId, VarIndex, VarKind, VarPath, VarSelect, Variable,
6 VariableInfo,
7};
8use crate::namespace::Namespace;
9use crate::namespace_table;
10use crate::symbol::{Affiliation, ClockDomain, Direction, GenericMap, SymbolId};
11use crate::symbol_path::GenericSymbolPath;
12use crate::value::MaskCache;
13use crate::{HashMap, HashSet};
14use std::sync::Arc;
15use veryl_parser::resource_table::StrId;
16use veryl_parser::token_range::TokenRange;
17use veryl_parser::veryl_token::Token;
18
19#[derive(Clone)]
20pub struct Config {
21 pub retain_component_body: bool,
22 pub instance_depth_limit: usize,
23 pub instance_total_limit: usize,
24 pub evaluate_size_limit: usize,
25 pub evaluate_array_limit: usize,
26}
27
28impl Default for Config {
29 fn default() -> Self {
30 Self {
31 retain_component_body: false,
32 instance_depth_limit: 1024,
33 instance_total_limit: 1024 * 1024,
34 evaluate_size_limit: 1024 * 1024,
35 evaluate_array_limit: 128,
36 }
37 }
38}
39
40#[derive(Default)]
41pub struct Context {
42 pub config: Config,
43 pub var_id: VarId,
44 pub var_paths: HashMap<VarPath, (VarId, Comptime)>,
45 pub func_paths: HashMap<FuncPath, VarId>,
46 pub variables: HashMap<VarId, Variable>,
47 pub functions: HashMap<VarId, Function>,
48 pub port_types: HashMap<VarPath, (Type, ClockDomain)>,
49 pub modports: HashMap<StrId, Vec<(StrId, Direction)>>,
50 pub declarations: Vec<Declaration>,
51 pub default_clock: Option<(VarPath, SymbolId)>,
52 pub default_reset: Option<(VarPath, SymbolId)>,
53 pub instance_history: InstanceHistory,
54 pub select_paths: Vec<(VarPath, GenericSymbolPath)>,
55 pub select_dims: Vec<usize>,
56 pub ignore_var_func: bool,
57 pub disalbe_const_opt: bool,
58 pub namespaces: Vec<Namespace>,
59 pub in_generic: bool,
60 pub allow_component_as_factor: bool,
61 pub in_test_module: bool,
62 pub in_global_func: Option<Token>,
63 pub in_if_reset: bool,
64 pub current_clock: Option<Comptime>,
65 pub mask_cache: MaskCache,
66 pub tb_reset_cycles: HashMap<StrId, Expression>,
67 pub tb_clock_period: HashMap<StrId, Expression>,
68 pub tb_reset_clock: HashMap<StrId, StrId>,
69 hierarchy: Vec<StrId>,
70 hierarchical_variables: Vec<Vec<VarPath>>,
71 hierarchical_functions: Vec<Vec<FuncPath>>,
72 shadowed_variables: HashMap<VarPath, Vec<(VarId, Comptime)>>,
73 affiliation: Vec<Affiliation>,
74 overrides: Vec<HashMap<VarPath, (Comptime, Expression)>>,
75 generic_maps: Vec<Vec<GenericMap>>,
76 errors: Vec<AnalyzerError>,
77}
78
79impl Context {
80 pub fn inherit(&mut self, tgt: &mut Context) {
81 std::mem::swap(&mut self.overrides, &mut tgt.overrides);
82 std::mem::swap(&mut self.generic_maps, &mut tgt.generic_maps);
83 std::mem::swap(&mut self.instance_history, &mut tgt.instance_history);
84 std::mem::swap(&mut self.errors, &mut tgt.errors);
85 std::mem::swap(&mut self.namespaces, &mut tgt.namespaces);
86 self.disalbe_const_opt = tgt.disalbe_const_opt;
87 self.in_generic = tgt.in_generic;
88 self.allow_component_as_factor = tgt.allow_component_as_factor;
89 self.config = tgt.config.clone();
90 }
91
92 pub fn get_override(&self, x: &VarPath) -> Option<&(Comptime, Expression)> {
93 let overrides = self.overrides.last()?;
94 overrides.get(x)
95 }
96
97 pub fn get_variable_info(&self, id: VarId) -> Option<VariableInfo> {
98 self.variables.get(&id).map(VariableInfo::new)
99 }
100
101 pub fn resolve_path(&self, mut path: GenericSymbolPath) -> GenericSymbolPath {
102 let Some(namespace) = namespace_table::get(path.paths[0].base.id) else {
103 return path;
104 };
105 path.resolve_imported(&namespace, None);
106 for map in self.generic_maps.iter().rev() {
107 path.apply_map(map);
108 }
109 path
110 }
111
112 pub fn insert_var_path(&mut self, path: VarPath, value: Comptime) -> VarId {
113 let id = self.var_id;
114 self.insert_var_path_with_id(path, id, value);
115 self.var_id.inc();
116 id
117 }
118
119 pub fn insert_var_path_with_id(&mut self, path: VarPath, id: VarId, value: Comptime) {
120 if let Some(x) = self.hierarchical_variables.last_mut() {
121 x.push(path.clone());
122 }
123
124 let shadowed = self.var_paths.insert(path.clone(), (id, value));
125
126 if let Some(x) = shadowed {
128 self.shadowed_variables
129 .entry(path)
130 .and_modify(|v| v.push(x.clone()))
131 .or_insert(vec![x]);
132 }
133 }
134
135 pub fn insert_func_path(&mut self, path: FuncPath) -> VarId {
136 let id = self.var_id;
137 self.func_paths.insert(path, id);
138 self.var_id.inc();
139 id
140 }
141
142 pub fn insert_variable(&mut self, id: VarId, mut variable: Variable) {
143 if self.ignore_var_func {
144 return;
145 }
146
147 let hier = &self.hierarchy;
148 if !hier.is_empty() {
149 variable.path.add_prelude(hier);
150 }
151 self.variables.insert(id, variable);
152 }
153
154 pub fn insert_port_type(&mut self, path: VarPath, r#type: Type, clock_domain: ClockDomain) {
155 self.port_types.insert(path, (r#type, clock_domain));
156 }
157
158 pub fn insert_function(&mut self, id: VarId, mut function: Function) {
159 if self.ignore_var_func {
160 return;
161 }
162
163 let hier = &self.hierarchy;
164 if !hier.is_empty() {
165 function.path.add_prelude(hier);
166 }
167 self.functions.insert(id, function);
168 }
169
170 pub fn insert_declaration(&mut self, decl: Declaration) {
171 if !decl.is_null() {
172 self.declarations.push(decl);
173 }
174 }
175
176 pub fn insert_error(&mut self, mut error: AnalyzerError) {
177 let mut replaced = false;
178
179 if let AnalyzerError::MultipleAssignment {
181 identifier: ref new_ident,
182 error_locations: ref mut new_locations,
183 ..
184 } = error
185 {
186 for e in &mut self.errors {
187 if let AnalyzerError::MultipleAssignment {
188 identifier: org_ident,
189 error_locations: org_locations,
190 ..
191 } = e
192 && new_ident == org_ident
193 {
194 org_locations.append(new_locations);
195 org_locations.sort();
196 org_locations.dedup();
197 replaced = true;
198 break;
199 }
200 }
201 }
202
203 if !replaced && !self.errors.contains(&error) {
204 self.errors.push(error);
205 }
206 }
207
208 pub fn insert_modport(&mut self, name: StrId, members: Vec<(StrId, Direction)>) {
209 self.modports.insert(name, members);
210 }
211
212 pub fn extract_function(&mut self, context: &mut Context, base: &VarPath, array: &ShapeRef) {
213 for (id, mut variable) in context.variables.drain() {
214 variable.path.add_prelude(&base.0);
215 variable.prepend_array(array);
216 self.variables.insert(id, variable);
217 }
218
219 for (mut path, id) in context.func_paths.drain() {
220 if !path.path.starts_with(&base.0) {
221 path.path.add_prelude(&base.0);
222 }
223 self.func_paths.insert(path, id);
224 }
225
226 for (id, mut function) in context.functions.drain() {
227 if !array.is_empty() {
228 let total_array = array.total();
229 let func_body = function.functions.remove(0);
230 if let Some(total_array) = total_array {
231 for i in 0..total_array {
232 let var_index = VarIndex::from_index(i, array);
233 let mut func_body = func_body.clone();
234 func_body.set_index(&var_index);
235 function.functions.push(func_body);
236 }
237 }
238 }
239
240 if !function.path.path.starts_with(&base.0) {
241 function.path.path.add_prelude(&base.0);
242 }
243 self.functions.insert(id, function);
244 }
245 }
246
247 pub fn extract_var_paths(&mut self, context: &Context, base: &VarPath, array: &ShapeRef) {
248 for (path, (id, comptime)) in &context.var_paths {
249 if path.starts_with(&base.0) {
250 let mut path = path.clone();
251 path.remove_prelude(&base.0);
252 if !path.0.is_empty() {
253 let mut comptime = comptime.clone();
254 for _ in 0..array.dims() {
255 comptime.r#type.array.remove(0);
256 }
257 self.var_paths.insert(path, (*id, comptime));
258 }
259 }
260 }
261 }
262
263 pub fn extract_interface_member(
264 &mut self,
265 base: StrId,
266 array: &ShapeRef,
267 component: Interface,
268 modport: Option<StrId>,
269 clock_domain: ClockDomain,
270 token: TokenRange,
271 ) {
272 let mut inserted = HashSet::default();
273
274 let modport_members = if let Some(x) = &modport {
275 component.get_modport(x)
276 } else {
277 HashMap::default()
278 };
279
280 let mut id_map = HashMap::default();
281 for mut variable in component.variables.into_values() {
282 if modport.is_some() {
283 if let Some(x) = modport_members.get(&variable.path.first()) {
284 variable.kind = match x {
285 Direction::Input => VarKind::Input,
286 Direction::Output => VarKind::Output,
287 Direction::Inout => VarKind::Inout,
288 _ => variable.kind,
289 };
290 } else {
291 continue;
293 }
294 }
295
296 variable.prepend_array(array);
297
298 variable.token = token;
300 variable.affiliation = self.get_affiliation();
301
302 inserted.insert(variable.path.clone());
303 let comptime = Comptime::from_type(variable.r#type.clone(), clock_domain, token);
304 variable.path.add_prelude(&[base]);
305 let id = self.insert_var_path(variable.path.clone(), comptime);
306
307 id_map.insert(variable.id, id);
309
310 variable.id = id;
311 self.insert_variable(id, variable);
312 }
313
314 for (mut path, (id, mut comptime)) in component.var_paths {
316 if !inserted.contains(&path) {
317 path.add_prelude(&[base]);
318 comptime.r#type.prepend_array(array);
319
320 if let Some(id) = id_map.get(&id) {
321 self.insert_var_path_with_id(path, *id, comptime);
322 } else {
323 self.insert_var_path(path, comptime);
324 }
325 }
326 }
327 }
328
329 pub fn inc_select_dim(&mut self) {
330 if let Some(x) = self.select_dims.last_mut() {
331 *x += 1;
332 }
333 }
334
335 pub fn get_select_dim(&self) -> Option<usize> {
336 self.select_dims.last().copied()
337 }
338
339 pub fn set_default_clock(&mut self, path: VarPath, id: SymbolId) {
340 self.default_clock.replace((path, id));
341 }
342
343 pub fn set_default_reset(&mut self, path: VarPath, id: SymbolId) {
344 self.default_reset.replace((path, id));
345 }
346
347 pub fn get_default_clock(&self) -> Option<(FfClock, SymbolId)> {
348 if let Some(x) = &self.default_clock {
349 if let Some((id, comptime)) = &self.var_paths.get(&x.0) {
350 let ret = FfClock {
351 id: *id,
352 index: VarIndex::default(),
353 select: VarSelect::default(),
354 comptime: comptime.clone(),
355 };
356 Some((ret, x.1))
357 } else {
358 None
359 }
360 } else {
361 None
362 }
363 }
364
365 pub fn get_default_reset(&self) -> Option<(FfReset, SymbolId)> {
366 if let Some(x) = &self.default_reset {
367 if let Some((id, comptime)) = &self.var_paths.get(&x.0) {
368 let ret = FfReset {
369 id: *id,
370 index: VarIndex::default(),
371 select: VarSelect::default(),
372 comptime: comptime.clone(),
373 };
374 Some((ret, x.1))
375 } else {
376 None
377 }
378 } else {
379 None
380 }
381 }
382
383 pub fn check_size(&mut self, x: usize, token: TokenRange) -> Option<usize> {
384 if x > self.config.evaluate_size_limit {
385 self.insert_error(AnalyzerError::exceed_limit(
386 ExceedLimitKind::EvaluateSize,
387 x,
388 &token,
389 ));
390 None
391 } else {
392 Some(x)
393 }
394 }
395
396 pub fn block<F, T>(&mut self, f: F) -> IrResult<T>
397 where
398 F: FnOnce(&mut Context) -> IrResult<T>,
399 {
400 f(self)
401 }
402
403 pub fn push_instance_history(&mut self, x: Signature) -> Result<bool, InstanceHistoryError> {
404 self.instance_history.push(x, &self.config)
405 }
406
407 pub fn pop_instance_history(&mut self) {
408 self.instance_history.pop();
409 }
410
411 pub fn get_current_signature(&self) -> Option<&Signature> {
412 self.instance_history.get_current_signature()
413 }
414
415 pub fn get_instance_history(&self, sig: &Signature) -> Option<Arc<Component>> {
416 self.instance_history.get(sig)
417 }
418
419 pub fn set_instance_history(&mut self, sig: &Signature, component: Arc<Component>) {
420 self.instance_history.set(sig, component);
421 }
422
423 pub fn push_hierarchy(&mut self, x: StrId) {
424 self.hierarchy.push(x);
425 self.hierarchical_variables.push(vec![]);
426 self.hierarchical_functions.push(vec![]);
427 }
428
429 pub fn pop_hierarchy(&mut self) {
430 self.hierarchy.pop();
431 let drops = self.hierarchical_variables.pop();
432 if let Some(drops) = drops {
433 for x in drops {
434 if let Some(y) = self.shadowed_variables.get_mut(&x)
435 && let Some(y) = y.pop()
436 {
437 self.var_paths.insert(x, y);
438 } else {
439 self.var_paths.remove(&x);
440 }
441 }
442 }
443 let drops = self.hierarchical_functions.pop();
444 if let Some(drops) = drops {
445 for x in drops {
446 self.func_paths.remove(&x);
447 }
448 }
449 }
450
451 pub fn push_affiliation(&mut self, x: Affiliation) {
452 self.affiliation.push(x);
453 }
454
455 pub fn pop_affiliation(&mut self) {
456 self.affiliation.pop();
457 }
458
459 pub fn push_override(&mut self, x: HashMap<VarPath, (Comptime, Expression)>) {
460 self.overrides.push(x);
461 }
462
463 pub fn pop_override(&mut self) {
464 self.overrides.pop();
465 }
466
467 pub fn push_generic_map(&mut self, x: Vec<GenericMap>) {
468 self.generic_maps.push(x);
469 }
470
471 pub fn pop_generic_map(&mut self) {
472 self.generic_maps.pop();
473 }
474
475 pub fn is_affiliated(&self, value: Affiliation) -> bool {
476 if let Some(x) = self.affiliation.last() {
477 *x == value
478 } else {
479 false
480 }
481 }
482
483 pub fn get_affiliation(&self) -> Affiliation {
484 self.affiliation.last().copied().unwrap()
485 }
486
487 pub fn push_namespace(&mut self, namespace: Namespace) {
488 self.namespaces.push(namespace);
489 }
490
491 pub fn pop_namespace(&mut self) {
492 self.namespaces.pop();
493 }
494
495 pub fn current_namespace(&self) -> Option<Namespace> {
496 self.namespaces.last().cloned()
497 }
498
499 pub fn find_path(&self, path: &VarPath) -> Option<(VarId, Comptime)> {
500 self.var_paths.get(path).cloned()
501 }
502
503 pub fn get_variable(&self, id: &VarId) -> Option<Variable> {
504 self.variables.get(id).cloned()
505 }
506
507 pub fn remove_path(&mut self, path: &VarPath) {
508 self.var_paths.remove(path);
509 }
510
511 pub fn drain_var_paths(&mut self) -> HashMap<VarPath, (VarId, Comptime)> {
512 self.var_paths.drain().collect()
513 }
514
515 pub fn drain_func_paths(&mut self) -> HashMap<FuncPath, VarId> {
516 self.func_paths.drain().collect()
517 }
518
519 pub fn drain_variables(&mut self) -> HashMap<VarId, Variable> {
520 self.variables.drain().collect()
521 }
522
523 pub fn drain_port_types(&mut self) -> HashMap<VarPath, (Type, ClockDomain)> {
524 self.port_types.drain().collect()
525 }
526
527 pub fn drain_functions(&mut self) -> HashMap<VarId, Function> {
528 self.functions.drain().collect()
529 }
530
531 pub fn drain_modports(&mut self) -> HashMap<StrId, Vec<(StrId, Direction)>> {
532 self.modports.drain().collect()
533 }
534
535 pub fn drain_declarations(&mut self) -> Vec<Declaration> {
536 self.declarations.drain(..).collect()
537 }
538
539 pub fn drain_errors(&mut self) -> Vec<AnalyzerError> {
540 self.errors.drain(..).collect()
541 }
542}