Create and populate virtual registers for all ports
(&mut self, virts: &mut VirtualRegisterMap, token: &mut NodeOwner)
| 250 | |
| 251 | /// Create and populate virtual registers for all ports |
| 252 | pub fn create_virtual_registers(&mut self, virts: &mut VirtualRegisterMap, token: &mut NodeOwner) { |
| 253 | let mut reg = virts.len().try_into().unwrap(); |
| 254 | let mut ports = self.ports.clone(); |
| 255 | // Give all ports that have no incoming edges and no storage a new virtual register |
| 256 | ports.clone().externals(Direction::Incoming).filter(|e| { |
| 257 | let e = &ports[*e]; |
| 258 | (match e.variant { EdgeVariant::Data => true, _ => false }) && e.storage.is_none() |
| 259 | }).map(|e| { |
| 260 | self.ports[e].set_storage(Storage::Virtual(reg)); |
| 261 | println!("gave {:?} virtual register {}", e, reg); |
| 262 | virts.insert(reg.into(), VirtualRegister { ports: vec![], hints: HashSet::new(), backing: None, allocated: false }); |
| 263 | reg += 1; |
| 264 | }).for_each(drop); |
| 265 | |
| 266 | // Give all ports that have a physical storage a virtual register constrained to the |
| 267 | // physical |
| 268 | ports.node_indices().clone().filter(|e| if let Some(Storage::Physical(_)) = *ports[*e].storage { true } else { false } ).map(|e| { |
| 269 | let phys = if let Some(Storage::Physical(p)) = *self.ports[e].storage { p } |
| 270 | else { panic!() }; |
| 271 | self.ports[e].set_storage(Storage::Virtual(reg)); |
| 272 | println!("made physical {:?} into virtual {}", e, reg); |
| 273 | let mut set = HashSet::new(); |
| 274 | set.insert(phys); |
| 275 | virts.insert(reg.into(), VirtualRegister { ports: vec![], hints: set, backing: Some(phys), allocated: false }); |
| 276 | reg += 1; |
| 277 | }).for_each(drop); |
| 278 | ports = self.ports.clone(); |
| 279 | |
| 280 | // We have a set of all the ports and edges between them |
| 281 | let mut ports_edges: Vec<_> = ports.edge_references() |
| 282 | .filter(|e| self.ports[e.source()].variant == EdgeVariant::Data ).collect(); |
| 283 | ports_edges.sort_by_key(|e| self.ports[e.target()].time); |
| 284 | ports_edges.reverse(); |
| 285 | // And we repeatedly propogate any edges we can. If we do propogate, we |
| 286 | // can remove it from the working set for next iteration. |
| 287 | // This is pretty slow, but who cares for now tbh. |
| 288 | // |
| 289 | // This should just be a queue that we add all source.incoming() to when |
| 290 | // we process (backwards moving frontier) |
| 291 | while ports_edges.len() > 0 { |
| 292 | println!("propogating edges, {} left", ports_edges.len()); |
| 293 | println!("{:?}", ports_edges); |
| 294 | ports_edges = ports_edges.drain(..).filter(|e| { |
| 295 | let mut source = &self.ports[e.target()]; |
| 296 | let mut sink = &self.ports[e.source()]; |
| 297 | println!("v{} <- v{}", sink.id, source.id); |
| 298 | println!("storages {} <- {}", sink.storage, source.storage); |
| 299 | if let (None, _) = (*sink.storage, *source.storage) { |
| 300 | // We don't have a target storage to progate upwards, so |
| 301 | // have to try against next time |
| 302 | println!("skip"); |
| 303 | return true |
| 304 | } |
| 305 | let (sink_backing, source_backing) = ( |
| 306 | sink.storage, |
| 307 | source.storage, |
| 308 | ); |
| 309 | println!("storages {} <- {}", sink.storage, source.storage); |
no test coverage detected