1 // Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com> 2 // 3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 6 // option. This file may not be copied, modified, or distributed 7 // except according to those terms. 8 9 use crate::block::Block; 10 use std::fmt; 11 use std::fmt::Debug; 12 use std::ops::{Index, IndexMut}; 13 14 /// Structure representing the memory matrix. 15 pub struct Memory { 16 /// The number of rows. 17 rows: usize, 18 19 /// The number of columns. 20 cols: usize, 21 22 /// The flat array of blocks representing the memory matrix. 23 blocks: Box<[Block]>, 24 } 25 26 impl Memory { 27 /// Creates a new memory matrix. new(lanes: u32, lane_length: u32) -> Memory28 pub fn new(lanes: u32, lane_length: u32) -> Memory { 29 let rows = lanes as usize; 30 let cols = lane_length as usize; 31 let total = rows * cols; 32 let blocks = vec![Block::zero(); total].into_boxed_slice(); 33 Memory { rows, cols, blocks } 34 } 35 36 #[cfg(feature = "crossbeam-utils")] 37 /// Gets the mutable lanes representation of the memory matrix. as_lanes_mut(&mut self) -> Vec<&mut Memory>38 pub fn as_lanes_mut(&mut self) -> Vec<&mut Memory> { 39 let ptr: *mut Memory = self; 40 let mut vec = Vec::with_capacity(self.rows); 41 for _ in 0..self.rows { 42 vec.push(unsafe { &mut (*ptr) }); 43 } 44 vec 45 } 46 } 47 48 impl Debug for Memory { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result49 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 50 write!(f, "Memory {{ rows: {}, cols: {} }}", self.rows, self.cols) 51 } 52 } 53 54 impl Index<u32> for Memory { 55 type Output = Block; index(&self, index: u32) -> &Block56 fn index(&self, index: u32) -> &Block { 57 &self.blocks[index as usize] 58 } 59 } 60 61 impl Index<u64> for Memory { 62 type Output = Block; index(&self, index: u64) -> &Block63 fn index(&self, index: u64) -> &Block { 64 &self.blocks[index as usize] 65 } 66 } 67 68 impl Index<(u32, u32)> for Memory { 69 type Output = Block; index(&self, index: (u32, u32)) -> &Block70 fn index(&self, index: (u32, u32)) -> &Block { 71 let pos = ((index.0 as usize) * self.cols) + (index.1 as usize); 72 &self.blocks[pos] 73 } 74 } 75 76 impl IndexMut<u32> for Memory { index_mut(&mut self, index: u32) -> &mut Block77 fn index_mut(&mut self, index: u32) -> &mut Block { 78 &mut self.blocks[index as usize] 79 } 80 } 81 82 impl IndexMut<u64> for Memory { index_mut(&mut self, index: u64) -> &mut Block83 fn index_mut(&mut self, index: u64) -> &mut Block { 84 &mut self.blocks[index as usize] 85 } 86 } 87 88 impl IndexMut<(u32, u32)> for Memory { index_mut(&mut self, index: (u32, u32)) -> &mut Block89 fn index_mut(&mut self, index: (u32, u32)) -> &mut Block { 90 let pos = ((index.0 as usize) * self.cols) + (index.1 as usize); 91 &mut self.blocks[pos] 92 } 93 } 94 95 #[cfg(test)] 96 mod tests { 97 98 use crate::memory::Memory; 99 100 #[test] new_returns_correct_instance()101 fn new_returns_correct_instance() { 102 let lanes = 4; 103 let lane_length = 128; 104 let memory = Memory::new(lanes, lane_length); 105 assert_eq!(memory.rows, lanes as usize); 106 assert_eq!(memory.cols, lane_length as usize); 107 assert_eq!(memory.blocks.len(), 512); 108 } 109 110 #[cfg(feature = "crossbeam-utils")] 111 #[test] as_lanes_mut_returns_correct_vec()112 fn as_lanes_mut_returns_correct_vec() { 113 let mut memory = Memory::new(4, 128); 114 let lanes = memory.as_lanes_mut(); 115 assert_eq!(lanes.len(), 4); 116 } 117 } 118