prjunnamed_netlist/cell/
flip_flop.rs

1use crate::{Const, ControlNet, Design, Net, Value};
2
3/// A flip-flop cell.
4///
5/// The output is determined by the following rules:
6///
7/// - at the beginning of time, the output is set to `init_value`
8/// - whenever `clear` as active, the output is set to `clear_value`
9/// - whenever `clear` is not active, and an active edge happens on `clock`:
10///   - if `reset_over_enable` is true:
11///     - if `reset` is active, the output is set to `reset_value`
12///     - if `enable` is false, output value is unchanged
13///   - if `reset_over_enable` is false:
14///     - if `enable` is false, output value is unchanged
15///     - if `reset` is active, the output is set to `reset_value`
16///   - otherwise, the output is set to `data`
17#[derive(Debug, Clone, PartialEq, Eq, Hash)]
18pub struct FlipFlop {
19    pub data: Value,
20    /// The clock.  The active edge is rising if it is a [`ControlNet::Pos`], and falling if it is
21    /// a [`ControlNet::Neg`].
22    pub clock: ControlNet,
23    /// Asynchronous reset.
24    pub clear: ControlNet,
25    /// Asynchronous load (set output to the value of `load_data`).
26    pub load: ControlNet,
27    /// Asynchronous load data.
28    pub load_data: Value,
29    /// Synchronous reset.
30    pub reset: ControlNet,
31    /// Clock enable.
32    pub enable: ControlNet,
33    /// If true, `reset` has priority over `enable`.  Otherwise, `enable` has priority over `reset`.
34    pub reset_over_enable: bool,
35
36    /// Must have the same width as `data`.
37    pub clear_value: Const,
38    /// Must have the same width as `data`.
39    pub reset_value: Const,
40    /// Must have the same width as `data`.
41    pub init_value: Const,
42}
43
44impl FlipFlop {
45    pub fn new(data: Value, clock: impl Into<ControlNet>) -> Self {
46        let size = data.len();
47        FlipFlop {
48            data,
49            clock: clock.into(),
50            clear: ControlNet::ZERO,
51            reset: ControlNet::ZERO,
52            load: ControlNet::ZERO,
53            load_data: Value::undef(size),
54            enable: ControlNet::ONE,
55            reset_over_enable: false,
56            clear_value: Const::undef(size),
57            reset_value: Const::undef(size),
58            init_value: Const::undef(size),
59        }
60    }
61
62    pub fn with_data(self, data: impl Into<Value>) -> Self {
63        Self { data: data.into(), ..self }
64    }
65
66    pub fn with_clock(self, clock: impl Into<ControlNet>) -> Self {
67        Self { clock: clock.into(), ..self }
68    }
69
70    pub fn with_clear(self, clear: impl Into<ControlNet>) -> Self {
71        Self { clear: clear.into(), ..self }
72    }
73
74    pub fn with_clear_value(self, clear: impl Into<ControlNet>, clear_value: impl Into<Const>) -> Self {
75        Self { clear: clear.into(), clear_value: clear_value.into(), ..self }
76    }
77
78    pub fn with_load(self, load: impl Into<ControlNet>, load_data: impl Into<Value>) -> Self {
79        let load_data = load_data.into();
80        assert_eq!(load_data.len(), self.data.len());
81        Self { load: load.into(), load_data, ..self }
82    }
83
84    pub fn with_reset(self, reset: impl Into<ControlNet>) -> Self {
85        Self { reset: reset.into(), reset_over_enable: false, ..self }
86    }
87
88    pub fn with_reset_value(self, reset: impl Into<ControlNet>, reset_value: impl Into<Const>) -> Self {
89        Self { reset: reset.into(), reset_over_enable: false, reset_value: reset_value.into(), ..self }
90    }
91
92    pub fn with_enable(self, enable: impl Into<ControlNet>) -> Self {
93        Self { enable: enable.into(), reset_over_enable: true, ..self }
94    }
95
96    pub fn with_init(self, value: impl Into<Const>) -> Self {
97        let value = value.into();
98        Self { clear_value: value.clone(), reset_value: value.clone(), init_value: value, ..self }
99    }
100
101    pub fn output_len(&self) -> usize {
102        self.data.len()
103    }
104
105    pub fn has_clock(&self) -> bool {
106        !self.clock.is_const()
107    }
108
109    pub fn has_enable(&self) -> bool {
110        !self.enable.is_always(true)
111    }
112
113    pub fn has_reset(&self) -> bool {
114        !self.reset.is_always(false)
115    }
116
117    pub fn has_reset_value(&self) -> bool {
118        !self.reset_value.is_undef()
119    }
120
121    pub fn has_load(&self) -> bool {
122        !self.load.is_always(false)
123    }
124
125    pub fn has_clear(&self) -> bool {
126        !self.clear.is_always(false)
127    }
128
129    pub fn has_clear_value(&self) -> bool {
130        !self.clear_value.is_undef()
131    }
132
133    pub fn has_init_value(&self) -> bool {
134        !self.init_value.is_undef()
135    }
136
137    pub fn slice(&self, range: impl std::ops::RangeBounds<usize> + Clone) -> FlipFlop {
138        FlipFlop {
139            data: self.data.slice(range.clone()),
140            clock: self.clock,
141            clear: self.clear,
142            load: self.load,
143            load_data: self.load_data.slice(range.clone()),
144            reset: self.reset,
145            enable: self.enable,
146            reset_over_enable: self.reset_over_enable,
147            clear_value: self.clear_value.slice(range.clone()),
148            reset_value: self.reset_value.slice(range.clone()),
149            init_value: self.init_value.slice(range.clone()),
150        }
151    }
152
153    pub fn remap_reset_over_enable(&mut self, design: &Design) {
154        if self.reset_over_enable {
155            return;
156        }
157        self.reset_over_enable = true;
158        if self.reset.is_always(false) || self.enable.is_always(true) {
159            return;
160        }
161        let reset = self.reset.into_pos(design);
162        let enable = self.enable.into_pos(design);
163        self.reset = ControlNet::Pos(design.add_and(reset, enable).unwrap_net());
164    }
165
166    pub fn remap_enable_over_reset(&mut self, design: &Design) {
167        if !self.reset_over_enable {
168            return;
169        }
170        self.reset_over_enable = false;
171        if self.reset.is_always(false) || self.enable.is_always(true) {
172            return;
173        }
174        let reset = self.reset.into_pos(design);
175        let enable = self.enable.into_pos(design);
176        self.enable = ControlNet::Pos(design.add_or(reset, enable).unwrap_net());
177    }
178
179    pub fn unmap_reset(&mut self, design: &Design) {
180        self.remap_enable_over_reset(design);
181        self.data = design.add_mux(self.reset, &self.reset_value, &self.data);
182        self.reset = ControlNet::ZERO;
183    }
184
185    pub fn unmap_enable(&mut self, design: &Design, output: &Value) {
186        self.remap_reset_over_enable(design);
187        self.data = design.add_mux(self.enable, &self.data, output);
188        self.enable = ControlNet::ONE;
189    }
190
191    pub fn invert(&mut self, design: &Design, output: &Value) -> Value {
192        self.data = design.add_not(&self.data);
193        self.load_data = design.add_not(&self.load_data);
194        self.clear_value = self.clear_value.not();
195        self.reset_value = self.reset_value.not();
196        self.init_value = self.init_value.not();
197        let new_output = design.add_void(self.data.len());
198        design.replace_value(output, design.add_not(&new_output));
199        new_output
200    }
201
202    pub fn visit(&self, mut f: impl FnMut(Net)) {
203        self.data.visit(&mut f);
204        self.clock.visit(&mut f);
205        self.enable.visit(&mut f);
206        self.reset.visit(&mut f);
207        self.load.visit(&mut f);
208        self.load_data.visit(&mut f);
209        self.clear.visit(&mut f);
210    }
211
212    pub fn visit_mut(&mut self, mut f: impl FnMut(&mut Net)) {
213        self.data.visit_mut(&mut f);
214        self.clock.visit_mut(&mut f);
215        self.enable.visit_mut(&mut f);
216        self.reset.visit_mut(&mut f);
217        self.load.visit_mut(&mut f);
218        self.load_data.visit_mut(&mut f);
219        self.clear.visit_mut(&mut f);
220    }
221}