rust_hdl_fpga_support/toolchains/
icestorm.rs1use 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}