forked from libre-chip/fayalite
		
	sim: add .dot output for Assignments graph for debugging
This commit is contained in:
		
							parent
							
								
									564ccb30bc
								
							
						
					
					
						commit
						6b31e6d515
					
				
					 2 changed files with 342 additions and 43 deletions
				
			
		| 
						 | 
				
			
			@ -42,8 +42,12 @@ use bitvec::{bits, order::Lsb0, slice::BitSlice, vec::BitVec, view::BitView};
 | 
			
		|||
use hashbrown::{HashMap, HashSet};
 | 
			
		||||
use num_bigint::BigInt;
 | 
			
		||||
use num_traits::{Signed, ToPrimitive, Zero};
 | 
			
		||||
use petgraph::visit::{
 | 
			
		||||
    GraphBase, IntoNeighbors, IntoNeighborsDirected, IntoNodeIdentifiers, VisitMap, Visitable,
 | 
			
		||||
use petgraph::{
 | 
			
		||||
    data::FromElements,
 | 
			
		||||
    visit::{
 | 
			
		||||
        EdgeRef, GraphBase, IntoEdgeReferences, IntoNeighbors, IntoNeighborsDirected,
 | 
			
		||||
        IntoNodeIdentifiers, IntoNodeReferences, NodeRef, VisitMap, Visitable,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
use std::{borrow::Cow, collections::BTreeSet, fmt, marker::PhantomData, mem, ops::IndexMut};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -384,8 +388,8 @@ impl CompiledExpr<Array> {
 | 
			
		|||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 | 
			
		||||
enum AssignmentOrSlotIndex {
 | 
			
		||||
    AssignmentIndex(usize),
 | 
			
		||||
    SmallSlots(StatePartIndex<StatePartKindSmallSlots>),
 | 
			
		||||
    BigSlots(StatePartIndex<StatePartKindBigSlots>),
 | 
			
		||||
    SmallSlot(StatePartIndex<StatePartKindSmallSlots>),
 | 
			
		||||
    BigSlot(StatePartIndex<StatePartKindBigSlots>),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 | 
			
		||||
| 
						 | 
				
			
			@ -408,6 +412,15 @@ enum AssignmentIO {
 | 
			
		|||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 | 
			
		||||
enum AssignmentsEdge {
 | 
			
		||||
    IO(AssignmentIO),
 | 
			
		||||
    AssignmentImmediatePredecessor {
 | 
			
		||||
        predecessor_assignment_index: usize,
 | 
			
		||||
        assignment_index: usize,
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
enum Assignments {
 | 
			
		||||
    Accumulating {
 | 
			
		||||
| 
						 | 
				
			
			@ -415,6 +428,7 @@ enum Assignments {
 | 
			
		|||
    },
 | 
			
		||||
    Finalized {
 | 
			
		||||
        assignments: Box<[Assignment]>,
 | 
			
		||||
        slots_layout: TypeLayout<InsnsBuildingDone>,
 | 
			
		||||
        slot_readers: SlotToAssignmentIndexFullMap,
 | 
			
		||||
        slot_writers: SlotToAssignmentIndexFullMap,
 | 
			
		||||
        assignment_immediate_predecessors: Box<[Box<[usize]>]>,
 | 
			
		||||
| 
						 | 
				
			
			@ -431,13 +445,13 @@ impl Default for Assignments {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
impl Assignments {
 | 
			
		||||
    fn finalize(&mut self, slots_len: TypeLen) {
 | 
			
		||||
    fn finalize(&mut self, slots_layout: TypeLayout<InsnsBuildingDone>) {
 | 
			
		||||
        let Self::Accumulating { assignments } = self else {
 | 
			
		||||
            unreachable!("already finalized");
 | 
			
		||||
        };
 | 
			
		||||
        let assignments = mem::take(assignments).into_boxed_slice();
 | 
			
		||||
        let mut slot_readers = SlotToAssignmentIndexFullMap::new(slots_len);
 | 
			
		||||
        let mut slot_writers = SlotToAssignmentIndexFullMap::new(slots_len);
 | 
			
		||||
        let mut slot_readers = SlotToAssignmentIndexFullMap::new(slots_layout.len());
 | 
			
		||||
        let mut slot_writers = SlotToAssignmentIndexFullMap::new(slots_layout.len());
 | 
			
		||||
        let mut assignment_immediate_predecessors = vec![BTreeSet::new(); assignments.len()];
 | 
			
		||||
        let mut assignment_immediate_successors = vec![BTreeSet::new(); assignments.len()];
 | 
			
		||||
        for (assignment_index, assignment) in assignments.iter().enumerate() {
 | 
			
		||||
| 
						 | 
				
			
			@ -465,6 +479,7 @@ impl Assignments {
 | 
			
		|||
        }
 | 
			
		||||
        *self = Self::Finalized {
 | 
			
		||||
            assignments,
 | 
			
		||||
            slots_layout,
 | 
			
		||||
            slot_readers,
 | 
			
		||||
            slot_writers,
 | 
			
		||||
            assignment_immediate_predecessors: assignment_immediate_predecessors
 | 
			
		||||
| 
						 | 
				
			
			@ -489,6 +504,12 @@ impl Assignments {
 | 
			
		|||
        };
 | 
			
		||||
        assignments
 | 
			
		||||
    }
 | 
			
		||||
    fn slots_layout(&self) -> TypeLayout<InsnsBuildingDone> {
 | 
			
		||||
        let Self::Finalized { slots_layout, .. } = self else {
 | 
			
		||||
            unreachable!("Assignments::finalize should have been called");
 | 
			
		||||
        };
 | 
			
		||||
        *slots_layout
 | 
			
		||||
    }
 | 
			
		||||
    fn slot_readers(&self) -> &SlotToAssignmentIndexFullMap {
 | 
			
		||||
        let Self::Finalized { slot_readers, .. } = self else {
 | 
			
		||||
            unreachable!("Assignments::finalize should have been called");
 | 
			
		||||
| 
						 | 
				
			
			@ -521,46 +542,131 @@ impl Assignments {
 | 
			
		|||
        };
 | 
			
		||||
        assignment_immediate_successors
 | 
			
		||||
    }
 | 
			
		||||
    fn elements(&self) -> AssignmentsElements<'_> {
 | 
			
		||||
        let SlotToAssignmentIndexFullMap(TypeParts {
 | 
			
		||||
            small_slots,
 | 
			
		||||
            big_slots,
 | 
			
		||||
        }) = self.slot_readers();
 | 
			
		||||
        AssignmentsElements {
 | 
			
		||||
            node_indexes: HashMap::with_capacity(
 | 
			
		||||
                self.assignments().len() + small_slots.len() + big_slots.len(),
 | 
			
		||||
            ),
 | 
			
		||||
            nodes: self.node_references(),
 | 
			
		||||
            edges: self.edge_references(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl GraphBase for Assignments {
 | 
			
		||||
    type EdgeId = AssignmentIO;
 | 
			
		||||
    type EdgeId = AssignmentsEdge;
 | 
			
		||||
    type NodeId = AssignmentOrSlotIndex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, Copy)]
 | 
			
		||||
enum AssignmentsNodeRef<'a> {
 | 
			
		||||
    Assignment {
 | 
			
		||||
        index: usize,
 | 
			
		||||
        assignment: &'a Assignment,
 | 
			
		||||
    },
 | 
			
		||||
    SmallSlot(StatePartIndex<StatePartKindSmallSlots>, SlotDebugData),
 | 
			
		||||
    BigSlot(StatePartIndex<StatePartKindBigSlots>, SlotDebugData),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> NodeRef for AssignmentsNodeRef<'a> {
 | 
			
		||||
    type NodeId = AssignmentOrSlotIndex;
 | 
			
		||||
    type Weight = AssignmentsNodeRef<'a>;
 | 
			
		||||
 | 
			
		||||
    fn id(&self) -> Self::NodeId {
 | 
			
		||||
        match *self {
 | 
			
		||||
            AssignmentsNodeRef::Assignment {
 | 
			
		||||
                index,
 | 
			
		||||
                assignment: _,
 | 
			
		||||
            } => AssignmentOrSlotIndex::AssignmentIndex(index),
 | 
			
		||||
            AssignmentsNodeRef::SmallSlot(slot, _) => AssignmentOrSlotIndex::SmallSlot(slot),
 | 
			
		||||
            AssignmentsNodeRef::BigSlot(slot, _) => AssignmentOrSlotIndex::BigSlot(slot),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn weight(&self) -> &Self::Weight {
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> petgraph::visit::Data for &'a Assignments {
 | 
			
		||||
    type NodeWeight = AssignmentsNodeRef<'a>;
 | 
			
		||||
    type EdgeWeight = AssignmentsEdge;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct AssignmentsElements<'a> {
 | 
			
		||||
    node_indexes: HashMap<AssignmentOrSlotIndex, usize>,
 | 
			
		||||
    nodes: AssignmentsNodes<'a>,
 | 
			
		||||
    edges: AssignmentsEdges<'a>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> Iterator for AssignmentsElements<'a> {
 | 
			
		||||
    type Item = petgraph::data::Element<
 | 
			
		||||
        <&'a Assignments as petgraph::visit::Data>::NodeWeight,
 | 
			
		||||
        <&'a Assignments as petgraph::visit::Data>::EdgeWeight,
 | 
			
		||||
    >;
 | 
			
		||||
 | 
			
		||||
    fn next(&mut self) -> Option<Self::Item> {
 | 
			
		||||
        let Self {
 | 
			
		||||
            node_indexes,
 | 
			
		||||
            nodes,
 | 
			
		||||
            edges,
 | 
			
		||||
        } = self;
 | 
			
		||||
        if let Some(node) = nodes.next() {
 | 
			
		||||
            node_indexes.insert(node.id(), node_indexes.len());
 | 
			
		||||
            return Some(petgraph::data::Element::Node { weight: node });
 | 
			
		||||
        }
 | 
			
		||||
        let edge = edges.next()?;
 | 
			
		||||
        Some(petgraph::data::Element::Edge {
 | 
			
		||||
            source: node_indexes[&edge.source()],
 | 
			
		||||
            target: node_indexes[&edge.target()],
 | 
			
		||||
            weight: *edge.weight(),
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone)]
 | 
			
		||||
struct AssignmentsNodeIdentifiers {
 | 
			
		||||
    assignment_indexes: std::ops::Range<usize>,
 | 
			
		||||
    small_slots: std::ops::Range<u32>,
 | 
			
		||||
    big_slots: std::ops::Range<u32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Iterator for AssignmentsNodeIdentifiers {
 | 
			
		||||
    type Item = AssignmentOrSlotIndex;
 | 
			
		||||
    fn next(&mut self) -> Option<Self::Item> {
 | 
			
		||||
impl AssignmentsNodeIdentifiers {
 | 
			
		||||
    fn internal_iter<'a>(&'a mut self) -> impl Iterator<Item = AssignmentOrSlotIndex> + 'a {
 | 
			
		||||
        let Self {
 | 
			
		||||
            assignment_indexes,
 | 
			
		||||
            small_slots,
 | 
			
		||||
            big_slots,
 | 
			
		||||
        } = self;
 | 
			
		||||
        assignment_indexes
 | 
			
		||||
            .next()
 | 
			
		||||
            .map(AssignmentOrSlotIndex::AssignmentIndex)
 | 
			
		||||
            .or_else(|| {
 | 
			
		||||
                small_slots.next().map(|value| {
 | 
			
		||||
                    AssignmentOrSlotIndex::SmallSlots(StatePartIndex {
 | 
			
		||||
                        value,
 | 
			
		||||
                        _phantom: PhantomData,
 | 
			
		||||
                    })
 | 
			
		||||
            .chain(small_slots.map(|value| {
 | 
			
		||||
                AssignmentOrSlotIndex::SmallSlot(StatePartIndex {
 | 
			
		||||
                    value,
 | 
			
		||||
                    _phantom: PhantomData,
 | 
			
		||||
                })
 | 
			
		||||
            })
 | 
			
		||||
            .or_else(|| {
 | 
			
		||||
                big_slots.next().map(|value| {
 | 
			
		||||
                    AssignmentOrSlotIndex::BigSlots(StatePartIndex {
 | 
			
		||||
                        value,
 | 
			
		||||
                        _phantom: PhantomData,
 | 
			
		||||
                    })
 | 
			
		||||
            }))
 | 
			
		||||
            .chain(big_slots.map(|value| {
 | 
			
		||||
                AssignmentOrSlotIndex::BigSlot(StatePartIndex {
 | 
			
		||||
                    value,
 | 
			
		||||
                    _phantom: PhantomData,
 | 
			
		||||
                })
 | 
			
		||||
            })
 | 
			
		||||
            }))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Iterator for AssignmentsNodeIdentifiers {
 | 
			
		||||
    type Item = AssignmentOrSlotIndex;
 | 
			
		||||
    fn next(&mut self) -> Option<Self::Item> {
 | 
			
		||||
        self.internal_iter().next()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn nth(&mut self, n: usize) -> Option<Self::Item> {
 | 
			
		||||
        self.internal_iter().nth(n)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -580,6 +686,44 @@ impl<'a> IntoNodeIdentifiers for &'a Assignments {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct AssignmentsNodes<'a> {
 | 
			
		||||
    assignments: &'a Assignments,
 | 
			
		||||
    nodes: AssignmentsNodeIdentifiers,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> Iterator for AssignmentsNodes<'a> {
 | 
			
		||||
    type Item = AssignmentsNodeRef<'a>;
 | 
			
		||||
 | 
			
		||||
    fn next(&mut self) -> Option<Self::Item> {
 | 
			
		||||
        self.nodes.next().map(|node| match node {
 | 
			
		||||
            AssignmentOrSlotIndex::AssignmentIndex(index) => AssignmentsNodeRef::Assignment {
 | 
			
		||||
                index,
 | 
			
		||||
                assignment: &self.assignments.assignments()[index],
 | 
			
		||||
            },
 | 
			
		||||
            AssignmentOrSlotIndex::SmallSlot(slot) => AssignmentsNodeRef::SmallSlot(
 | 
			
		||||
                slot,
 | 
			
		||||
                *self.assignments.slots_layout().small_slots.debug_data(slot),
 | 
			
		||||
            ),
 | 
			
		||||
            AssignmentOrSlotIndex::BigSlot(slot) => AssignmentsNodeRef::BigSlot(
 | 
			
		||||
                slot,
 | 
			
		||||
                *self.assignments.slots_layout().big_slots.debug_data(slot),
 | 
			
		||||
            ),
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> IntoNodeReferences for &'a Assignments {
 | 
			
		||||
    type NodeRef = AssignmentsNodeRef<'a>;
 | 
			
		||||
    type NodeReferences = AssignmentsNodes<'a>;
 | 
			
		||||
 | 
			
		||||
    fn node_references(self) -> Self::NodeReferences {
 | 
			
		||||
        AssignmentsNodes {
 | 
			
		||||
            assignments: self,
 | 
			
		||||
            nodes: self.node_identifiers(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct AssignmentsNeighborsDirected<'a> {
 | 
			
		||||
    assignment_indexes: std::slice::Iter<'a, usize>,
 | 
			
		||||
    small_slots: std::collections::btree_set::Iter<'a, StatePartIndex<StatePartKindSmallSlots>>,
 | 
			
		||||
| 
						 | 
				
			
			@ -603,13 +747,13 @@ impl Iterator for AssignmentsNeighborsDirected<'_> {
 | 
			
		|||
        } else if let retval @ Some(_) = small_slots
 | 
			
		||||
            .next()
 | 
			
		||||
            .copied()
 | 
			
		||||
            .map(AssignmentOrSlotIndex::SmallSlots)
 | 
			
		||||
            .map(AssignmentOrSlotIndex::SmallSlot)
 | 
			
		||||
        {
 | 
			
		||||
            retval
 | 
			
		||||
        } else if let retval @ Some(_) = big_slots
 | 
			
		||||
            .next()
 | 
			
		||||
            .copied()
 | 
			
		||||
            .map(AssignmentOrSlotIndex::BigSlots)
 | 
			
		||||
            .map(AssignmentOrSlotIndex::BigSlot)
 | 
			
		||||
        {
 | 
			
		||||
            retval
 | 
			
		||||
        } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -664,12 +808,12 @@ impl<'a> IntoNeighborsDirected for &'a Assignments {
 | 
			
		|||
                    big_slots: big_slots.iter(),
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            AssignmentOrSlotIndex::SmallSlots(slot) => AssignmentsNeighborsDirected {
 | 
			
		||||
            AssignmentOrSlotIndex::SmallSlot(slot) => AssignmentsNeighborsDirected {
 | 
			
		||||
                assignment_indexes: slot_map[slot].iter(),
 | 
			
		||||
                small_slots: Default::default(),
 | 
			
		||||
                big_slots: Default::default(),
 | 
			
		||||
            },
 | 
			
		||||
            AssignmentOrSlotIndex::BigSlots(slot) => AssignmentsNeighborsDirected {
 | 
			
		||||
            AssignmentOrSlotIndex::BigSlot(slot) => AssignmentsNeighborsDirected {
 | 
			
		||||
                assignment_indexes: slot_map[slot].iter(),
 | 
			
		||||
                small_slots: Default::default(),
 | 
			
		||||
                big_slots: Default::default(),
 | 
			
		||||
| 
						 | 
				
			
			@ -678,6 +822,149 @@ impl<'a> IntoNeighborsDirected for &'a Assignments {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl EdgeRef for AssignmentsEdge {
 | 
			
		||||
    type NodeId = AssignmentOrSlotIndex;
 | 
			
		||||
    type EdgeId = AssignmentsEdge;
 | 
			
		||||
    type Weight = AssignmentsEdge;
 | 
			
		||||
 | 
			
		||||
    fn source(&self) -> Self::NodeId {
 | 
			
		||||
        match *self {
 | 
			
		||||
            AssignmentsEdge::IO(AssignmentIO::BigInput {
 | 
			
		||||
                assignment_index: _,
 | 
			
		||||
                slot,
 | 
			
		||||
            }) => AssignmentOrSlotIndex::BigSlot(slot),
 | 
			
		||||
            AssignmentsEdge::IO(AssignmentIO::SmallInput {
 | 
			
		||||
                assignment_index: _,
 | 
			
		||||
                slot,
 | 
			
		||||
            }) => AssignmentOrSlotIndex::SmallSlot(slot),
 | 
			
		||||
            AssignmentsEdge::IO(AssignmentIO::BigOutput {
 | 
			
		||||
                assignment_index,
 | 
			
		||||
                slot: _,
 | 
			
		||||
            }) => AssignmentOrSlotIndex::AssignmentIndex(assignment_index),
 | 
			
		||||
            AssignmentsEdge::IO(AssignmentIO::SmallOutput {
 | 
			
		||||
                assignment_index,
 | 
			
		||||
                slot: _,
 | 
			
		||||
            }) => AssignmentOrSlotIndex::AssignmentIndex(assignment_index),
 | 
			
		||||
            AssignmentsEdge::AssignmentImmediatePredecessor {
 | 
			
		||||
                predecessor_assignment_index,
 | 
			
		||||
                assignment_index: _,
 | 
			
		||||
            } => AssignmentOrSlotIndex::AssignmentIndex(predecessor_assignment_index),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn target(&self) -> Self::NodeId {
 | 
			
		||||
        match *self {
 | 
			
		||||
            AssignmentsEdge::IO(AssignmentIO::BigInput {
 | 
			
		||||
                assignment_index,
 | 
			
		||||
                slot: _,
 | 
			
		||||
            }) => AssignmentOrSlotIndex::AssignmentIndex(assignment_index),
 | 
			
		||||
            AssignmentsEdge::IO(AssignmentIO::SmallInput {
 | 
			
		||||
                assignment_index,
 | 
			
		||||
                slot: _,
 | 
			
		||||
            }) => AssignmentOrSlotIndex::AssignmentIndex(assignment_index),
 | 
			
		||||
            AssignmentsEdge::IO(AssignmentIO::BigOutput {
 | 
			
		||||
                assignment_index: _,
 | 
			
		||||
                slot,
 | 
			
		||||
            }) => AssignmentOrSlotIndex::BigSlot(slot),
 | 
			
		||||
            AssignmentsEdge::IO(AssignmentIO::SmallOutput {
 | 
			
		||||
                assignment_index: _,
 | 
			
		||||
                slot,
 | 
			
		||||
            }) => AssignmentOrSlotIndex::SmallSlot(slot),
 | 
			
		||||
            AssignmentsEdge::AssignmentImmediatePredecessor {
 | 
			
		||||
                predecessor_assignment_index: _,
 | 
			
		||||
                assignment_index,
 | 
			
		||||
            } => AssignmentOrSlotIndex::AssignmentIndex(assignment_index),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn weight(&self) -> &Self::Weight {
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn id(&self) -> Self::EdgeId {
 | 
			
		||||
        *self
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct AssignmentsEdges<'a> {
 | 
			
		||||
    assignments: &'a Assignments,
 | 
			
		||||
    nodes: AssignmentsNodeIdentifiers,
 | 
			
		||||
    outgoing_neighbors: Option<(AssignmentOrSlotIndex, AssignmentsNeighborsDirected<'a>)>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Iterator for AssignmentsEdges<'_> {
 | 
			
		||||
    type Item = AssignmentsEdge;
 | 
			
		||||
 | 
			
		||||
    fn next(&mut self) -> Option<Self::Item> {
 | 
			
		||||
        loop {
 | 
			
		||||
            if let Some((node, outgoing_neighbors)) = &mut self.outgoing_neighbors {
 | 
			
		||||
                if let Some(outgoing_neighbor) = outgoing_neighbors.next() {
 | 
			
		||||
                    return Some(match (*node, outgoing_neighbor) {
 | 
			
		||||
                        (
 | 
			
		||||
                            AssignmentOrSlotIndex::SmallSlot(_) | AssignmentOrSlotIndex::BigSlot(_),
 | 
			
		||||
                            AssignmentOrSlotIndex::SmallSlot(_) | AssignmentOrSlotIndex::BigSlot(_),
 | 
			
		||||
                        ) => unreachable!(),
 | 
			
		||||
                        (
 | 
			
		||||
                            AssignmentOrSlotIndex::AssignmentIndex(predecessor_assignment_index),
 | 
			
		||||
                            AssignmentOrSlotIndex::AssignmentIndex(assignment_index),
 | 
			
		||||
                        ) => AssignmentsEdge::AssignmentImmediatePredecessor {
 | 
			
		||||
                            predecessor_assignment_index,
 | 
			
		||||
                            assignment_index,
 | 
			
		||||
                        },
 | 
			
		||||
                        (
 | 
			
		||||
                            AssignmentOrSlotIndex::AssignmentIndex(assignment_index),
 | 
			
		||||
                            AssignmentOrSlotIndex::SmallSlot(slot),
 | 
			
		||||
                        ) => AssignmentsEdge::IO(AssignmentIO::SmallOutput {
 | 
			
		||||
                            assignment_index,
 | 
			
		||||
                            slot,
 | 
			
		||||
                        }),
 | 
			
		||||
                        (
 | 
			
		||||
                            AssignmentOrSlotIndex::AssignmentIndex(assignment_index),
 | 
			
		||||
                            AssignmentOrSlotIndex::BigSlot(slot),
 | 
			
		||||
                        ) => AssignmentsEdge::IO(AssignmentIO::BigOutput {
 | 
			
		||||
                            assignment_index,
 | 
			
		||||
                            slot,
 | 
			
		||||
                        }),
 | 
			
		||||
                        (
 | 
			
		||||
                            AssignmentOrSlotIndex::SmallSlot(slot),
 | 
			
		||||
                            AssignmentOrSlotIndex::AssignmentIndex(assignment_index),
 | 
			
		||||
                        ) => AssignmentsEdge::IO(AssignmentIO::SmallInput {
 | 
			
		||||
                            assignment_index,
 | 
			
		||||
                            slot,
 | 
			
		||||
                        }),
 | 
			
		||||
                        (
 | 
			
		||||
                            AssignmentOrSlotIndex::BigSlot(slot),
 | 
			
		||||
                            AssignmentOrSlotIndex::AssignmentIndex(assignment_index),
 | 
			
		||||
                        ) => AssignmentsEdge::IO(AssignmentIO::BigInput {
 | 
			
		||||
                            assignment_index,
 | 
			
		||||
                            slot,
 | 
			
		||||
                        }),
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            let node = self.nodes.next()?;
 | 
			
		||||
            self.outgoing_neighbors = Some((
 | 
			
		||||
                node,
 | 
			
		||||
                self.assignments
 | 
			
		||||
                    .neighbors_directed(node, petgraph::Direction::Outgoing),
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> IntoEdgeReferences for &'a Assignments {
 | 
			
		||||
    type EdgeRef = AssignmentsEdge;
 | 
			
		||||
    type EdgeReferences = AssignmentsEdges<'a>;
 | 
			
		||||
 | 
			
		||||
    fn edge_references(self) -> Self::EdgeReferences {
 | 
			
		||||
        AssignmentsEdges {
 | 
			
		||||
            assignments: self,
 | 
			
		||||
            nodes: self.node_identifiers(),
 | 
			
		||||
            outgoing_neighbors: None,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct AssignmentsVisitMap {
 | 
			
		||||
    assignments: Vec<bool>,
 | 
			
		||||
    slots: DenseSlotSet,
 | 
			
		||||
| 
						 | 
				
			
			@ -689,8 +976,8 @@ impl VisitMap<AssignmentOrSlotIndex> for AssignmentsVisitMap {
 | 
			
		|||
            AssignmentOrSlotIndex::AssignmentIndex(assignment_index) => {
 | 
			
		||||
                !mem::replace(&mut self.assignments[assignment_index], true)
 | 
			
		||||
            }
 | 
			
		||||
            AssignmentOrSlotIndex::SmallSlots(slot) => self.slots.insert(slot),
 | 
			
		||||
            AssignmentOrSlotIndex::BigSlots(slot) => self.slots.insert(slot),
 | 
			
		||||
            AssignmentOrSlotIndex::SmallSlot(slot) => self.slots.insert(slot),
 | 
			
		||||
            AssignmentOrSlotIndex::BigSlot(slot) => self.slots.insert(slot),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -699,8 +986,8 @@ impl VisitMap<AssignmentOrSlotIndex> for AssignmentsVisitMap {
 | 
			
		|||
            AssignmentOrSlotIndex::AssignmentIndex(assignment_index) => {
 | 
			
		||||
                self.assignments[assignment_index]
 | 
			
		||||
            }
 | 
			
		||||
            AssignmentOrSlotIndex::SmallSlots(slot) => self.slots.contains(slot),
 | 
			
		||||
            AssignmentOrSlotIndex::BigSlots(slot) => self.slots.contains(slot),
 | 
			
		||||
            AssignmentOrSlotIndex::SmallSlot(slot) => self.slots.contains(slot),
 | 
			
		||||
            AssignmentOrSlotIndex::BigSlot(slot) => self.slots.contains(slot),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2725,12 +3012,15 @@ impl Compiler {
 | 
			
		|||
                .compile_expr(instantiated_module, Expr::canonical(expr.base()))
 | 
			
		||||
                .map_ty(Bundle::from_canonical)
 | 
			
		||||
                .field_by_index(expr.field_index()),
 | 
			
		||||
            ExprEnum::VariantAccess(variant_access) => self.compile_expr(
 | 
			
		||||
                instantiated_module,
 | 
			
		||||
                variant_access.base().cast_to_bits()
 | 
			
		||||
                    [Expr::ty(variant_access.base()).discriminant_bit_width()..]
 | 
			
		||||
                    .cast_bits_to(Expr::ty(expr)),
 | 
			
		||||
            ),
 | 
			
		||||
            ExprEnum::VariantAccess(variant_access) => {
 | 
			
		||||
                let start = Expr::ty(variant_access.base()).discriminant_bit_width();
 | 
			
		||||
                let len = Expr::ty(expr).bit_width();
 | 
			
		||||
                self.compile_expr(
 | 
			
		||||
                    instantiated_module,
 | 
			
		||||
                    variant_access.base().cast_to_bits()[start..start + len]
 | 
			
		||||
                        .cast_bits_to(Expr::ty(expr)),
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            ExprEnum::ArrayIndex(expr) => self
 | 
			
		||||
                .compile_expr(instantiated_module, Expr::canonical(expr.base()))
 | 
			
		||||
                .map_ty(Array::from_canonical)
 | 
			
		||||
| 
						 | 
				
			
			@ -4146,7 +4436,13 @@ impl Compiler {
 | 
			
		|||
    }
 | 
			
		||||
    fn process_assignments(&mut self) {
 | 
			
		||||
        self.assignments
 | 
			
		||||
            .finalize(self.insns.state_layout().len().ty);
 | 
			
		||||
            .finalize(self.insns.state_layout().ty.clone().into());
 | 
			
		||||
        println!(
 | 
			
		||||
            "{:#?}",
 | 
			
		||||
            petgraph::dot::Dot::new(&petgraph::graph::DiGraph::<_, _, usize>::from_elements(
 | 
			
		||||
                self.assignments.elements()
 | 
			
		||||
            ))
 | 
			
		||||
        );
 | 
			
		||||
        let assignments_order: Vec<_> = match petgraph::algo::toposort(&self.assignments, None) {
 | 
			
		||||
            Ok(nodes) => nodes
 | 
			
		||||
                .into_iter()
 | 
			
		||||
| 
						 | 
				
			
			@ -4160,11 +4456,11 @@ impl Compiler {
 | 
			
		|||
                    "combinatorial logic cycle detected at: {}",
 | 
			
		||||
                    self.assignments.assignments()[assignment_index].source_location,
 | 
			
		||||
                ),
 | 
			
		||||
                AssignmentOrSlotIndex::SmallSlots(slot) => panic!(
 | 
			
		||||
                AssignmentOrSlotIndex::SmallSlot(slot) => panic!(
 | 
			
		||||
                    "combinatorial logic cycle detected through: {}",
 | 
			
		||||
                    self.insns.state_layout().ty.small_slots.debug_data[slot.as_usize()].name,
 | 
			
		||||
                ),
 | 
			
		||||
                AssignmentOrSlotIndex::BigSlots(slot) => panic!(
 | 
			
		||||
                AssignmentOrSlotIndex::BigSlot(slot) => panic!(
 | 
			
		||||
                    "combinatorial logic cycle detected through: {}",
 | 
			
		||||
                    self.insns.state_layout().ty.big_slots.debug_data[slot.as_usize()].name,
 | 
			
		||||
                ),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1652,6 +1652,9 @@ impl<K: StatePartKind, BK: InsnsBuildingKind> StatePartLayout<K, BK> {
 | 
			
		|||
            _phantom: PhantomData,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    pub(crate) fn debug_data(&self, index: StatePartIndex<K>) -> &K::DebugData {
 | 
			
		||||
        &self.debug_data[index.as_usize()]
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<K: StatePartKind> From<StatePartLayout<K, InsnsBuilding>>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue