prjunnamed_netlist/cell/
flip_flop.rs1use 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 reset: ControlNet,
27 pub enable: ControlNet,
29 pub reset_over_enable: bool,
31
32 pub clear_value: Const,
34 pub reset_value: Const,
36 pub init_value: Const,
38}
39
40impl FlipFlop {
41 pub fn new(data: Value, clock: impl Into<ControlNet>) -> Self {
42 let size = data.len();
43 FlipFlop {
44 data,
45 clock: clock.into(),
46 clear: ControlNet::ZERO,
47 reset: ControlNet::ZERO,
48 enable: ControlNet::ONE,
49 reset_over_enable: false,
50 clear_value: Const::undef(size),
51 reset_value: Const::undef(size),
52 init_value: Const::undef(size),
53 }
54 }
55
56 pub fn with_data(self, data: impl Into<Value>) -> Self {
57 Self { data: data.into(), ..self }
58 }
59
60 pub fn with_clock(self, clock: impl Into<ControlNet>) -> Self {
61 Self { clock: clock.into(), ..self }
62 }
63
64 pub fn with_clear(self, clear: impl Into<ControlNet>) -> Self {
65 Self { clear: clear.into(), ..self }
66 }
67
68 pub fn with_clear_value(self, clear: impl Into<ControlNet>, clear_value: impl Into<Const>) -> Self {
69 Self { clear: clear.into(), clear_value: clear_value.into(), ..self }
70 }
71
72 pub fn with_reset(self, reset: impl Into<ControlNet>) -> Self {
73 Self { reset: reset.into(), reset_over_enable: false, ..self }
74 }
75
76 pub fn with_reset_value(self, reset: impl Into<ControlNet>, reset_value: impl Into<Const>) -> Self {
77 Self { reset: reset.into(), reset_over_enable: false, reset_value: reset_value.into(), ..self }
78 }
79
80 pub fn with_enable(self, enable: impl Into<ControlNet>) -> Self {
81 Self { enable: enable.into(), reset_over_enable: true, ..self }
82 }
83
84 pub fn with_init(self, value: impl Into<Const>) -> Self {
85 let value = value.into();
86 Self { clear_value: value.clone(), reset_value: value.clone(), init_value: value, ..self }
87 }
88
89 pub fn output_len(&self) -> usize {
90 self.data.len()
91 }
92
93 pub fn has_clock(&self) -> bool {
94 !self.clock.is_const()
95 }
96
97 pub fn has_enable(&self) -> bool {
98 !self.enable.is_always(true)
99 }
100
101 pub fn has_reset(&self) -> bool {
102 !self.reset.is_always(false)
103 }
104
105 pub fn has_reset_value(&self) -> bool {
106 !self.reset_value.is_undef()
107 }
108
109 pub fn has_clear(&self) -> bool {
110 !self.clear.is_always(false)
111 }
112
113 pub fn has_clear_value(&self) -> bool {
114 !self.clear_value.is_undef()
115 }
116
117 pub fn has_init_value(&self) -> bool {
118 !self.init_value.is_undef()
119 }
120
121 pub fn slice(&self, range: impl std::ops::RangeBounds<usize> + Clone) -> FlipFlop {
122 FlipFlop {
123 data: self.data.slice(range.clone()),
124 clock: self.clock,
125 clear: self.clear,
126 reset: self.reset,
127 enable: self.enable,
128 reset_over_enable: self.reset_over_enable,
129 clear_value: self.clear_value.slice(range.clone()),
130 reset_value: self.reset_value.slice(range.clone()),
131 init_value: self.init_value.slice(range.clone()),
132 }
133 }
134
135 pub fn remap_reset_over_enable(&mut self, design: &Design) {
136 if self.reset_over_enable {
137 return;
138 }
139 self.reset_over_enable = true;
140 if self.reset.is_always(false) || self.enable.is_always(true) {
141 return;
142 }
143 let reset = self.reset.into_pos(design);
144 let enable = self.enable.into_pos(design);
145 self.reset = ControlNet::Pos(design.add_and(reset, enable).unwrap_net());
146 }
147
148 pub fn remap_enable_over_reset(&mut self, design: &Design) {
149 if !self.reset_over_enable {
150 return;
151 }
152 self.reset_over_enable = false;
153 if self.reset.is_always(false) || self.enable.is_always(true) {
154 return;
155 }
156 let reset = self.reset.into_pos(design);
157 let enable = self.enable.into_pos(design);
158 self.enable = ControlNet::Pos(design.add_or(reset, enable).unwrap_net());
159 }
160
161 pub fn unmap_reset(&mut self, design: &Design) {
162 self.remap_enable_over_reset(design);
163 self.data = design.add_mux(self.reset, &self.reset_value, &self.data);
164 self.reset = ControlNet::ZERO;
165 }
166
167 pub fn unmap_enable(&mut self, design: &Design, output: &Value) {
168 self.remap_reset_over_enable(design);
169 self.data = design.add_mux(self.enable, &self.data, output);
170 self.enable = ControlNet::ONE;
171 }
172
173 pub fn invert(&mut self, design: &Design, output: &Value) -> Value {
174 self.data = design.add_not(&self.data);
175 self.clear_value = self.clear_value.not();
176 self.reset_value = self.reset_value.not();
177 self.init_value = self.init_value.not();
178 let new_output = design.add_void(self.data.len());
179 design.replace_value(output, design.add_not(&new_output));
180 new_output
181 }
182
183 pub fn visit(&self, mut f: impl FnMut(Net)) {
184 self.data.visit(&mut f);
185 self.clock.visit(&mut f);
186 self.enable.visit(&mut f);
187 self.reset.visit(&mut f);
188 self.clear.visit(&mut f);
189 }
190
191 pub fn visit_mut(&mut self, mut f: impl FnMut(&mut Net)) {
192 self.data.visit_mut(&mut f);
193 self.clock.visit_mut(&mut f);
194 self.enable.visit_mut(&mut f);
195 self.reset.visit_mut(&mut f);
196 self.clear.visit_mut(&mut f);
197 }
198}