1use libreda_db::prelude as db;
8use num_traits::Zero;
9use smallvec::{smallvec, SmallVec};
10use std::{collections::HashMap, num::NonZeroU32, ops::Deref, sync::RwLock};
11
12use uom::si::f64::Time;
13
14use crate::{
15 traits::{
16 cell_constraint_model::{CellConstraintArc, CellConstraintModel},
17 cell_logic_model::{LogicModel, OutputFunction},
18 timing_base::SignalTransitionType,
19 CellDelayArc, CellDelayModel, CellModel, ConstraintBase, DelayBase, InterconnectDelayModel,
20 LoadBase, Signal, TimingBase,
21 },
22 RequiredSignal, RiseFall,
23};
24
25#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
31pub struct ClockId {
32 id: NonZeroU32,
45}
46
47#[test]
48fn test_clock_id_compact_encoding_of_option() {
49 use core::mem::size_of;
50 assert_eq!(size_of::<Option<ClockId>>(), size_of::<ClockId>());
51}
52
53impl std::fmt::Debug for ClockId {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 write!(f, "ClockId(index={}, flags=[", self.storage_index())?;
56
57 let flags = [
59 ("C", ClockId::BIT_INDEX_IS_CLOCK),
60 ("I", ClockId::BIT_INDEX_INVERTED),
61 ("R", ClockId::BIT_INDEX_RISING_EDGE),
62 ("F", ClockId::BIT_INDEX_FALLING_EDGE),
63 ];
64 for (symbol, bit_index) in flags {
65 if self.get_bit(bit_index) {
66 write!(f, "{}", symbol)?;
67 }
68 }
69
70 write!(f, "])")
71 }
72}
73
74impl ClockId {
75 const NUM_FLAGS: usize = 4;
77 const BIT_INDEX_IS_CLOCK: usize = 0;
78 const BIT_INDEX_INVERTED: usize = 1;
79 const BIT_INDEX_RISING_EDGE: usize = 2;
80 const BIT_INDEX_FALLING_EDGE: usize = 3;
81
82 pub fn new(storage_index: u32) -> Self {
88 let id = storage_index + 1;
90
91 let id = id << Self::NUM_FLAGS;
93
94 let mut id = Self {
95 id: NonZeroU32::new(id).unwrap(),
96 };
97
98 id.set_edge_sensitivity(RiseFall::Rise, true);
100 id.set_edge_sensitivity(RiseFall::Fall, true);
101
102 id
103 }
104
105 fn with_flags_from(&self, other: Self) -> Self {
107 let mask = (1 << Self::NUM_FLAGS) - 1;
108
109 let raw = self.id.get();
110 let cleared = raw & !mask;
112 let with_flags = cleared | (other.id.get() & mask);
114
115 Self {
116 id: NonZeroU32::new(with_flags).unwrap(),
117 }
118 }
119
120 pub fn storage_index(&self) -> usize {
123 ((self.id.get() >> Self::NUM_FLAGS) - 1) as usize
124 }
125
126 pub fn is_inverted(&self) -> bool {
128 self.get_bit(Self::BIT_INDEX_INVERTED)
129 }
130
131 pub fn is_clock(&self) -> bool {
135 self.get_bit(Self::BIT_INDEX_IS_CLOCK)
136 }
137
138 pub fn set_clock(&mut self, is_clock: bool) {
140 self.set_bit(Self::BIT_INDEX_IS_CLOCK, is_clock)
141 }
142
143 pub fn inverted(&self) -> Self {
145 let mut inverted = *self;
146 inverted.flip_bit(Self::BIT_INDEX_INVERTED);
147 inverted
148 }
149
150 pub fn is_sensitive_on_edge(&self, edge_type: RiseFall) -> bool {
153 let bit_idx = match edge_type {
154 RiseFall::Rise => Self::BIT_INDEX_RISING_EDGE,
155 RiseFall::Fall => Self::BIT_INDEX_FALLING_EDGE,
156 };
157
158 self.get_bit(bit_idx)
159 }
160
161 pub fn set_edge_sensitivity(&mut self, edge_type: RiseFall, can_change: bool) {
163 let bit_idx = match edge_type {
164 RiseFall::Rise => Self::BIT_INDEX_RISING_EDGE,
165 RiseFall::Fall => Self::BIT_INDEX_FALLING_EDGE,
166 };
167
168 self.set_bit(bit_idx, can_change);
169 }
170
171 fn set_bit(&mut self, bit_idx: usize, value: bool) {
173 debug_assert!(bit_idx < Self::NUM_FLAGS, "cannot modify the clock index");
174 let id = self.id.get();
175
176 let id = id & (!(1 << bit_idx));
178 let id = id | ((value as u32) << bit_idx);
180
181 self.id = NonZeroU32::new(id).unwrap();
183 }
184
185 fn flip_bit(&mut self, bit_idx: usize) {
189 debug_assert!(
190 bit_idx < Self::NUM_FLAGS,
191 "bit index out of range: cannot modify the clock index"
192 );
193 let id = self.id.get() ^ (1 << bit_idx);
194 self.id = NonZeroU32::new(id).unwrap()
195 }
196
197 fn get_bit(&self, bit_idx: usize) -> bool {
199 debug_assert!(
200 bit_idx < Self::NUM_FLAGS,
201 "bit index out of range: cannot modify the clock index"
202 );
203 self.id.get() & (1 << bit_idx) != 0
204 }
205}
206
207#[test]
208fn test_create_clock_id() {
209 let id = ClockId::new(7);
210 assert_eq!(id.storage_index(), 7);
211 assert!(!id.is_clock());
213 assert!(!id.is_inverted());
214 assert!(id.is_sensitive_on_edge(RiseFall::Rise));
215 assert!(id.is_sensitive_on_edge(RiseFall::Fall));
216}
217
218#[test]
219fn test_clock_id_set_flags() {
220 let mut id = ClockId::new(7);
221 id.set_clock(true);
222 assert!(id.is_clock());
223 assert!(id.inverted().is_inverted());
224 assert!(!id.inverted().inverted().is_inverted());
225}
226
227#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
229pub struct SignalWithClock<S> {
230 inner: S,
232 clock_id: Option<ClockId>,
234}
235
236impl<S> Deref for SignalWithClock<S> {
237 type Target = S;
238
239 fn deref(&self) -> &Self::Target {
240 &self.inner
241 }
242}
243
244impl<S> SignalWithClock<S> {
245 pub fn new(signal: S) -> Self {
247 Self {
248 inner: signal,
249 clock_id: Default::default(),
250 }
251 }
252
253 pub fn with_clock_id(mut self, clock_id: Option<ClockId>) -> Self {
255 self.set_clock_id(clock_id);
256 self
257 }
258
259 pub fn set_clock_id(&mut self, clock_id: Option<ClockId>) {
261 self.clock_id = clock_id;
262 }
263
264 pub fn clock_id(&self) -> Option<ClockId> {
266 self.clock_id
267 }
268
269 pub fn inner(&self) -> &S {
271 &self.inner
272 }
273
274 pub fn into_inner(self) -> S {
276 self.inner
277 }
278}
279
280impl<S> RequiredSignal for SignalWithClock<S> where S: RequiredSignal {}
281
282impl<S> Signal for SignalWithClock<S>
283where
284 S: Signal,
285{
286 type LogicValue = S::LogicValue;
287
288 fn logic_value(&self) -> Self::LogicValue {
289 self.inner.logic_value()
290 }
291
292 fn transition_type(&self) -> SignalTransitionType {
293 self.inner.transition_type()
294 }
295
296 fn with_transition_type(self, trans: SignalTransitionType) -> Self {
297 let clock_id = self.clock_id;
298 Self {
299 inner: self.inner.with_transition_type(trans),
300 clock_id,
301 }
302 }
303}
304
305#[derive(Debug)]
308pub struct ClockAwareModel<M> {
309 pub(crate) inner: M,
311 clocks: RwLock<Clocks>,
317}
318
319impl<M> Deref for ClockAwareModel<M> {
320 type Target = M;
321
322 fn deref(&self) -> &Self::Target {
323 &self.inner
324 }
325}
326
327impl<M> ClockAwareModel<M> {
328 pub fn new(inner_model: M) -> Self {
330 Self {
331 inner: inner_model,
332 clocks: Default::default(),
333 }
334 }
335
336 pub fn create_primary_clock(&mut self, period: Time, jitter: Time) -> ClockId {
338 let clock_definition = PrimaryClockDefinition { period, jitter };
339
340 self.clocks
341 .write()
342 .expect("failed to acquire read lock")
343 .create_defined_clock(clock_definition)
344 }
345
346 fn join_clocks(&self, clock1: Option<ClockId>, clock2: Option<ClockId>) -> Option<ClockId> {
352 match (clock1, clock2) {
356 (c1, c2) if c1 == c2 => c1,
358 (Some(c1), Some(c2)) => {
360 debug_assert_ne!(c1, c2);
361 let existing_id = {
365 let ids = smallvec::smallvec![c1, c2];
366 let clocks = self.clocks.read().expect("failed to acquire read-lock");
367 clocks.find_joined_clock_id(ids)
368 };
369
370 let joined_id = existing_id.unwrap_or_else(|| {
371 let ids = smallvec::smallvec![c1, c2];
373 let mut clocks = self.clocks.write().expect("failed to acquire write-lock");
374 clocks.create_joined_clock(ids)
375 });
376
377 Some(joined_id)
378 }
379 (None, Some(c)) | (Some(c), None) => Some(c),
381 (None, None) => None,
383 }
384 }
385
386 fn join_clocks_of_required_signals(
387 &self,
388 clock1: Option<ClockId>,
389 clock2: Option<ClockId>,
390 ) -> Option<ClockId> {
391 self.join_clocks(clock1, clock2)
392 }
393
394 fn clock_period(&self, clock_id: ClockId) -> Time {
396 let clocks_guard = self.clocks.read().unwrap();
397 let clock = clocks_guard.get_by_id(&clock_id);
398 match clock {
399 Clock::Primary(p) => p.period,
400 Clock::Joined(_) => {
401 Time::zero()
404 }
405 }
406 }
407}
408
409#[derive(Debug, Clone, Default)]
411struct Clocks {
412 clocks: Vec<Clock>,
415 joined_clocks: HashMap<SmallVec<[ClockId; 2]>, ClockId>,
418}
419
420impl Clocks {
421 fn create_defined_clock(&mut self, clock_definition: PrimaryClockDefinition) -> ClockId {
424 assert!(self.clocks.len() < u32::MAX as usize - 2);
425
426 let mut new_id = self.next_id();
427 new_id.set_clock(true);
428
429 self.clocks.push(Clock::Primary(clock_definition));
430 new_id
431 }
432
433 fn next_id(&self) -> ClockId {
435 ClockId::new(self.clocks.len() as u32)
436 }
437
438 fn get_by_id(&self, id: &ClockId) -> &Clock {
440 &self.clocks[id.storage_index()]
441 }
442
443 fn find_joined_clock_id(
445 &self,
446 mut source_clock_ids: SmallVec<[ClockId; 2]>,
447 ) -> Option<ClockId> {
448 source_clock_ids.sort();
450 source_clock_ids.dedup();
451
452 self.joined_clocks
453 .get(&source_clock_ids)
454 .copied()
455 .or_else(|| {
456 let resolved_ids = self.resolve_joined_clocks(source_clock_ids.iter().copied());
460 self.joined_clocks.get(&resolved_ids).copied()
461 })
462 }
463
464 fn resolve_joined_clocks(&self, ids: impl Iterator<Item = ClockId>) -> SmallVec<[ClockId; 2]> {
466 let mut primary_clock_ids: SmallVec<[_; 2]> = smallvec![];
467 for src_id in ids {
469 match self.get_by_id(&src_id) {
470 Clock::Primary(_) => primary_clock_ids.push(src_id),
472 Clock::Joined(clock_def) => {
474 for inner_id in &clock_def.source_clocks {
476 debug_assert!(
478 matches!(self.get_by_id(inner_id), Clock::Primary(_)),
479 "definition of joined clock should contain only primary clocks"
480 );
481 let primary_id = inner_id.with_flags_from(src_id);
483 primary_clock_ids.push(primary_id);
484 }
485 }
486 }
487 }
488
489 primary_clock_ids.sort();
491 primary_clock_ids.dedup();
492
493 primary_clock_ids
494 }
495
496 fn create_joined_clock(&mut self, mut source_clock_ids: SmallVec<[ClockId; 2]>) -> ClockId {
498 source_clock_ids.sort();
499 source_clock_ids.dedup();
500
501 let primary_clock_ids = self.resolve_joined_clocks(source_clock_ids.iter().copied());
502
503 debug_assert!(
505 !self.joined_clocks.contains_key(&source_clock_ids),
506 "joined clock already exists"
507 );
508
509 let clock_definition = JoinedClockDefinition {
510 source_clocks: primary_clock_ids.clone(),
511 };
512
513 let new_id = self.next_id();
514 self.clocks.push(Clock::Joined(clock_definition));
516
517 self.joined_clocks.insert(source_clock_ids, new_id);
519 self.joined_clocks.insert(primary_clock_ids, new_id);
520
521 new_id
522 }
523}
524
525#[derive(Debug, Clone)]
528struct PrimaryClockDefinition {
529 period: Time,
530 jitter: Time,
531}
532
533#[derive(Debug, Clone)]
535struct JoinedClockDefinition {
536 source_clocks: SmallVec<[ClockId; 2]>,
538}
539
540#[derive(Debug, Clone)]
541enum Clock {
542 Primary(PrimaryClockDefinition),
544 Joined(JoinedClockDefinition),
546}
547
548impl<M> LoadBase for ClockAwareModel<M>
549where
550 M: LoadBase,
551{
552 type Load = M::Load;
553
554 fn sum_loads(&self, load1: &Self::Load, load2: &Self::Load) -> Self::Load {
555 self.inner.sum_loads(load1, load2)
556 }
557}
558
559impl<M> TimingBase for ClockAwareModel<M>
560where
561 M: TimingBase,
562{
563 type Signal = SignalWithClock<M::Signal>;
564
565 type LogicValue = M::LogicValue;
566}
567
568impl<M> DelayBase for ClockAwareModel<M>
569where
570 M: DelayBase,
571{
572 type Delay = M::Delay;
573
574 fn summarize_delays(&self, signal1: &Self::Signal, signal2: &Self::Signal) -> Self::Signal {
575 let s = self.inner.summarize_delays(&signal1.inner, &signal2.inner);
576
577 let clock_id = self.join_clocks(signal1.clock_id, signal2.clock_id);
578 SignalWithClock { inner: s, clock_id }
579 }
580
581 fn get_delay(&self, from: &Self::Signal, to: &Self::Signal) -> Self::Delay {
582 self.inner.get_delay(&from.inner, &to.inner)
583 }
584}
585
586impl<M> ConstraintBase for ClockAwareModel<M>
587where
588 M: ConstraintBase,
589{
590 type Constraint = M::Constraint;
591
592 type RequiredSignal = SignalWithClock<M::RequiredSignal>;
593
594 type Slack = M::Slack;
595
596 fn summarize_constraints(
597 &self,
598 constraint1: &Self::RequiredSignal,
599 constraint2: &Self::RequiredSignal,
600 ) -> Self::RequiredSignal {
601 let constraint_without_clock = self
602 .inner
603 .summarize_constraints(constraint1.inner(), constraint2.inner());
604
605 let clock_id =
607 self.join_clocks_of_required_signals(constraint1.clock_id(), constraint2.clock_id());
608
609 SignalWithClock {
610 inner: constraint_without_clock,
611 clock_id,
612 }
613 }
614
615 fn solve_delay_constraint(
616 &self,
617 actual_delay: &Self::Delay,
618 required_output: &Self::RequiredSignal,
619 actual_signal: &Self::Signal,
620 ) -> Self::RequiredSignal {
621 let without_clock = self.inner.solve_delay_constraint(
622 actual_delay,
623 required_output.inner(),
624 actual_signal.inner(),
625 );
626
627 SignalWithClock {
628 inner: without_clock,
629 clock_id: required_output.clock_id(),
630 }
631 }
632
633 fn get_slack(
634 &self,
635 actual_signal: &Self::Signal,
636 required_signal: &Self::RequiredSignal,
637 ) -> Self::Slack {
638 self.inner
639 .get_slack(actual_signal.inner(), required_signal.inner())
640 }
641
642 fn add_clock_period(
643 &self,
644 required: Self::RequiredSignal,
645 clock_period: Time,
646 ) -> Self::RequiredSignal {
647 SignalWithClock {
648 inner: self.inner.add_clock_period(required.inner, clock_period),
649 ..required
650 }
651 }
652}
653
654impl<M, N> CellModel<N> for ClockAwareModel<M>
655where
656 N: db::NetlistBase,
657 M: CellModel<N>,
658{
659 fn ordered_pins(
660 &self,
661 cell: &<N>::CellId,
662 ) -> Vec<<N as libreda_db::traits::NetlistIds>::PinId> {
663 self.inner.ordered_pins(cell)
664 }
665}
666
667impl<M, N> CellDelayModel<N> for ClockAwareModel<M>
668where
669 N: db::NetlistBase,
670 M: CellDelayModel<N> + LogicModel<N>,
671 M::LogicValue: libreda_logic::traits::LogicOps + TryInto<bool>,
672{
673 fn cell_output(
674 &self,
675 netlist: &N,
676 arc: &CellDelayArc<N::PinId>,
677 input_signal: &Self::Signal,
678 output_load: &Self::Load,
679 other_inputs: &impl Fn(&N::PinId) -> Option<Self::LogicValue>,
680 ) -> Option<Self::Signal> {
681 let output_signals_without_clock =
683 self.inner
684 .cell_output(netlist, arc, &input_signal.inner, output_load, other_inputs);
685
686 let output_function = self.inner.pin_function(&arc.output_pin.0);
688
689 let is_combinational_arc = match output_function {
691 OutputFunction::Unknown => true, OutputFunction::Comb(_) => true,
693 OutputFunction::Sequential(_) => false,
694 };
695
696 let clock_id = input_signal.clock_id.and_then(|input_clock_id| {
697 if input_clock_id.is_clock() {
698 let mut output_clock_id = input_clock_id;
703
704 output_clock_id.set_edge_sensitivity(arc.input_pin.1, true);
706
707 output_clock_id.set_clock(is_combinational_arc);
711
712 if is_combinational_arc {
714 let unateness = self.inner.timing_sense(
715 &arc.output_pin.0,
716 &arc.input_pin.0,
717 &|pin| {
719 other_inputs(pin).and_then(|l| l.try_into().ok())
721 },
722 );
723
724 use crate::cell_logic_model::Unateness;
726 match unateness {
727 Unateness::None => {
728 todo!("ClockId needs to know concept of 'unknown polarity'");
729 }
730 Unateness::Negative => Some(output_clock_id.inverted()),
731 Unateness::Positive => {
732 Some(output_clock_id)
734 }
735 }
736 } else {
737 debug_assert!(
740 !output_clock_id.is_clock(),
741 "clock-flag should be cleared already"
742 );
743 Some(output_clock_id)
744 }
745 } else {
746 Some(input_clock_id)
749 }
750 });
751
752 output_signals_without_clock.map(|s| SignalWithClock { inner: s, clock_id })
754 }
755
756 fn delay_arcs(
757 &self,
758 netlist: &N,
759 cell_id: &N::CellId,
760 ) -> impl Iterator<Item = CellDelayArc<N::PinId>> + '_ {
761 self.inner.delay_arcs(netlist, cell_id)
762 }
763}
764
765impl<M, N> CellConstraintModel<N> for ClockAwareModel<M>
766where
767 N: db::NetlistBase,
768 M: CellConstraintModel<N>,
769{
770 fn get_required_input(
771 &self,
772 netlist: &N,
773 arc: &CellConstraintArc<N::PinId>,
774 constrained_pin_signal: &Self::Signal,
775 related_pin_signal: &Self::Signal,
776 other_inputs: &impl Fn(&<N>::PinId) -> Option<Self::Signal>,
777 output_loads: &impl Fn(&<N>::PinId) -> Option<Self::Load>,
778 ) -> Option<Self::RequiredSignal> {
779 let clock_id = related_pin_signal.clock_id().map(|mut clock_id| {
781 clock_id.set_clock(false);
785 clock_id.set_edge_sensitivity(RiseFall::Rise, false);
787 clock_id.set_edge_sensitivity(RiseFall::Fall, false);
788
789 use SignalTransitionType::*;
790 match related_pin_signal.transition_type() {
791 Rise => clock_id.set_edge_sensitivity(RiseFall::Rise, true),
792 Fall => clock_id.set_edge_sensitivity(RiseFall::Fall, true),
793 Any => {
794 panic!("propagated signals should have a defined edge polarity");
795 }
796 Constant(_) => {
797 }
799 };
800 clock_id
801 });
802
803 let clock_period: Option<_> = clock_id.map(|c| self.clock_period(c));
804
805 let required_signal_without_clock = self.inner.get_required_input(
807 netlist,
808 arc,
809 &constrained_pin_signal.inner,
810 &related_pin_signal.inner,
811 &|pin_id| other_inputs(pin_id).map(|signal| signal.inner),
812 output_loads,
813 );
814
815 let required_signal_without_clock = if let Some(t_clock) = clock_period {
817 required_signal_without_clock.map(|r| self.inner.add_clock_period(r, t_clock))
818 } else {
819 required_signal_without_clock
820 };
821
822 required_signal_without_clock.map(|signal| SignalWithClock {
824 inner: signal,
825 clock_id,
826 })
827 }
828
829 fn constraint_arcs(
830 &self,
831 netlist: &N,
832 cell_id: &<N>::CellId,
833 ) -> impl Iterator<Item = CellConstraintArc<N::PinId>> + '_ {
834 self.inner.constraint_arcs(netlist, cell_id)
835 }
836}
837
838#[derive(Debug, Clone)]
844pub struct ClockAwareInterconnectModel<M> {
845 inner: M,
847}
848
849impl<M> ClockAwareInterconnectModel<M> {
850 pub fn new(inner_model: M) -> Self {
853 Self { inner: inner_model }
854 }
855}
856
857impl<M> LoadBase for ClockAwareInterconnectModel<M>
859where
860 M: LoadBase,
861{
862 type Load = M::Load;
863
864 fn sum_loads(&self, load1: &Self::Load, load2: &Self::Load) -> Self::Load {
865 self.inner.sum_loads(load1, load2)
866 }
867}
868
869impl<M> TimingBase for ClockAwareInterconnectModel<M>
871where
872 M: TimingBase,
873{
874 type Signal = SignalWithClock<M::Signal>;
875
876 type LogicValue = M::LogicValue;
877}
878
879impl<M> DelayBase for ClockAwareInterconnectModel<M>
881where
882 M: DelayBase,
883{
884 type Delay = M::Delay;
885 fn summarize_delays(&self, signal1: &Self::Signal, signal2: &Self::Signal) -> Self::Signal {
886 assert_eq!(
887 signal1.clock_id, signal2.clock_id,
888 "signals must have same clock ID" );
890 let signal_without_clock = self.inner.summarize_delays(&signal1.inner, &signal2.inner);
891
892 Self::Signal {
893 inner: signal_without_clock,
894 clock_id: signal1.clock_id,
895 }
896 }
897
898 fn get_delay(&self, from: &Self::Signal, to: &Self::Signal) -> Self::Delay {
899 self.inner.get_delay(&from.inner, &to.inner)
900 }
901}
902
903impl<M, N> InterconnectDelayModel<N> for ClockAwareInterconnectModel<M>
904where
905 N: db::NetlistBase,
906 M: InterconnectDelayModel<N>,
907{
908 fn interconnect_output(
909 &self,
910 netlist: &N,
911 source_terminal: &db::TerminalId<N>,
912 input_signal: &Self::Signal,
913 target_terminal: &db::TerminalId<N>,
914 output_load: &Self::Load,
915 ) -> Option<Self::Signal> {
916 let output_without_clock = self.inner.interconnect_output(
918 netlist,
919 source_terminal,
920 &input_signal.inner,
921 target_terminal,
922 output_load,
923 );
924
925 output_without_clock.map(|s| SignalWithClock {
927 inner: s,
928 clock_id: input_signal.clock_id,
929 })
930 }
931}