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) => {
85 if bv.len() >= 4 && bv.len() % 4 == 0 {
86 write!(f, "{}'h", bv.len())?;
87 for n in bv.chunks(4).rev() {
88 let val: u8 = n.load();
89 write!(f, "{:x}", val)?;
90 }
91 Ok(())
92 } else {
93 write!(
94 f,
95 "{}'b{}",
96 bv.len(),
97 bv.iter()
98 .rev()
99 .map(|b| if *b { '1' } else { '0' })
100 .collect::<String>()
101 )
102 }
103 }
104 Parameter::Logic(l) => write!(f, "{l}"),
105 }
106 }
107}
108
109impl Parameter {
110 pub fn integer(i: u64) -> Self {
112 Self::Integer(i)
113 }
114
115 pub fn real(r: f32) -> Self {
117 Self::Real(r)
118 }
119
120 pub fn bitvec(size: usize, val: u64) -> Self {
122 if size > 64 {
123 panic!("BitVec parameter size cannot be larger than 64");
124 }
125 let mut bv: BitVec = bitvec!(usize, Lsb0; 0; 64);
126 bv[0..64].store::<u64>(val);
127 bv.truncate(size);
128 Self::BitVec(bv)
129 }
130
131 pub fn logic(l: Logic) -> Self {
133 Self::Logic(l)
134 }
135
136 pub fn from_bool(b: bool) -> Self {
138 Self::Logic(Logic::from_bool(b))
139 }
140}
141
142pub struct AttributeFilter<'a, I: Instantiable> {
144 _netlist: &'a Netlist<I>,
146 keys: Vec<AttributeKey>,
148 map: HashMap<AttributeKey, HashSet<NetRef<I>>>,
150 full_set: HashSet<NetRef<I>>,
152}
153
154impl<'a, I> AttributeFilter<'a, I>
155where
156 I: Instantiable,
157{
158 fn new(netlist: &'a Netlist<I>, keys: Vec<AttributeKey>) -> Self {
160 let mut map = HashMap::new();
161 let mut full_set = HashSet::new();
162 for nr in netlist.objects() {
163 for attr in nr.attributes() {
164 if keys.contains(attr.key()) {
165 map.entry(attr.key().clone())
166 .or_insert_with(HashSet::new)
167 .insert(nr.clone());
168 full_set.insert(nr.clone());
169 }
170 }
171 }
172 Self {
173 _netlist: netlist,
174 keys,
175 map,
176 full_set,
177 }
178 }
179
180 pub fn has(&self, n: &NetRef<I>) -> bool {
182 self.map.values().any(|s| s.contains(n))
183 }
184
185 pub fn keys(&self) -> &[AttributeKey] {
187 &self.keys
188 }
189}
190
191impl<'a, I> IntoIterator for AttributeFilter<'a, I>
192where
193 I: Instantiable,
194{
195 type Item = NetRef<I>;
196
197 type IntoIter = std::collections::hash_set::IntoIter<NetRef<I>>;
198
199 fn into_iter(self) -> Self::IntoIter {
200 self.full_set.into_iter()
201 }
202}
203
204pub fn dont_touch_filter<'a, I>(netlist: &'a Netlist<I>) -> AttributeFilter<'a, I>
206where
207 I: Instantiable,
208{
209 AttributeFilter::new(netlist, vec!["dont_touch".to_string()])
210}
211
212#[cfg(test)]
213mod tests {
214 use super::*;
215
216 #[test]
217 fn attribute_iter() {
218 let attributes: [(AttributeKey, AttributeValue); 2] = [
219 ("dont_touch".to_string(), Some("true".to_string())),
220 ("synthesizable".to_string(), None),
221 ];
222 let real_attrs: Vec<Attribute> = Attribute::from_pairs(attributes.into_iter()).collect();
223 assert_eq!(real_attrs.len(), 2);
224 assert_eq!(
225 real_attrs.first().unwrap().to_string(),
226 "(* dont_touch = true *)"
227 );
228 assert_eq!(real_attrs.first().unwrap().key(), "dont_touch");
229 assert_eq!(
230 real_attrs.last().unwrap().to_string(),
231 "(* synthesizable *)"
232 );
233 assert!(real_attrs.last().unwrap().value().is_none());
234 }
235
236 #[test]
237 fn test_parameter_fmt() {
238 let p1 = Parameter::Integer(42);
239 let p2 = Parameter::BitVec(bitvec![0, 0, 0, 0, 0, 0, 0, 1]);
241 let p3 = Parameter::Logic(Logic::from_bool(true));
242 let p4 = Parameter::from_bool(true);
243 assert_eq!(p1.to_string(), "42");
244 assert_eq!(p2.to_string(), "8'h80");
245 assert_eq!(p3.to_string(), "1'b1");
246 assert_eq!(p4.to_string(), "1'b1");
247 }
248
249 #[test]
250 fn test_parameter_hex() {
251 let p = Parameter::BitVec(bitvec![1, 1, 1, 0, 1, 0, 0, 0]);
252 assert_eq!(p.to_string(), "8'h17");
253 let p = Parameter::BitVec(bitvec![1, 1, 1, 1, 1, 0, 0, 0]);
254 assert_eq!(p.to_string(), "8'h1f");
255 }
256}