1use std::collections::{HashMap, HashSet};
2use std::fmt::Write;
3
4use color_eyre::{eyre::anyhow, eyre::bail, Result};
5use derive_more::Debug;
6use log::warn;
7use num::{BigUint, ToPrimitive};
8use surfer_translation_types::{
9 VariableDirection, VariableEncoding, VariableIndex, VariableType, VariableValue,
10};
11use wellen::{
12 FileFormat, Hierarchy, ScopeType, Signal, SignalEncoding, SignalRef, SignalSource, Time,
13 TimeTable, TimeTableIdx, Timescale, TimescaleUnit, Var, VarRef, VarType,
14};
15
16use crate::time::{TimeScale, TimeUnit};
17use crate::variable_direction::VariableDirectionExt;
18use crate::variable_index::VariableIndexExt;
19use crate::variable_type::VariableTypeExt;
20use crate::wave_container::{
21 MetaData, QueryResult, ScopeId, ScopeRef, ScopeRefExt, VarId, VariableMeta, VariableRef,
22 VariableRefExt,
23};
24
25static UNIQUE_ID_COUNT: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
26
27#[derive(Debug)]
28pub struct WellenContainer {
29 #[debug(skip)]
30 hierarchy: std::sync::Arc<Hierarchy>,
31 server: Option<String>,
33 scopes: Vec<String>,
34 vars: Vec<String>,
35 signals: HashMap<SignalRef, Signal>,
36 signals_to_be_loaded: HashSet<SignalRef>,
38 time_table: TimeTable,
39 #[debug(skip)]
40 source: Option<SignalSource>,
41 unique_id: u64,
42 body_loaded: bool,
43}
44
45pub struct LoadSignalsCmd {
48 signals: Vec<SignalRef>,
49 from_unique_id: u64,
50 payload: LoadSignalPayload,
51}
52
53pub enum HeaderResult {
54 LocalFile(Box<wellen::viewers::HeaderResult<std::io::BufReader<std::fs::File>>>),
56 LocalBytes(Box<wellen::viewers::HeaderResult<std::io::Cursor<Vec<u8>>>>),
58 Remote(std::sync::Arc<Hierarchy>, FileFormat, String),
60}
61
62pub enum BodyResult {
63 Local(wellen::viewers::BodyResult),
65 Remote(Vec<wellen::Time>, String),
67}
68
69pub enum LoadSignalPayload {
70 Local(SignalSource, std::sync::Arc<Hierarchy>),
71 Remote(String),
72}
73
74impl LoadSignalsCmd {
75 pub fn destruct(self) -> (Vec<SignalRef>, u64, LoadSignalPayload) {
76 (self.signals, self.from_unique_id, self.payload)
77 }
78}
79
80pub struct LoadSignalsResult {
81 source: Option<SignalSource>,
82 server: Option<String>,
83 signals: Vec<(SignalRef, Signal)>,
84 from_unique_id: u64,
85}
86
87impl LoadSignalsResult {
88 pub fn local(
89 source: SignalSource,
90 signals: Vec<(SignalRef, Signal)>,
91 from_unique_id: u64,
92 ) -> Self {
93 Self {
94 source: Some(source),
95 server: None,
96 signals,
97 from_unique_id,
98 }
99 }
100
101 pub fn remote(server: String, signals: Vec<(SignalRef, Signal)>, from_unique_id: u64) -> Self {
102 Self {
103 source: None,
104 server: Some(server),
105 signals,
106 from_unique_id,
107 }
108 }
109
110 pub fn len(&self) -> usize {
111 self.signals.len()
112 }
113
114 pub fn is_empty(&self) -> bool {
115 self.signals.is_empty()
116 }
117}
118
119pub fn convert_format(format: FileFormat) -> crate::WaveFormat {
120 match format {
121 FileFormat::Vcd => crate::WaveFormat::Vcd,
122 FileFormat::Fst => crate::WaveFormat::Fst,
123 FileFormat::Ghw => crate::WaveFormat::Ghw,
124 FileFormat::Unknown => unreachable!("should never get here"),
125 }
126}
127
128impl WellenContainer {
129 pub fn new(hierarchy: std::sync::Arc<Hierarchy>, server: Option<String>) -> Self {
130 let h = &hierarchy;
132 let scopes = h.iter_scopes().map(|r| r.full_name(h)).collect::<Vec<_>>();
133 let vars: Vec<String> = h.iter_vars().map(|r| r.full_name(h)).collect::<Vec<_>>();
134
135 let unique_id = UNIQUE_ID_COUNT.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
136
137 Self {
138 hierarchy,
139 server,
140 scopes,
141 vars,
142 signals: HashMap::new(),
143 signals_to_be_loaded: HashSet::new(),
144 time_table: vec![],
145 source: None,
146 unique_id,
147 body_loaded: false,
148 }
149 }
150
151 pub fn body_loaded(&self) -> bool {
152 self.body_loaded
153 }
154
155 pub fn add_body(&mut self, body: BodyResult) -> Result<Option<LoadSignalsCmd>> {
156 if self.body_loaded {
157 bail!("Did we just parse the body twice? That should not happen!");
158 }
159 match body {
160 BodyResult::Local(body) => {
161 if self.server.is_some() {
162 bail!("We are connected to a server, but also received the result of parsing a file locally. Something is going wrong here!");
163 }
164 self.time_table = body.time_table;
165 self.source = Some(body.source);
166 }
167 BodyResult::Remote(time_table, server) => {
168 if let Some(old) = &self.server {
169 if old != &server {
170 bail!("Inconsistent server URLs: {old} vs. {server}")
171 }
172 } else {
173 bail!("Missing server URL!");
174 }
175 self.time_table = time_table;
176 }
177 }
178 self.body_loaded = true;
179
180 Ok(self.load_signals(&[]))
183 }
184
185 pub fn metadata(&self) -> MetaData {
186 let timescale = self
187 .hierarchy
188 .timescale()
189 .unwrap_or(Timescale::new(1, TimescaleUnit::Unknown));
190 let date = None;
191 MetaData {
192 date,
193 version: Some(self.hierarchy.version().to_string()),
194 timescale: TimeScale {
195 unit: TimeUnit::from(timescale.unit),
196 multiplier: Some(timescale.factor),
197 },
198 }
199 }
200
201 pub fn max_timestamp(&self) -> Option<BigUint> {
202 self.time_table.last().map(|t| BigUint::from(*t))
203 }
204
205 pub fn is_fully_loaded(&self) -> bool {
206 (self.source.is_some() || self.server.is_some()) && self.signals_to_be_loaded.is_empty()
207 }
208
209 pub fn variable_names(&self) -> Vec<String> {
210 self.vars.clone()
211 }
212
213 fn lookup_scope(&self, scope: &ScopeRef) -> Option<wellen::ScopeRef> {
214 match scope.id {
215 ScopeId::Wellen(id) => Some(id),
216 ScopeId::None => self.hierarchy.lookup_scope(scope.strs()),
217 }
218 }
219
220 fn has_scope(&self, scope: &ScopeRef) -> bool {
221 match scope.id {
222 ScopeId::Wellen(_) => true,
223 ScopeId::None => self.hierarchy.lookup_scope(scope.strs()).is_some(),
224 }
225 }
226
227 pub fn variables(&self) -> Vec<VariableRef> {
228 let h = &self.hierarchy;
229 h.iter_vars()
230 .map(|r| VariableRef::from_hierarchy_string(&r.full_name(h)))
231 .collect::<Vec<_>>()
232 }
233
234 pub fn variables_in_scope(&self, scope_ref: &ScopeRef) -> Vec<VariableRef> {
235 let h = &self.hierarchy;
236 if scope_ref.has_empty_strs() {
238 h.vars()
239 .filter(|id| h[*id].var_type() != VarType::Parameter)
240 .map(|id| {
241 VariableRef::new_with_id(
242 scope_ref.clone(),
243 h[id].name(h).to_string(),
244 VarId::Wellen(id),
245 )
246 })
247 .collect::<Vec<_>>()
248 } else {
249 let scope = match self.lookup_scope(scope_ref) {
250 Some(id) => &h[id],
251 None => {
252 warn!("Found no scope '{scope_ref}'. Defaulting to no variables");
253 return vec![];
254 }
255 };
256 scope
257 .vars(h)
258 .filter(|id| h[*id].var_type() != VarType::Parameter)
259 .map(|id| {
260 VariableRef::new_with_id(
261 scope_ref.clone(),
262 h[id].name(h).to_string(),
263 VarId::Wellen(id),
264 )
265 })
266 .collect::<Vec<_>>()
267 }
268 }
269
270 pub fn parameters_in_scope(&self, scope_ref: &ScopeRef) -> Vec<VariableRef> {
271 let h = &self.hierarchy;
272 if scope_ref.strs().is_empty() {
274 h.vars()
275 .filter(|id| h[*id].var_type() == VarType::Parameter)
276 .map(|id| {
277 VariableRef::new_with_id(
278 scope_ref.clone(),
279 h[id].name(h).to_string(),
280 VarId::Wellen(id),
281 )
282 })
283 .collect::<Vec<_>>()
284 } else {
285 let scope = match self.lookup_scope(scope_ref) {
286 Some(id) => &h[id],
287 None => {
288 warn!("Found no scope '{scope_ref}'. Defaulting to no variables");
289 return vec![];
290 }
291 };
292 scope
293 .vars(h)
294 .filter(|id| h[*id].var_type() == VarType::Parameter)
295 .map(|id| {
296 VariableRef::new_with_id(
297 scope_ref.clone(),
298 h[id].name(h).to_string(),
299 VarId::Wellen(id),
300 )
301 })
302 .collect::<Vec<_>>()
303 }
304 }
305
306 pub fn no_variables_in_scope(&self, scope_ref: &ScopeRef) -> bool {
307 let h = &self.hierarchy;
308 if scope_ref.has_empty_strs() {
310 h.vars().next().is_none()
311 } else {
312 let scope = match self.lookup_scope(scope_ref) {
313 Some(id) => &h[id],
314 None => {
315 warn!("Found no scope '{scope_ref}'. Defaulting to no variables");
316 return true;
317 }
318 };
319 scope.vars(h).next().is_none()
320 }
321 }
322
323 pub fn update_variable_ref(&self, variable: &VariableRef) -> Option<VariableRef> {
324 let h = &self.hierarchy;
326
327 let (var, new_scope_ref) = if variable.path.has_empty_strs() {
328 let var = h.lookup_var(&[], &variable.name)?;
329 (var, variable.path.clone())
330 } else {
331 let scope = h.lookup_scope(variable.path.strs())?;
333 let new_scope_ref = variable.path.with_id(ScopeId::Wellen(scope));
334
335 let var = h[scope].vars(h).find(|r| h[*r].name(h) == variable.name)?;
337 (var, new_scope_ref)
338 };
339
340 let new_variable_ref =
341 VariableRef::new_with_id(new_scope_ref, variable.name.clone(), VarId::Wellen(var));
342 Some(new_variable_ref)
343 }
344
345 pub fn get_var(&self, r: &VariableRef) -> Result<&Var> {
346 let h = &self.hierarchy;
347 self.get_var_ref(r).map(|r| &h[r])
348 }
349
350 pub fn get_enum_map(&self, v: &Var) -> HashMap<String, String> {
351 match v.enum_type(&self.hierarchy) {
352 None => HashMap::new(),
353 Some((_, mapping)) => HashMap::from_iter(
354 mapping
355 .into_iter()
356 .map(|(k, v)| (k.to_string(), v.to_string())),
357 ),
358 }
359 }
360
361 fn get_var_ref(&self, r: &VariableRef) -> Result<VarRef> {
362 match r.id {
363 VarId::Wellen(id) => Ok(id),
364 VarId::None => {
365 let h = &self.hierarchy;
366 let var = match h.lookup_var(r.path.strs(), &r.name) {
367 None => bail!("Failed to find variable: {r:?}"),
368 Some(id) => id,
369 };
370 Ok(var)
371 }
372 }
373 }
374
375 pub fn load_variables<S: AsRef<VariableRef>, T: Iterator<Item = S>>(
376 &mut self,
377 variables: T,
378 ) -> Result<Option<LoadSignalsCmd>> {
379 let h = &self.hierarchy;
380 let signal_refs = variables
381 .flat_map(|s| {
382 let r = s.as_ref();
383 self.get_var_ref(r).map(|v| h[v].signal_ref())
384 })
385 .collect::<Vec<_>>();
386 Ok(self.load_signals(&signal_refs))
387 }
388
389 pub fn load_all_params(&mut self) -> Result<Option<LoadSignalsCmd>> {
390 let h = &self.hierarchy;
391 let params = h
392 .iter_vars()
393 .filter(|r| r.var_type() == VarType::Parameter)
394 .map(|r| r.signal_ref())
395 .collect::<Vec<_>>();
396 Ok(self.load_signals(¶ms))
397 }
398
399 pub fn on_signals_loaded(&mut self, res: LoadSignalsResult) -> Result<Option<LoadSignalsCmd>> {
400 if res.from_unique_id == self.unique_id {
402 debug_assert!(self.source.is_none());
404 debug_assert!(self.server.is_none());
405 self.source = res.source;
406 self.server = res.server;
407 debug_assert!(self.server.is_some() || self.source.is_some());
408 for (id, signal) in res.signals {
410 self.signals.insert(id, signal);
411 }
412 }
413
414 Ok(self.load_signals(&[]))
416 }
417
418 fn load_signals(&mut self, ids: &[SignalRef]) -> Option<LoadSignalsCmd> {
419 let filtered_ids = ids
421 .iter()
422 .filter(|id| !self.signals.contains_key(id) && !self.signals_to_be_loaded.contains(id))
423 .cloned()
424 .collect::<Vec<_>>();
425
426 self.signals_to_be_loaded.extend(filtered_ids.iter());
428
429 if self.signals_to_be_loaded.is_empty() {
430 return None; }
432
433 if !self.body_loaded {
434 return None; }
436
437 if let Some(server) = std::mem::take(&mut self.server) {
439 let mut signals = Vec::from_iter(self.signals_to_be_loaded.drain());
441 signals.sort(); let cmd = LoadSignalsCmd {
443 signals,
444 payload: LoadSignalPayload::Remote(server),
445 from_unique_id: self.unique_id,
446 };
447 Some(cmd)
448 } else if let Some(source) = std::mem::take(&mut self.source) {
449 let mut signals = Vec::from_iter(self.signals_to_be_loaded.drain());
451 signals.sort(); let cmd = LoadSignalsCmd {
453 signals,
454 payload: LoadSignalPayload::Local(source, self.hierarchy.clone()),
455 from_unique_id: self.unique_id,
456 };
457 Some(cmd)
458 } else {
459 None
460 }
461 }
462
463 fn time_to_time_table_idx(&self, time: &BigUint) -> Option<TimeTableIdx> {
464 let time: Time = time.to_u64().expect("unsupported time!");
465 let table = &self.time_table;
466 if table.is_empty() || table[0] > time {
467 None
468 } else {
469 let idx = binary_search(table, time);
471 assert!(table[idx] <= time);
472 Some(idx as TimeTableIdx)
473 }
474 }
475
476 pub fn query_variable(
477 &self,
478 variable: &VariableRef,
479 time: &BigUint,
480 ) -> Result<Option<QueryResult>> {
481 let h = &self.hierarchy;
482 let var_ref = self.get_var_ref(variable)?;
484 let signal_ref = h[var_ref].signal_ref();
486 let sig = match self.signals.get(&signal_ref) {
487 Some(sig) => sig,
488 None => {
489 return Ok(None);
491 }
492 };
493 let time_table = &self.time_table;
494
495 if let Some(idx) = self.time_to_time_table_idx(time) {
497 if let Some(offset) = sig.get_offset(idx) {
499 let offset_time_idx = sig.get_time_idx_at(&offset);
501 let offset_time = time_table[offset_time_idx as usize];
502 let current_value = sig.get_value_at(&offset, offset.elements - 1);
504 let next_time = offset
506 .next_index
507 .and_then(|i| time_table.get(i.get() as usize));
508
509 let converted_value = convert_variable_value(current_value);
510 let result = QueryResult {
511 current: Some((BigUint::from(offset_time), converted_value)),
512 next: next_time.map(|t| BigUint::from(*t)),
513 };
514 return Ok(Some(result));
515 }
516 }
517
518 let first_index = sig.get_first_time_idx();
520 let next_time = first_index.and_then(|i| time_table.get(i as usize));
521 let result = QueryResult {
522 current: None,
523 next: next_time.map(|t| BigUint::from(*t)),
524 };
525 Ok(Some(result))
526 }
527
528 pub fn scope_names(&self) -> Vec<String> {
529 self.scopes.clone()
530 }
531
532 pub fn root_scopes(&self) -> Vec<ScopeRef> {
533 let h = &self.hierarchy;
534 h.scopes()
535 .map(|id| ScopeRef::from_strs_with_id(&[h[id].name(h)], ScopeId::Wellen(id)))
536 .collect::<Vec<_>>()
537 }
538
539 pub fn child_scopes(&self, scope_ref: &ScopeRef) -> Result<Vec<ScopeRef>> {
540 let h = &self.hierarchy;
541 let scope = match self.lookup_scope(scope_ref) {
542 Some(id) => &h[id],
543 None => return Err(anyhow!("Failed to find scope {scope_ref:?}")),
544 };
545 Ok(scope
546 .scopes(h)
547 .map(|id| scope_ref.with_subscope(h[id].name(h).to_string(), ScopeId::Wellen(id)))
548 .collect::<Vec<_>>())
549 }
550
551 pub fn scope_exists(&self, scope: &ScopeRef) -> bool {
552 scope.has_empty_strs() | self.has_scope(scope)
553 }
554
555 pub fn get_scope_tooltip_data(&self, scope: &ScopeRef) -> String {
556 let mut out = String::new();
557 if let Some(scope_ref) = self.lookup_scope(scope) {
558 let h = &self.hierarchy;
559 let scope = &h[scope_ref];
560 writeln!(&mut out, "{}", scope_type_to_string(scope.scope_type())).unwrap();
561 if let Some((path, line)) = scope.instantiation_source_loc(h) {
562 writeln!(&mut out, "{path}:{line}").unwrap();
563 }
564 match (scope.component(h), scope.source_loc(h)) {
565 (Some(name), Some((path, line))) => {
566 write!(&mut out, "{name} : {path}:{line}").unwrap();
567 }
568 (None, Some((path, line))) => {
569 let same = scope
571 .instantiation_source_loc(h)
572 .is_some_and(|(i_path, i_line)| path == i_path && line == i_line);
573 if !same {
574 write!(&mut out, "{path}:{line}").unwrap();
575 }
576 }
577 (Some(name), None) => write!(&mut out, "{name}").unwrap(),
578 (None, None) => {}
580 }
581 }
582 if out.ends_with('\n') {
583 out.pop().unwrap();
584 }
585 out
586 }
587
588 pub fn variable_to_meta(&self, variable: &VariableRef) -> Result<VariableMeta> {
589 let var = self.get_var(variable)?;
590 let encoding = match var.signal_encoding() {
591 SignalEncoding::String => VariableEncoding::String,
592 SignalEncoding::Real => VariableEncoding::Real,
593 SignalEncoding::BitVector(_) => VariableEncoding::BitVector,
594 };
595 Ok(VariableMeta {
596 var: variable.clone(),
597 num_bits: var.length(),
598 variable_type: Some(VariableType::from_wellen_type(var.var_type())),
599 variable_type_name: var.vhdl_type_name(&self.hierarchy).map(|s| s.to_string()),
600 index: var.index().map(VariableIndex::from_wellen_type),
601 direction: Some(VariableDirection::from_wellen_direction(var.direction())),
602 enum_map: self.get_enum_map(var),
603 encoding,
604 })
605 }
606}
607
608fn scope_type_to_string(tpe: ScopeType) -> &'static str {
609 match tpe {
610 ScopeType::Module => "module",
611 ScopeType::Task => "task",
612 ScopeType::Function => "function",
613 ScopeType::Begin => "begin",
614 ScopeType::Fork => "fork",
615 ScopeType::Generate => "generate",
616 ScopeType::Struct => "struct",
617 ScopeType::Union => "union",
618 ScopeType::Class => "class",
619 ScopeType::Interface => "interface",
620 ScopeType::Package => "package",
621 ScopeType::Program => "program",
622 ScopeType::VhdlArchitecture => "architecture",
623 ScopeType::VhdlProcedure => "procedure",
624 ScopeType::VhdlFunction => "function",
625 ScopeType::VhdlRecord => "record",
626 ScopeType::VhdlProcess => "process",
627 ScopeType::VhdlBlock => "block",
628 ScopeType::VhdlForGenerate => "for-generate",
629 ScopeType::VhdlIfGenerate => "if-generate",
630 ScopeType::VhdlGenerate => "generate",
631 ScopeType::VhdlPackage => "package",
632 ScopeType::GhwGeneric => "generic",
633 ScopeType::VhdlArray => "array",
634 ScopeType::Unknown => "unknown",
635 _ => todo!(),
636 }
637}
638
639fn convert_variable_value(value: wellen::SignalValue) -> VariableValue {
640 match value {
641 wellen::SignalValue::Binary(data, _bits) => {
642 VariableValue::BigUint(BigUint::from_bytes_be(data))
643 }
644 wellen::SignalValue::FourValue(_, _) | wellen::SignalValue::NineValue(_, _) => {
645 VariableValue::String(
646 value
647 .to_bit_string()
648 .expect("failed to convert value {value:?} to a string"),
649 )
650 }
651 wellen::SignalValue::String(value) => VariableValue::String(value.to_string()),
652 wellen::SignalValue::Real(value) => VariableValue::String(format!("{value}")),
653 }
654}
655
656#[local_impl::local_impl]
657impl FromVarType for VariableType {
658 fn from(signaltype: VarType) -> Self {
659 match signaltype {
660 VarType::Reg => VariableType::VCDReg,
661 VarType::Wire => VariableType::VCDWire,
662 VarType::Integer => VariableType::VCDInteger,
663 VarType::Real => VariableType::VCDReal,
664 VarType::Parameter => VariableType::VCDParameter,
665 VarType::String => VariableType::VCDString,
666 VarType::Time => VariableType::VCDTime,
667 VarType::Event => VariableType::VCDEvent,
668 VarType::Supply0 => VariableType::VCDSupply0,
669 VarType::Supply1 => VariableType::VCDSupply1,
670 VarType::Tri => VariableType::VCDTri,
671 VarType::TriAnd => VariableType::VCDTriAnd,
672 VarType::TriOr => VariableType::VCDTriOr,
673 VarType::TriReg => VariableType::VCDTriReg,
674 VarType::Tri0 => VariableType::VCDTri0,
675 VarType::Tri1 => VariableType::VCDTri1,
676 VarType::WAnd => VariableType::VCDWAnd,
677 VarType::WOr => VariableType::VCDWOr,
678 VarType::Port => VariableType::Port,
679 VarType::Bit => VariableType::Bit,
680 VarType::Logic => VariableType::Logic,
681 VarType::Int => VariableType::VCDInteger,
682 VarType::Enum => VariableType::Enum,
683 VarType::SparseArray => VariableType::SparseArray,
684 VarType::RealTime => VariableType::RealTime,
685 VarType::ShortInt => VariableType::ShortInt,
686 VarType::LongInt => VariableType::LongInt,
687 VarType::Byte => VariableType::Byte,
688 VarType::ShortReal => VariableType::ShortReal,
689 VarType::Boolean => VariableType::Boolean,
690 VarType::BitVector => VariableType::BitVector,
691 VarType::StdLogic => VariableType::StdLogic,
692 VarType::StdLogicVector => VariableType::StdLogicVector,
693 VarType::StdULogic => VariableType::StdULogic,
694 VarType::StdULogicVector => VariableType::StdULogicVector,
695 }
696 }
697}
698
699#[inline]
700fn binary_search(times: &[Time], needle: Time) -> usize {
701 let mut lower_idx = 0usize;
702 let mut upper_idx = times.len() - 1;
703 while lower_idx <= upper_idx {
704 let mid_idx = lower_idx + ((upper_idx - lower_idx) / 2);
705
706 match times[mid_idx].cmp(&needle) {
707 std::cmp::Ordering::Less => {
708 lower_idx = mid_idx + 1;
709 }
710 std::cmp::Ordering::Equal => {
711 return mid_idx;
712 }
713 std::cmp::Ordering::Greater => {
714 upper_idx = mid_idx - 1;
715 }
716 }
717 }
718 lower_idx - 1
719}
720
721#[cfg(test)]
722mod tests {
723 use super::*;
724
725 #[test]
726 fn test_signal_conversion() {
727 let inp0: &[u8] = &[128, 0, 0, 3];
728 let out0 = convert_variable_value(wellen::SignalValue::Binary(inp0, 32));
729 assert_eq!(out0, VariableValue::BigUint(BigUint::from(0x80000003u64)));
730 }
731}