1use crate::{Const, ControlNet, Design, Net, Value};
2
3#[derive(Debug, Clone, PartialEq, Eq, Hash)]
18pub struct FlipFlop {
19 pub data: Value,
20 pub clock: ControlNet,
23 pub clear: ControlNet,
25 pub load: ControlNet,
27 pub load_data: Value,
29 pub reset: ControlNet,
31 pub enable: ControlNet,
33 pub reset_over_enable: bool,
35
36 pub clear_value: Const,
38 pub reset_value: Const,
40 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}