1use bitvec::{bitvec, field::BitField, order::Lsb0, vec::BitVec};
8use std::collections::{HashMap, HashSet};
9
10use crate::{
11 circuit::Instantiable,
12 logic::Logic,
13 netlist::{NetRef, Netlist},
14};
15
16pub type AttributeKey = String;
18pub type AttributeValue = Option<String>;
20
21#[derive(Debug, Clone, PartialEq, Eq)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23pub struct Attribute {
25 k: AttributeKey,
26 v: AttributeValue,
27}
28
29impl Attribute {
30 pub fn new(k: AttributeKey, v: AttributeValue) -> Self {
32 Self { k, v }
33 }
34
35 pub fn key(&self) -> &AttributeKey {
37 &self.k
38 }
39
40 pub fn value(&self) -> &AttributeValue {
42 &self.v
43 }
44
45 pub fn from_pairs(
47 iter: impl Iterator<Item = (AttributeKey, AttributeValue)>,
48 ) -> impl Iterator<Item = Self> {
49 iter.map(|(k, v)| Self::new(k, v))
50 }
51}
52
53impl std::fmt::Display for Attribute {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 if let Some(value) = &self.v {
56 write!(f, "(* {} = {} *)", self.k, value)
57 } else {
58 write!(f, "(* {} *)", self.k)
59 }
60 }
61}
62
63#[derive(Debug, Clone, PartialEq)]
64#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
65pub enum Parameter {
67 Integer(u64),
69 Real(f32),
71 BitVec(BitVec),
73 Logic(Logic),
75}
76
77impl Eq for Parameter {}
78
79impl std::fmt::Display for Parameter {
80 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81 match self {
82 Parameter::Integer(i) => write!(f, "{i}"),
83 Parameter::Real(_r) => todo!(),
84 Parameter::BitVec(bv) => write!(
85 f,
86 "{}'b{}",
87 bv.len(),
88 bv.iter()
89 .rev()
90 .map(|b| if *b { '1' } else { '0' })
91 .collect::<String>()
92 ),
93 Parameter::Logic(l) => write!(f, "{l}"),
94 }
95 }
96}
97
98impl Parameter {
99 pub fn integer(i: u64) -> Self {
101 Self::Integer(i)
102 }
103
104 pub fn real(r: f32) -> Self {
106 Self::Real(r)
107 }
108
109 pub fn bitvec(size: usize, val: u64) -> Self {
111 if size > 64 {
112 panic!("BitVec parameter size cannot be larger than 64");
113 }
114 let mut bv: BitVec = bitvec!(usize, Lsb0; 0; 64);
115 bv[0..64].store::<u64>(val);
116 bv.truncate(size);
117 Self::BitVec(bv)
118 }
119
120 pub fn logic(l: Logic) -> Self {
122 Self::Logic(l)
123 }
124
125 pub fn from_bool(b: bool) -> Self {
127 Self::Logic(Logic::from_bool(b))
128 }
129}
130
131pub struct AttributeFilter<'a, I: Instantiable> {
133 _netlist: &'a Netlist<I>,
135 keys: Vec<AttributeKey>,
137 map: HashMap<AttributeKey, HashSet<NetRef<I>>>,
139 full_set: HashSet<NetRef<I>>,
141}
142
143impl<'a, I> AttributeFilter<'a, I>
144where
145 I: Instantiable,
146{
147 fn new(netlist: &'a Netlist<I>, keys: Vec<AttributeKey>) -> Self {
149 let mut map = HashMap::new();
150 let mut full_set = HashSet::new();
151 for nr in netlist.objects() {
152 for attr in nr.attributes() {
153 if keys.contains(attr.key()) {
154 map.entry(attr.key().clone())
155 .or_insert_with(HashSet::new)
156 .insert(nr.clone());
157 full_set.insert(nr.clone());
158 }
159 }
160 }
161 Self {
162 _netlist: netlist,
163 keys,
164 map,
165 full_set,
166 }
167 }
168
169 pub fn has(&self, n: &NetRef<I>) -> bool {
171 self.map.values().any(|s| s.contains(n))
172 }
173
174 pub fn keys(&self) -> &[AttributeKey] {
176 &self.keys
177 }
178}
179
180impl<'a, I> IntoIterator for AttributeFilter<'a, I>
181where
182 I: Instantiable,
183{
184 type Item = NetRef<I>;
185
186 type IntoIter = std::collections::hash_set::IntoIter<NetRef<I>>;
187
188 fn into_iter(self) -> Self::IntoIter {
189 self.full_set.into_iter()
190 }
191}
192
193pub fn dont_touch_filter<'a, I>(netlist: &'a Netlist<I>) -> AttributeFilter<'a, I>
195where
196 I: Instantiable,
197{
198 AttributeFilter::new(netlist, vec!["dont_touch".to_string()])
199}
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204
205 #[test]
206 fn attribute_iter() {
207 let attributes: [(AttributeKey, AttributeValue); 2] = [
208 ("dont_touch".to_string(), Some("true".to_string())),
209 ("synthesizable".to_string(), None),
210 ];
211 let real_attrs: Vec<Attribute> = Attribute::from_pairs(attributes.into_iter()).collect();
212 assert_eq!(real_attrs.len(), 2);
213 assert_eq!(
214 real_attrs.first().unwrap().to_string(),
215 "(* dont_touch = true *)"
216 );
217 assert_eq!(real_attrs.first().unwrap().key(), "dont_touch");
218 assert_eq!(
219 real_attrs.last().unwrap().to_string(),
220 "(* synthesizable *)"
221 );
222 assert!(real_attrs.last().unwrap().value().is_none());
223 }
224
225 #[test]
226 fn test_parameter_fmt() {
227 let p1 = Parameter::Integer(42);
228 let p2 = Parameter::BitVec(bitvec![0, 0, 0, 0, 0, 0, 0, 1]);
230 let p3 = Parameter::Logic(Logic::from_bool(true));
231 let p4 = Parameter::from_bool(true);
232 assert_eq!(p1.to_string(), "42");
233 assert_eq!(p2.to_string(), "8'b10000000");
234 assert_eq!(p3.to_string(), "1'b1");
235 assert_eq!(p4.to_string(), "1'b1");
236 }
237}