rust_hdl_fpga_support/toolchains/
icestorm.rs

1use rust_hdl_core::prelude::*;
2
3#[derive(Default)]
4struct PCFGenerator {
5    path: NamedPath,
6    namespace: NamedPath,
7    pcf: Vec<String>,
8}
9
10impl Probe for PCFGenerator {
11    fn visit_start_scope(&mut self, name: &str, _node: &dyn Block) {
12        let _top_level = self.path.to_string();
13        self.path.push(name);
14        self.namespace.reset();
15    }
16    fn visit_start_namespace(&mut self, name: &str, _node: &dyn Block) {
17        self.namespace.push(name);
18    }
19    fn visit_atom(&mut self, name: &str, signal: &dyn Atom) {
20        if self.path.len() == 1 {
21            let namespace = self.namespace.flat("$");
22            let name = if namespace.is_empty() {
23                name.to_owned()
24            } else {
25                format!("{}${}", namespace, name)
26            };
27            for pin in &signal.constraints() {
28                match &pin.constraint {
29                    Constraint::Location(l) => {
30                        if signal.bits() == 1 {
31                            self.pcf.push(format!("set_io {} {}", name, l))
32                        } else {
33                            self.pcf
34                                .push(format!("set_io {}[{}] {}", name, pin.index, l))
35                        }
36                    }
37                    Constraint::Custom(s) => self.pcf.push(s.clone()),
38                    _ => {
39                        panic!("Pin constraint type {:?} is unsupported!", pin.constraint)
40                    }
41                }
42            }
43        }
44    }
45    fn visit_end_namespace(&mut self, _name: &str, _node: &dyn Block) {
46        self.namespace.pop();
47    }
48    fn visit_end_scope(&mut self, _name: &str, _node: &dyn Block) {
49        self.path.pop();
50    }
51}
52
53pub fn generate_pcf<U: Block>(uut: &U) -> String {
54    let mut pcf = PCFGenerator::default();
55    uut.accept("top", &mut pcf);
56    pcf.pcf.join("\n") + "\n"
57}