Skip to main content

oxilean_codegen/chisel_backend/
functions.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use super::types::{
6    ChiselAnalysisCache, ChiselAnnotationKind, ChiselBackend, ChiselConstantFoldingHelper,
7    ChiselDepGraph, ChiselDominatorTree, ChiselExpr, ChiselInterfaceTemplate, ChiselLivenessInfo,
8    ChiselModule, ChiselPassConfig, ChiselPassPhase, ChiselPassRegistry, ChiselPassStats,
9    ChiselPipelineRegisterChain, ChiselPort, ChiselReadyValidBundle, ChiselSRAMWrapper,
10    ChiselStreamingModule, ChiselType, ChiselWorklist, PipelineStage, StreamDirection,
11};
12
13#[cfg(test)]
14mod tests {
15    use super::*;
16    #[test]
17    pub(super) fn test_type_uint() {
18        assert_eq!(ChiselType::UInt(8).to_string(), "UInt(8.W)");
19    }
20    #[test]
21    pub(super) fn test_type_sint() {
22        assert_eq!(ChiselType::SInt(16).to_string(), "SInt(16.W)");
23    }
24    #[test]
25    pub(super) fn test_type_bool() {
26        assert_eq!(ChiselType::Bool.to_string(), "Bool()");
27    }
28    #[test]
29    pub(super) fn test_type_clock() {
30        assert_eq!(ChiselType::Clock.to_string(), "Clock()");
31    }
32    #[test]
33    pub(super) fn test_type_reset() {
34        assert_eq!(ChiselType::Reset.to_string(), "Reset()");
35    }
36    #[test]
37    pub(super) fn test_type_async_reset() {
38        assert_eq!(ChiselType::AsyncReset.to_string(), "AsyncReset()");
39    }
40    #[test]
41    pub(super) fn test_type_vec() {
42        let t = ChiselType::Vec(4, Box::new(ChiselType::UInt(32)));
43        assert_eq!(t.to_string(), "Vec(4, UInt(32.W))");
44    }
45    #[test]
46    pub(super) fn test_type_bundle() {
47        let b = ChiselType::Bundle(vec![
48            ("data".to_string(), Box::new(ChiselType::UInt(8))),
49            ("valid".to_string(), Box::new(ChiselType::Bool)),
50        ]);
51        let s = b.to_string();
52        assert!(s.contains("val data = Output(UInt(8.W))"));
53        assert!(s.contains("val valid = Output(Bool())"));
54    }
55    #[test]
56    pub(super) fn test_port_input() {
57        let p = ChiselPort::input("clk", ChiselType::Clock);
58        assert_eq!(p.name, "clk");
59        assert!(!p.is_output);
60        assert_eq!(p.direction(), "Input");
61    }
62    #[test]
63    pub(super) fn test_port_output() {
64        let p = ChiselPort::output("out", ChiselType::UInt(8));
65        assert_eq!(p.name, "out");
66        assert!(p.is_output);
67        assert_eq!(p.direction(), "Output");
68    }
69    #[test]
70    pub(super) fn test_expr_ulit() {
71        let e = ChiselExpr::ULit(42, 8);
72        assert_eq!(e.to_string(), "42.U(8.W)");
73    }
74    #[test]
75    pub(super) fn test_expr_slit() {
76        let e = ChiselExpr::SLit(-1, 8);
77        assert_eq!(e.to_string(), "-1.S(8.W)");
78    }
79    #[test]
80    pub(super) fn test_expr_bool_lit() {
81        assert_eq!(ChiselExpr::BoolLit(true).to_string(), "true.B");
82        assert_eq!(ChiselExpr::BoolLit(false).to_string(), "false.B");
83    }
84    #[test]
85    pub(super) fn test_expr_var() {
86        let e = ChiselExpr::Var("myReg".to_string());
87        assert_eq!(e.to_string(), "myReg");
88    }
89    #[test]
90    pub(super) fn test_expr_io() {
91        let e = ChiselExpr::Io("in_data".to_string());
92        assert_eq!(e.to_string(), "io.in_data");
93    }
94    #[test]
95    pub(super) fn test_expr_binop() {
96        let lhs = ChiselExpr::Io("a".to_string());
97        let rhs = ChiselExpr::Io("b".to_string());
98        let e = ChiselExpr::BinOp(Box::new(lhs), "+".to_string(), Box::new(rhs));
99        assert_eq!(e.to_string(), "(io.a + io.b)");
100    }
101    #[test]
102    pub(super) fn test_expr_unop() {
103        let inner = ChiselExpr::Io("x".to_string());
104        let e = ChiselExpr::UnOp("~".to_string(), Box::new(inner));
105        assert_eq!(e.to_string(), "(~(io.x))");
106    }
107    #[test]
108    pub(super) fn test_expr_mux() {
109        let e = ChiselExpr::Mux(
110            Box::new(ChiselExpr::Io("sel".to_string())),
111            Box::new(ChiselExpr::ULit(1, 1)),
112            Box::new(ChiselExpr::ULit(0, 1)),
113        );
114        assert_eq!(e.to_string(), "Mux(io.sel, 1.U(1.W), 0.U(1.W))");
115    }
116    #[test]
117    pub(super) fn test_expr_bitslice() {
118        let e = ChiselExpr::BitSlice(Box::new(ChiselExpr::Var("data".to_string())), 7, 0);
119        assert_eq!(e.to_string(), "data(7, 0)");
120    }
121    #[test]
122    pub(super) fn test_expr_cat() {
123        let e = ChiselExpr::Cat(vec![
124            ChiselExpr::Io("msb".to_string()),
125            ChiselExpr::Io("lsb".to_string()),
126        ]);
127        assert_eq!(e.to_string(), "Cat(io.msb, io.lsb)");
128    }
129    #[test]
130    pub(super) fn test_expr_method_call() {
131        let e = ChiselExpr::MethodCall(
132            Box::new(ChiselExpr::Var("fifo".to_string())),
133            "enq".to_string(),
134            vec![ChiselExpr::Io("data".to_string())],
135        );
136        assert_eq!(e.to_string(), "fifo.enq(io.data)");
137    }
138    #[test]
139    pub(super) fn test_connect() {
140        let b = ChiselBackend::new();
141        assert_eq!(b.connect("io.out", "reg_data"), "io.out := reg_data");
142    }
143    #[test]
144    pub(super) fn test_when_stmt() {
145        let b = ChiselBackend::new();
146        let result = b.when_stmt("io.en", "reg_q := io.d");
147        assert!(result.contains("when (io.en)"));
148        assert!(result.contains("reg_q := io.d"));
149    }
150    #[test]
151    pub(super) fn test_when_otherwise() {
152        let b = ChiselBackend::new();
153        let result = b.when_otherwise("io.rst", "reg_q := 0.U", "reg_q := io.d");
154        assert!(result.contains("when (io.rst)"));
155        assert!(result.contains(".otherwise"));
156        assert!(result.contains("reg_q := 0.U"));
157        assert!(result.contains("reg_q := io.d"));
158    }
159    #[test]
160    pub(super) fn test_reg_init() {
161        let b = ChiselBackend::new();
162        let result = b.reg_init("counter", &ChiselType::UInt(8), "0");
163        assert!(result.contains("val counter = RegInit("));
164        assert!(result.contains("UInt(8.W)"));
165    }
166    #[test]
167    pub(super) fn test_reg_no_reset() {
168        let b = ChiselBackend::new();
169        let result = b.reg_no_reset("data_reg", &ChiselType::UInt(32));
170        assert_eq!(result, "val data_reg = Reg(UInt(32.W))");
171    }
172    #[test]
173    pub(super) fn test_wire_decl() {
174        let b = ChiselBackend::new();
175        let result = b.wire_decl("tmp", &ChiselType::Bool);
176        assert_eq!(result, "val tmp = Wire(Bool())");
177    }
178    #[test]
179    pub(super) fn test_printf() {
180        let b = ChiselBackend::new();
181        let r1 = b.printf("val=%d", &["x"]);
182        assert!(r1.contains("printf(\"val=%d\\n\", x)"));
183        let r2 = b.printf("hello", &[]);
184        assert!(r2.contains("printf(\"hello\\n\")"));
185    }
186    #[test]
187    pub(super) fn test_assert_stmt() {
188        let b = ChiselBackend::new();
189        let result = b.assert_stmt("io.valid", "input must be valid");
190        assert_eq!(result, "assert(io.valid, \"input must be valid\")");
191    }
192    #[test]
193    pub(super) fn test_mux_expr() {
194        let b = ChiselBackend::new();
195        assert_eq!(b.mux_expr("sel", "a", "b"), "Mux(sel, a, b)");
196    }
197    #[test]
198    pub(super) fn test_cat_expr() {
199        let b = ChiselBackend::new();
200        assert_eq!(b.cat_expr(&["msb", "lsb"]), "Cat(msb, lsb)");
201    }
202    #[test]
203    pub(super) fn test_fill_expr() {
204        let b = ChiselBackend::new();
205        assert_eq!(b.fill_expr(8, "0.U(1.W)"), "Fill(8, 0.U(1.W))");
206    }
207    #[test]
208    pub(super) fn test_instantiate() {
209        let b = ChiselBackend::new();
210        assert_eq!(
211            b.instantiate("Adder", "u_adder"),
212            "val u_adder = Module(new Adder())"
213        );
214    }
215    #[test]
216    pub(super) fn test_emit_expr() {
217        let b = ChiselBackend::new();
218        let e = ChiselExpr::ULit(255, 8);
219        assert_eq!(b.emit_expr(&e), "255.U(8.W)");
220    }
221    #[test]
222    pub(super) fn test_io_bundle_basic() {
223        let b = ChiselBackend::new();
224        let ports = vec![
225            ChiselPort::input("clk", ChiselType::Clock),
226            ChiselPort::input("in", ChiselType::UInt(8)),
227            ChiselPort::output("out", ChiselType::UInt(8)),
228        ];
229        let result = b.io_bundle(&ports);
230        assert!(result.contains("val io = IO(new Bundle {"));
231        assert!(result.contains("val clk = Input(Clock())"));
232        assert!(result.contains("val in = Input(UInt(8.W))"));
233        assert!(result.contains("val out = Output(UInt(8.W))"));
234    }
235    #[test]
236    pub(super) fn test_io_bundle_empty() {
237        let b = ChiselBackend::new();
238        let result = b.io_bundle(&[]);
239        assert!(result.contains("val io = IO(new Bundle {"));
240        assert!(result.ends_with("})"));
241    }
242    #[test]
243    pub(super) fn test_emit_simple_passthrough() {
244        let b = ChiselBackend::new();
245        let mut m = ChiselModule::new("Passthrough");
246        m.add_input("in", ChiselType::UInt(8));
247        m.add_output("out", ChiselType::UInt(8));
248        m.add_stmt(b.connect("io.out", "io.in"));
249        let code = b.emit_module(&m);
250        assert!(code.contains("class Passthrough extends Module"));
251        assert!(code.contains("import chisel3._"));
252        assert!(code.contains("val io = IO(new Bundle {"));
253        assert!(code.contains("io.out := io.in"));
254        assert!(code.ends_with("}\n"));
255    }
256    #[test]
257    pub(super) fn test_emit_d_flip_flop() {
258        let b = ChiselBackend::new();
259        let mut m = ChiselModule::new("DFlipFlop");
260        m.add_input("d", ChiselType::Bool);
261        m.add_output("q", ChiselType::Bool);
262        m.add_stmt(b.reg_init("reg_q", &ChiselType::Bool, "false"));
263        m.add_stmt(b.connect("reg_q", "io.d"));
264        m.add_stmt(b.connect("io.q", "reg_q"));
265        let code = b.emit_module(&m);
266        assert!(code.contains("class DFlipFlop extends Module"));
267        assert!(code.contains("RegInit("));
268        assert!(code.contains("io.q := reg_q"));
269    }
270    #[test]
271    pub(super) fn test_emit_module_no_ports() {
272        let b = ChiselBackend::new();
273        let m = ChiselModule::new("EmptyMod");
274        let code = b.emit_module(&m);
275        assert!(code.contains("class EmptyMod extends Module"));
276        assert!(code.ends_with("}\n"));
277    }
278    #[test]
279    pub(super) fn test_emit_counter() {
280        let b = ChiselBackend::new();
281        let mut m = ChiselModule::new("Counter");
282        m.add_input("en", ChiselType::Bool);
283        m.add_output("count", ChiselType::UInt(8));
284        m.add_stmt(b.reg_init("cnt", &ChiselType::UInt(8), "0"));
285        m.add_stmt(b.when_stmt("io.en", "cnt := cnt + 1.U"));
286        m.add_stmt(b.connect("io.count", "cnt"));
287        let code = b.emit_module(&m);
288        assert!(code.contains("class Counter extends Module"));
289        assert!(code.contains("when (io.en)"));
290        assert!(code.contains("cnt := cnt + 1.U"));
291        assert!(code.contains("io.count := cnt"));
292    }
293    #[test]
294    pub(super) fn test_chisel_module_add_helpers() {
295        let mut m = ChiselModule::new("Test");
296        m.add_input("a", ChiselType::UInt(4));
297        m.add_output("b", ChiselType::UInt(4));
298        m.add_stmt("val x = Wire(UInt(4.W))");
299        assert_eq!(m.ports.len(), 2);
300        assert_eq!(m.body.len(), 1);
301    }
302    #[test]
303    pub(super) fn test_chisel_backend_default() {
304        let b = ChiselBackend::default();
305        let m = ChiselModule::new("Default");
306        let code = b.emit_module(&m);
307        assert!(code.contains("class Default extends Module"));
308    }
309}
310#[cfg(test)]
311mod chisel_new_tests {
312    use super::*;
313    #[test]
314    pub(super) fn test_ready_valid_bundle_basic() {
315        let rv = ChiselReadyValidBundle::new(ChiselType::UInt(32));
316        let s = rv.emit_decoupled("out_port", true);
317        assert!(s.contains("Decoupled"));
318        assert!(s.contains("out_port"));
319    }
320    #[test]
321    pub(super) fn test_ready_valid_bundle_with_last() {
322        let rv = ChiselReadyValidBundle::new(ChiselType::UInt(8)).with_last();
323        let s = rv.emit_decoupled("stream", true);
324        assert!(s.contains("stream_last"));
325    }
326    #[test]
327    pub(super) fn test_ready_valid_bundle_with_keep() {
328        let rv = ChiselReadyValidBundle::new(ChiselType::UInt(64)).with_keep(8);
329        let s = rv.emit_decoupled("data", true);
330        assert!(s.contains("data_keep"));
331        assert!(s.contains("8.W"));
332    }
333    #[test]
334    pub(super) fn test_ready_valid_fire() {
335        let rv = ChiselReadyValidBundle::new(ChiselType::UInt(32));
336        let s = rv.emit_fire("ch");
337        assert!(s.contains("ch_fire"));
338        assert!(s.contains("ch.valid && ch.ready"));
339    }
340    #[test]
341    pub(super) fn test_ready_valid_queue() {
342        let rv = ChiselReadyValidBundle::new(ChiselType::UInt(8));
343        let s = rv.emit_queue("inp", "out", 16);
344        assert!(s.contains("Queue"));
345        assert!(s.contains("16"));
346    }
347    #[test]
348    pub(super) fn test_streaming_producer_emit() {
349        let m = ChiselStreamingModule::producer("Src", 32).with_tlast();
350        let s = m.emit();
351        assert!(s.contains("class Src extends Module"));
352        assert!(s.contains("tdata"));
353        assert!(s.contains("tvalid"));
354        assert!(s.contains("tready"));
355        assert!(s.contains("tlast"));
356    }
357    #[test]
358    pub(super) fn test_streaming_consumer_emit() {
359        let m = ChiselStreamingModule::consumer("Sink", 64);
360        let s = m.emit();
361        assert!(s.contains("class Sink extends Module"));
362        assert!(s.contains("Input(Bool())"));
363    }
364    #[test]
365    pub(super) fn test_streaming_with_tid_and_tuser() {
366        let m = ChiselStreamingModule::producer("Src2", 128)
367            .with_tid(4)
368            .with_tuser(8);
369        let s = m.emit();
370        assert!(s.contains("tid"));
371        assert!(s.contains("tuser"));
372        assert!(s.contains("4.W"));
373        assert!(s.contains("8.W"));
374    }
375    #[test]
376    pub(super) fn test_streaming_with_body() {
377        let m = ChiselStreamingModule::producer("Gen", 32).add_stmt("val cnt = RegInit(0.U(32.W))");
378        let s = m.emit();
379        assert!(s.contains("val cnt"));
380    }
381    #[test]
382    pub(super) fn test_interface_sram_master() {
383        let t = ChiselInterfaceTemplate::SramPort {
384            addr_bits: 10,
385            data_bits: 32,
386        };
387        let s = t.emit_ports("sram", true);
388        assert!(s.contains("sram_addr"));
389        assert!(s.contains("sram_wdata"));
390        assert!(s.contains("10.W"));
391    }
392    #[test]
393    pub(super) fn test_interface_apb_master() {
394        let t = ChiselInterfaceTemplate::ApbPort {
395            addr_bits: 32,
396            data_bits: 32,
397        };
398        let s = t.emit_ports("apb", true);
399        assert!(s.contains("apb_paddr"));
400        assert!(s.contains("apb_pready"));
401        assert!(s.contains("pwrite"));
402    }
403    #[test]
404    pub(super) fn test_interface_ahb_lite() {
405        let t = ChiselInterfaceTemplate::AhbLitePort {
406            addr_bits: 32,
407            data_bits: 32,
408        };
409        let s = t.emit_ports("bus", true);
410        assert!(s.contains("bus_haddr"));
411        assert!(s.contains("htrans"));
412    }
413    #[test]
414    pub(super) fn test_interface_axi4_lite() {
415        let t = ChiselInterfaceTemplate::Axi4LitePort {
416            addr_bits: 32,
417            data_bits: 32,
418        };
419        let s = t.emit_ports("axi", true);
420        assert!(s.contains("awvalid"));
421        assert!(s.contains("arready"));
422        assert!(s.contains("wstrb"));
423    }
424    #[test]
425    pub(super) fn test_annotation_dont_touch() {
426        let ann = ChiselAnnotationKind::DontTouch;
427        let s = ann.scala_annotation("io.sig");
428        assert!(s.contains("DontTouch"));
429        assert!(s.contains("io.sig"));
430    }
431    #[test]
432    pub(super) fn test_annotation_load_memory() {
433        let ann = ChiselAnnotationKind::LoadMemoryAnnotation {
434            file: "mem.hex".into(),
435        };
436        let s = ann.scala_annotation("mem_module");
437        assert!(s.contains("loadMemoryFromFile"));
438        assert!(s.contains("mem.hex"));
439    }
440    #[test]
441    pub(super) fn test_annotation_inline_instance() {
442        let ann = ChiselAnnotationKind::InlineInstance;
443        let s = ann.scala_annotation("sub");
444        assert!(s.contains("Inline"));
445    }
446    #[test]
447    pub(super) fn test_pipeline_stage_chain() {
448        let chain = ChiselPipelineRegisterChain::new("0")
449            .stage(PipelineStage::new("s0", ChiselType::UInt(32)).with_valid())
450            .stage(
451                PipelineStage::new("s1", ChiselType::UInt(32))
452                    .with_valid()
453                    .with_stall(),
454            );
455        let s = chain.emit_registers();
456        assert!(s.contains("s0"));
457        assert!(s.contains("s1"));
458        assert!(s.contains("s0_valid"));
459        assert!(s.contains("s1_stall"));
460    }
461    #[test]
462    pub(super) fn test_pipeline_stage_count() {
463        let chain = ChiselPipelineRegisterChain::new("0")
464            .stage(PipelineStage::new("a", ChiselType::Bool))
465            .stage(PipelineStage::new("b", ChiselType::Bool))
466            .stage(PipelineStage::new("c", ChiselType::Bool));
467        assert_eq!(chain.stage_count(), 3);
468    }
469    #[test]
470    pub(super) fn test_sram_wrapper_single_port_emit() {
471        let sram = ChiselSRAMWrapper::single_port("RegFile", 1024, 64);
472        let s = sram.emit();
473        assert!(s.contains("class RegFile extends Module"));
474        assert!(s.contains("SyncReadMem(1024"));
475        assert!(s.contains("64.W"));
476        assert!(s.contains("wen"));
477    }
478    #[test]
479    pub(super) fn test_sram_wrapper_addr_width() {
480        let sram = ChiselSRAMWrapper::single_port("M", 256, 32);
481        assert_eq!(sram.addr_width(), 8);
482    }
483    #[test]
484    pub(super) fn test_sram_wrapper_with_mask() {
485        let sram = ChiselSRAMWrapper::single_port("M", 64, 32).with_mask(8);
486        assert_eq!(sram.mask_width(), 4);
487        let s = sram.emit();
488        assert!(s.contains("wmask"));
489    }
490    #[test]
491    pub(super) fn test_sram_wrapper_sdp() {
492        let sram = ChiselSRAMWrapper::simple_dual_port("Sdp", 512, 32);
493        let s = sram.emit();
494        assert!(s.contains("raddr"));
495        assert!(s.contains("rdata"));
496    }
497    #[test]
498    pub(super) fn test_sram_wrapper_pipeline_read() {
499        let sram = ChiselSRAMWrapper::single_port("PL", 64, 8).with_pipeline_read();
500        let s = sram.emit();
501        assert!(s.contains("raddr_r"));
502        assert!(s.contains("RegNext"));
503    }
504    #[test]
505    pub(super) fn test_backend_dont_care() {
506        let b = ChiselBackend::new();
507        let s = b.dont_care("io.out");
508        assert!(s.contains("DontCare"));
509        assert!(s.contains("io.out"));
510    }
511    #[test]
512    pub(super) fn test_backend_irrevocable_port() {
513        let b = ChiselBackend::new();
514        let s = b.irrevocable_port("out", &ChiselType::UInt(8), true);
515        assert!(s.contains("Irrevocable"));
516        assert!(s.contains("out"));
517    }
518    #[test]
519    pub(super) fn test_backend_comb_rom() {
520        let b = ChiselBackend::new();
521        let s = b.comb_rom("lut", &ChiselType::UInt(8), &["0", "1", "2", "255"]);
522        assert!(s.contains("VecInit"));
523        assert!(s.contains("255.U"));
524    }
525    #[test]
526    pub(super) fn test_backend_mux1h() {
527        let b = ChiselBackend::new();
528        let s = b.mux1h("sel", &[("sel(0)", "a"), ("sel(1)", "b")]);
529        assert!(s.contains("Mux1H"));
530        assert!(s.contains("sel(0)"));
531    }
532    #[test]
533    pub(super) fn test_backend_log2_ceil() {
534        let b = ChiselBackend::new();
535        assert_eq!(b.log2_ceil(1), 1);
536        assert_eq!(b.log2_ceil(8), 3);
537        assert_eq!(b.log2_ceil(9), 4);
538    }
539    #[test]
540    pub(super) fn test_backend_log2_floor() {
541        let b = ChiselBackend::new();
542        assert_eq!(b.log2_floor(8), 3);
543        assert_eq!(b.log2_floor(9), 3);
544    }
545    #[test]
546    pub(super) fn test_backend_is_pow2() {
547        let b = ChiselBackend::new();
548        assert!(b.is_pow2(1));
549        assert!(b.is_pow2(64));
550        assert!(!b.is_pow2(0));
551        assert!(!b.is_pow2(3));
552    }
553    #[test]
554    pub(super) fn test_backend_cover_stmt() {
555        let b = ChiselBackend::new();
556        let s = b.cover_stmt("io.valid", "valid_active");
557        assert!(s.contains("cover"));
558        assert!(s.contains("io.valid"));
559    }
560    #[test]
561    pub(super) fn test_backend_assume_stmt() {
562        let b = ChiselBackend::new();
563        let s = b.assume_stmt("io.en");
564        assert!(s.contains("assume"));
565    }
566    #[test]
567    pub(super) fn test_backend_cat() {
568        let b = ChiselBackend::new();
569        let s = b.cat(&["a", "b", "c"]);
570        assert!(s.contains("Cat(a, b, c)"));
571    }
572    #[test]
573    pub(super) fn test_backend_popcount() {
574        let b = ChiselBackend::new();
575        let s = b.popcount("mask");
576        assert!(s.contains("PopCount(mask)"));
577    }
578    #[test]
579    pub(super) fn test_backend_oh_to_uint() {
580        let b = ChiselBackend::new();
581        let s = b.oh_to_uint("oh_sig");
582        assert!(s.contains("OHToUInt(oh_sig)"));
583    }
584    #[test]
585    pub(super) fn test_backend_mux_case() {
586        let b = ChiselBackend::new();
587        let s = b.mux_case("0.U", &[("a === 1.U", "x"), ("a === 2.U", "y")]);
588        assert!(s.contains("MuxCase"));
589        assert!(s.contains("a === 1.U"));
590    }
591    #[test]
592    pub(super) fn test_backend_shift_register() {
593        let b = ChiselBackend::new();
594        let s = b.shift_register("io.in", 4, "0");
595        assert!(s.contains("ShiftRegister"));
596        assert!(s.contains("io.in"));
597        assert!(s.contains(", 4,"));
598    }
599    #[test]
600    pub(super) fn test_backend_rr_arbiter() {
601        let b = ChiselBackend::new();
602        let s = b.round_robin_arbiter("arb", &ChiselType::UInt(8), 4);
603        assert!(s.contains("RRArbiter"));
604        assert!(s.contains("arb"));
605    }
606    #[test]
607    pub(super) fn test_backend_priority_arbiter() {
608        let b = ChiselBackend::new();
609        let s = b.priority_arbiter("parb", &ChiselType::Bool, 2);
610        assert!(s.contains("Arbiter"));
611    }
612    #[test]
613    pub(super) fn test_backend_queue_module() {
614        let b = ChiselBackend::new();
615        let s = b.queue_module("fifo", &ChiselType::UInt(32), 8);
616        assert!(s.contains("Queue"));
617        assert!(s.contains("fifo"));
618        assert!(s.contains(", 8)"));
619    }
620    #[test]
621    pub(super) fn test_backend_when_chain() {
622        let b = ChiselBackend::new();
623        let s = b.when_chain(&[("a", "x := 1.U"), ("b", "x := 2.U")], Some("x := 0.U"));
624        assert!(s.contains("when (a)"));
625        assert!(s.contains("elsewhen (b)"));
626        assert!(s.contains("otherwise"));
627    }
628    #[test]
629    pub(super) fn test_backend_counter() {
630        let b = ChiselBackend::new();
631        let s = b.counter("cyc", 99, "true.B");
632        assert!(s.contains("Counter"));
633        assert!(s.contains("cyc_count"));
634    }
635    #[test]
636    pub(super) fn test_backend_reset_sync() {
637        let b = ChiselBackend::new();
638        let s = b.reset_sync("rst", "io.async_rst");
639        assert!(s.contains("rst_sync"));
640        assert!(s.contains("asAsyncReset"));
641    }
642    #[test]
643    pub(super) fn test_backend_cdc_comment() {
644        let b = ChiselBackend::new();
645        let s = b.cdc_handshake_comment("clk_a", "clk_b");
646        assert!(s.contains("CDC"));
647        assert!(s.contains("clk_a"));
648    }
649    #[test]
650    pub(super) fn test_backend_blackbox_stub_no_params() {
651        let b = ChiselBackend::new();
652        let s = b.blackbox_stub("MyIp", &[]);
653        assert!(s.contains("BlackBox"));
654        assert!(s.contains("class MyIp"));
655    }
656    #[test]
657    pub(super) fn test_backend_blackbox_stub_with_params() {
658        let b = ChiselBackend::new();
659        let s = b.blackbox_stub("ParamIp", &[("WIDTH", "32"), ("DEPTH", "16")]);
660        assert!(s.contains("Map("));
661        assert!(s.contains("WIDTH"));
662        assert!(s.contains("32"));
663    }
664    #[test]
665    pub(super) fn test_backend_fill() {
666        let b = ChiselBackend::new();
667        let s = b.fill(8, "io.bit");
668        assert!(s.contains("Fill(8, io.bit)"));
669    }
670    #[test]
671    pub(super) fn test_backend_reverse() {
672        let b = ChiselBackend::new();
673        let s = b.reverse("io.data");
674        assert!(s.contains("Reverse(io.data)"));
675    }
676    #[test]
677    pub(super) fn test_backend_uint_to_oh() {
678        let b = ChiselBackend::new();
679        let s = b.uint_to_oh("io.sel", 8);
680        assert!(s.contains("UIntToOH"));
681        assert!(s.contains("io.sel"));
682    }
683    #[test]
684    pub(super) fn test_pipeline_stage_no_valid() {
685        let s = PipelineStage::new("s", ChiselType::UInt(8));
686        assert!(!s.has_valid);
687        assert!(!s.has_stall);
688    }
689    #[test]
690    pub(super) fn test_streaming_direction_producer() {
691        let m = ChiselStreamingModule::producer("P", 8);
692        assert_eq!(m.direction, StreamDirection::Producer);
693    }
694    #[test]
695    pub(super) fn test_streaming_direction_consumer() {
696        let m = ChiselStreamingModule::consumer("C", 8);
697        assert_eq!(m.direction, StreamDirection::Consumer);
698    }
699    #[test]
700    pub(super) fn test_sram_mask_granularity_byte() {
701        let sram = ChiselSRAMWrapper::single_port("M", 64, 64).with_mask(8);
702        assert_eq!(sram.mask_width(), 8);
703    }
704    #[test]
705    pub(super) fn test_interface_template_sram_slave() {
706        let t = ChiselInterfaceTemplate::SramPort {
707            addr_bits: 12,
708            data_bits: 16,
709        };
710        let s = t.emit_ports("mem", false);
711        assert!(s.contains("mem_addr"));
712        assert!(s.contains("12.W"));
713    }
714}
715#[cfg(test)]
716mod Chisel_infra_tests {
717    use super::*;
718    #[test]
719    pub(super) fn test_pass_config() {
720        let config = ChiselPassConfig::new("test_pass", ChiselPassPhase::Transformation);
721        assert!(config.enabled);
722        assert!(config.phase.is_modifying());
723        assert_eq!(config.phase.name(), "transformation");
724    }
725    #[test]
726    pub(super) fn test_pass_stats() {
727        let mut stats = ChiselPassStats::new();
728        stats.record_run(10, 100, 3);
729        stats.record_run(20, 200, 5);
730        assert_eq!(stats.total_runs, 2);
731        assert!((stats.average_changes_per_run() - 15.0).abs() < 0.01);
732        assert!((stats.success_rate() - 1.0).abs() < 0.01);
733        let s = stats.format_summary();
734        assert!(s.contains("Runs: 2/2"));
735    }
736    #[test]
737    pub(super) fn test_pass_registry() {
738        let mut reg = ChiselPassRegistry::new();
739        reg.register(ChiselPassConfig::new("pass_a", ChiselPassPhase::Analysis));
740        reg.register(ChiselPassConfig::new("pass_b", ChiselPassPhase::Transformation).disabled());
741        assert_eq!(reg.total_passes(), 2);
742        assert_eq!(reg.enabled_count(), 1);
743        reg.update_stats("pass_a", 5, 50, 2);
744        let stats = reg.get_stats("pass_a").expect("stats should exist");
745        assert_eq!(stats.total_changes, 5);
746    }
747    #[test]
748    pub(super) fn test_analysis_cache() {
749        let mut cache = ChiselAnalysisCache::new(10);
750        cache.insert("key1".to_string(), vec![1, 2, 3]);
751        assert!(cache.get("key1").is_some());
752        assert!(cache.get("key2").is_none());
753        assert!((cache.hit_rate() - 0.5).abs() < 0.01);
754        cache.invalidate("key1");
755        assert!(!cache.entries["key1"].valid);
756        assert_eq!(cache.size(), 1);
757    }
758    #[test]
759    pub(super) fn test_worklist() {
760        let mut wl = ChiselWorklist::new();
761        assert!(wl.push(1));
762        assert!(wl.push(2));
763        assert!(!wl.push(1));
764        assert_eq!(wl.len(), 2);
765        assert_eq!(wl.pop(), Some(1));
766        assert!(!wl.contains(1));
767        assert!(wl.contains(2));
768    }
769    #[test]
770    pub(super) fn test_dominator_tree() {
771        let mut dt = ChiselDominatorTree::new(5);
772        dt.set_idom(1, 0);
773        dt.set_idom(2, 0);
774        dt.set_idom(3, 1);
775        assert!(dt.dominates(0, 3));
776        assert!(dt.dominates(1, 3));
777        assert!(!dt.dominates(2, 3));
778        assert!(dt.dominates(3, 3));
779    }
780    #[test]
781    pub(super) fn test_liveness() {
782        let mut liveness = ChiselLivenessInfo::new(3);
783        liveness.add_def(0, 1);
784        liveness.add_use(1, 1);
785        assert!(liveness.defs[0].contains(&1));
786        assert!(liveness.uses[1].contains(&1));
787    }
788    #[test]
789    pub(super) fn test_constant_folding() {
790        assert_eq!(ChiselConstantFoldingHelper::fold_add_i64(3, 4), Some(7));
791        assert_eq!(ChiselConstantFoldingHelper::fold_div_i64(10, 0), None);
792        assert_eq!(ChiselConstantFoldingHelper::fold_div_i64(10, 2), Some(5));
793        assert_eq!(
794            ChiselConstantFoldingHelper::fold_bitand_i64(0b1100, 0b1010),
795            0b1000
796        );
797        assert_eq!(ChiselConstantFoldingHelper::fold_bitnot_i64(0), -1);
798    }
799    #[test]
800    pub(super) fn test_dep_graph() {
801        let mut g = ChiselDepGraph::new();
802        g.add_dep(1, 2);
803        g.add_dep(2, 3);
804        g.add_dep(1, 3);
805        assert_eq!(g.dependencies_of(2), vec![1]);
806        let topo = g.topological_sort();
807        assert_eq!(topo.len(), 3);
808        assert!(!g.has_cycle());
809        let pos: std::collections::HashMap<u32, usize> =
810            topo.iter().enumerate().map(|(i, &n)| (n, i)).collect();
811        assert!(pos[&1] < pos[&2]);
812        assert!(pos[&1] < pos[&3]);
813        assert!(pos[&2] < pos[&3]);
814    }
815}