1use calyx_utils::{CalyxResult, Error, Id};
2use std::str::FromStr;
3use strum::EnumCount;
4use strum_macros::{AsRefStr, EnumCount, EnumString, FromRepr};
5
6pub const DEPRECATED_ATTRIBUTES: &[&str] = &["static"];
8
9#[derive(
10 EnumCount,
11 FromRepr,
12 AsRefStr,
13 EnumString,
14 Clone,
15 Copy,
16 Hash,
17 PartialEq,
18 Eq,
19 Debug,
20)]
21#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
22#[repr(u8)]
23pub enum BoolAttr {
25 #[strum(serialize = "toplevel")]
26 TopLevel,
28 #[strum(serialize = "external")]
29 External,
31 #[strum(serialize = "nointerface")]
32 NoInterface,
34 #[strum(serialize = "reset")]
35 Reset,
37 #[strum(serialize = "clk")]
38 Clk,
40 #[strum(serialize = "stable")]
41 Stable,
43 #[strum(serialize = "data")]
44 Data,
46 #[strum(serialize = "control")]
47 Control,
49 #[strum(serialize = "share")]
50 Share,
52 #[strum(serialize = "state_share")]
53 StateShare,
55 #[strum(serialize = "generated")]
56 Generated,
58 #[strum(serialize = "new_fsm")]
59 NewFSM,
61 #[strum(serialize = "inline")]
62 Inline,
64 #[strum(serialize = "promoted")]
65 Promoted,
67}
68impl From<BoolAttr> for Attribute {
69 fn from(attr: BoolAttr) -> Self {
70 Attribute::Bool(attr)
71 }
72}
73impl std::fmt::Display for BoolAttr {
74 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 write!(f, "{}", self.as_ref())
76 }
77}
78
79#[derive(AsRefStr, EnumString, Clone, Copy, Hash, PartialEq, Eq, Debug)]
80#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
81pub enum NumAttr {
83 #[strum(serialize = "go")]
86 Go,
87 #[strum(serialize = "done")]
88 Done,
89 #[strum(serialize = "read_together")]
91 ReadTogether,
92 #[strum(serialize = "write_together")]
93 WriteTogether,
94 #[strum(serialize = "sync")]
95 Sync,
97 #[strum(serialize = "bound")]
98 Bound,
100 #[strum(serialize = "pos")]
101 Pos,
103 #[strum(serialize = "promotable")]
104 Promotable,
107 #[strum(serialize = "compactable")]
108 Compactable,
110 #[strum(serialize = "interval")]
111 Interval,
117}
118impl From<NumAttr> for Attribute {
119 fn from(attr: NumAttr) -> Self {
120 Attribute::Num(attr)
121 }
122}
123impl std::fmt::Display for NumAttr {
124 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125 write!(f, "{}", self.as_ref())
126 }
127}
128
129#[derive(AsRefStr, Clone, Copy, Hash, PartialEq, Eq, Debug)]
130#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
131#[allow(non_camel_case_types)]
132pub enum InternalAttr {
134 DEAD,
135 NODE_ID,
136 BEGIN_ID,
137 END_ID,
138 ST_ID,
139 LOOP,
140 START,
141 END,
142}
143impl From<InternalAttr> for Attribute {
144 fn from(attr: InternalAttr) -> Self {
145 Attribute::Internal(attr)
146 }
147}
148
149#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
150#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
151pub enum Attribute {
155 Bool(BoolAttr),
156 Num(NumAttr),
157 Internal(InternalAttr),
158 Unknown(Id),
161}
162impl std::fmt::Display for Attribute {
163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164 match self {
165 Attribute::Bool(b) => write!(f, "{}", b.as_ref()),
166 Attribute::Num(n) => write!(f, "{}", n.as_ref()),
167 Attribute::Internal(i) => write!(f, "{}", i.as_ref()),
168 Attribute::Unknown(s) => write!(f, "{}", s),
169 }
170 }
171}
172impl FromStr for Attribute {
173 type Err = Error;
174
175 fn from_str(s: &str) -> CalyxResult<Self> {
176 if let Ok(b) = BoolAttr::from_str(s) {
177 Ok(Attribute::Bool(b))
178 } else if let Ok(n) = NumAttr::from_str(s) {
179 Ok(Attribute::Num(n))
180 } else {
181 if DEPRECATED_ATTRIBUTES.contains(&s) {
182 log::warn!("The attribute @{s} is deprecated and will be ignored by the compiler.");
183 }
184 if s.to_uppercase() == s {
186 return Err(Error::misc(format!("Invalid attribute: {}. All caps attributes are reserved for internal use.", s)));
187 }
188 Ok(Attribute::Unknown(s.into()))
189 }
190 }
191}
192
193#[derive(Default, Debug, Clone)]
194pub(super) struct InlineAttributes {
196 attrs: u16,
198}
199
200impl InlineAttributes {
201 pub const fn is_empty(&self) -> bool {
203 self.attrs == 0
204 }
205
206 pub fn insert(&mut self, attr: BoolAttr) {
208 self.attrs |= 1 << attr as u8;
209 }
210
211 pub fn has(&self, attr: BoolAttr) -> bool {
213 self.attrs & (1 << (attr as u8)) != 0
214 }
215
216 pub fn remove(&mut self, attr: BoolAttr) {
218 self.attrs &= !(1 << attr as u8);
219 }
220
221 pub(super) fn iter(&self) -> impl Iterator<Item = BoolAttr> + '_ {
223 (0..(BoolAttr::COUNT as u8)).filter_map(|idx| {
224 if self.attrs & (1 << idx) != 0 {
225 Some(BoolAttr::from_repr(idx).unwrap())
226 } else {
227 None
228 }
229 })
230 }
231}
232
233#[cfg(feature = "serialize")]
234impl serde::Serialize for InlineAttributes {
235 fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
236 where
237 S: serde::Serializer,
238 {
239 self.to_owned().attrs.serialize(ser)
240 }
241}