コード例 #1
0
    def test_add_invalid_type(self):
        ''' Modifier add invalid type. '''
        network = Network('test_net')
        network.set_input(InputLayer(3, 224))

        with self.assertRaisesRegexp(TypeError, 'Network: .*Layer.*'):
            network.add('c1', (3, 64, 224, 3))
コード例 #2
0
 def test_set_input_type(self):
     ''' Modifier set_input type. '''
     network = Network('test_net')
     with self.assertRaisesRegexp(TypeError, 'Network: .*input_layer.*'):
         network.set_input(Layer(3, 24))
     with self.assertRaisesRegexp(TypeError, 'Network: .*input_layer.*'):
         network.set_input(ConvLayer(3, 8, 24, 3))
コード例 #3
0
    def test_add_unmatch_prev(self):
        ''' Modifier add unmatch prevs. '''
        network = Network('test_net')
        network.set_input(InputLayer(3, 224))
        network.add('c1', ConvLayer(3, 64, 224, 3))

        with self.assertRaisesRegexp(ValueError,
                                     'Network: .*c1.*p1.*mismatch fmap.*'):
            network.add('p1', PoolingLayer(64, 7, 2))
        self.assertEqual(len(network), 1)
        with self.assertRaisesRegexp(ValueError,
                                     'Network: .*c1.*c2.*mismatch fmap.*'):
            network.add('c2', ConvLayer(64, 128, 220, 3))
        self.assertEqual(len(network), 1)

        with self.assertRaisesRegexp(ValueError, 'Network: .*merge.*c1.*p1.*'):
            network.add('p1', PoolingLayer(32, 7, 32))
        self.assertEqual(len(network), 1)
        with self.assertRaisesRegexp(ValueError, 'Network: .*merge.*c1.*c2.*'):
            network.add('c2', ConvLayer(32, 128, 224, 3))
        self.assertEqual(len(network), 1)

        network.add('c2', ConvLayer(64, 128, 224, 3))

        with self.assertRaisesRegexp(ValueError,
                                     r'Network: .*merge.*c1\s*c2.*p1.*'):
            network.add('p1', PoolingLayer(128, 7, 32), prevs=('c1', 'c2'))
        self.assertEqual(len(network), 2)
コード例 #4
0
    def test_add_no_prev(self):
        ''' Modifier add no prevs. '''
        network = Network('test_net')
        network.set_input(InputLayer(3, 224))

        network.add('c1', ConvLayer(3, 64, 224, 3))
        with self.assertRaisesRegexp(KeyError, 'Network: .*prev.*p1.*'):
            network.add('p1', PoolingLayer(64, 7, 32), prevs='p1')
コード例 #5
0
    def test_add_same_key(self):
        ''' Modifier add same key. '''
        network = Network('test_net')
        network.set_input(InputLayer(3, 224))

        network.add('c1', ConvLayer(3, 64, 224, 3))
        with self.assertRaisesRegexp(KeyError, 'Network: .*c1.*'):
            network.add('c1', ConvLayer(64, 128, 224, 3))
コード例 #6
0
 def test_set_input(self):
     ''' Modifier set_input. '''
     network = Network('test_net')
     network.set_input(InputLayer(3, 24))
     self.assertIsInstance(network.input_layer(), InputLayer)
     self.assertEqual(network.input_layer().nofm, 3)
     self.assertEqual(network.input_layer().hofm, 24)
     self.assertEqual(network.input_layer().wofm, 24)
     self.assertEqual(len(network), 0)
コード例 #7
0
def MLP_network(input_size, hiden_fc1, hiden_fc2, hiden_fc3, output_size):
    NN = Network('MLP_L')

    NN.set_input(InputLayer(input_size, 1))
    NN.add('fc1', FCLayer(input_size, hiden_fc1))
    NN.add('fc2', FCLayer(hiden_fc1, hiden_fc2))
    NN.add('fc3', FCLayer(hiden_fc2, hiden_fc3))
    NN.add('fc4', FCLayer(hiden_fc3, output_size))

    return NN
コード例 #8
0
    def test_iter(self):
        ''' Accessor iter. '''
        num = 0
        for layer in self.network:
            self.assertIn(layer, self.network)
            self.assertIsInstance(self.network[layer], Layer)
            num += 1
        self.assertEqual(len(self.network), num)

        network = Network('test_net')
        network.set_input(InputLayer(3, 224))
        with self.assertRaises(StopIteration):
            _ = next(iter(network))
コード例 #9
0
    def test_len(self):
        ''' Accessor len. '''
        self.assertEqual(len(self.network), 3)

        network = Network('test_net')
        self.assertEqual(len(network), 0)
        network.set_input(InputLayer(3, 224))
        self.assertEqual(len(network), 0)
        network.add('c1', ConvLayer(3, 4, 224, 1))
        self.assertEqual(len(network), 1)

        self.network.add('f2', FCLayer(64, 2000, 7), prevs='p1')
        self.assertEqual(len(self.network), 4)
        self.network.add('f3', FCLayer(3000, 1000), prevs=('f1', 'f2'))
        self.assertEqual(len(self.network), 5)
        self.network.add('f4', FCLayer(1000, 1000), prevs=('f1', 'f3'))
        self.assertEqual(len(self.network), 6)
コード例 #10
0
ファイル: mlp_m.py プロジェクト: yue32000/nn_dataflow
TETRIS paper ("TETRIS: Scalable and Efficient Neural Network Acceleration with
3D Memory", in ASPLOS'17. April, 2017), and that you send us a citation of your
work.

This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the BSD-3 License for more details.

You should have received a copy of the Modified BSD-3 License along with this
program. If not, see <https://opensource.org/licenses/BSD-3-Clause>.
"""

from nn_dataflow.core import Network
from nn_dataflow.core import InputLayer, FCLayer

'''
MLP-M

PRIME, 2016
'''

NN = Network('MLP-M')

NN.set_input(InputLayer(784, 1))

NN.add('fc1', FCLayer(784, 1000))
NN.add('fc2', FCLayer(1000, 500))
NN.add('fc3', FCLayer(500, 250))
NN.add('fc4', FCLayer(250, 10))

コード例 #11
0
ファイル: resnet152.py プロジェクト: yue32000/nn_dataflow
You should have received a copy of the Modified BSD-3 License along with this
program. If not, see <https://opensource.org/licenses/BSD-3-Clause>.
"""

from nn_dataflow.core import Network
from nn_dataflow.core import InputLayer, ConvLayer, PoolingLayer

'''
ResNet-152

He, Zhang, Ren, and Sun, 2015
'''

NN = Network('ResNet')

NN.set_input(InputLayer(3, 224))

_PREVS = None

NN.add('conv1', ConvLayer(3, 64, 112, 7, 2))
NN.add('pool1', PoolingLayer(64, 56, 2))

for i in range(1, 4):
    NN.add('conv2_{}_a'.format(i),
           ConvLayer(64, 64, 56, 1) if i == 1 else ConvLayer(256, 64, 56, 1),
           prevs=_PREVS)
    NN.add('conv2_{}_b'.format(i), ConvLayer(64, 64, 56, 3))
    NN.add('conv2_{}_c'.format(i), ConvLayer(64, 256, 56, 1))

    # With residual shortcut.
    if i == 1:
コード例 #12
0
 def test_set_input_duplicate(self):
     ''' Modifier set_input duplicate. '''
     network = Network('test_net')
     network.set_input(InputLayer(3, 24))
     with self.assertRaisesRegexp(KeyError, 'Network: .*input.*'):
         network.set_input(InputLayer(3, 24))
コード例 #13
0
class TestNetwork(unittest.TestCase):
    ''' Tests for Network. '''

    # pylint: disable=too-many-public-methods

    def setUp(self):
        ''' Set up. '''
        self.network = Network('test_net')
        self.network.set_input(InputLayer(3, 224))
        self.network.add('c1', ConvLayer(3, 64, 224, 3))
        self.network.add('p1', PoolingLayer(64, 7, 32))
        self.network.add('f1', FCLayer(64, 1000, 7))

    def test_set_input(self):
        ''' Modifier set_input. '''
        network = Network('test_net')
        network.set_input(InputLayer(3, 24))
        self.assertIsInstance(network.input_layer(), InputLayer)
        self.assertEqual(network.input_layer().nofm, 3)
        self.assertEqual(network.input_layer().hofm, 24)
        self.assertEqual(network.input_layer().wofm, 24)
        self.assertEqual(len(network), 0)

    def test_set_input_type(self):
        ''' Modifier set_input type. '''
        network = Network('test_net')
        with self.assertRaisesRegexp(TypeError, 'Network: .*input_layer.*'):
            network.set_input(Layer(3, 24))
        with self.assertRaisesRegexp(TypeError, 'Network: .*input_layer.*'):
            network.set_input(ConvLayer(3, 8, 24, 3))

    def test_set_input_duplicate(self):
        ''' Modifier set_input duplicate. '''
        network = Network('test_net')
        network.set_input(InputLayer(3, 24))
        with self.assertRaisesRegexp(KeyError, 'Network: .*input.*'):
            network.set_input(InputLayer(3, 24))

    def test_add(self):
        ''' Modifier add. '''
        self.assertEqual(len(self.network), 3)

        self.network.add('f2', FCLayer(64, 2000, 7), prevs='p1')
        self.network.add('f3', FCLayer(3000, 1000), prevs=('f1', 'f2'))
        self.network.add('f4', FCLayer(1000, 1000), prevs=('f1', 'f3'))
        self.assertEqual(len(self.network), 6)

    def test_add_same_key(self):
        ''' Modifier add same key. '''
        network = Network('test_net')
        network.set_input(InputLayer(3, 224))

        network.add('c1', ConvLayer(3, 64, 224, 3))
        with self.assertRaisesRegexp(KeyError, 'Network: .*c1.*'):
            network.add('c1', ConvLayer(64, 128, 224, 3))

    def test_add_no_input(self):
        ''' Modifier add no input. '''
        network = Network('test_net')

        with self.assertRaisesRegexp(RuntimeError, 'Network: .*input.*'):
            network.add('c1', ConvLayer(3, 64, 224, 3))

    def test_add_no_prev(self):
        ''' Modifier add no prevs. '''
        network = Network('test_net')
        network.set_input(InputLayer(3, 224))

        network.add('c1', ConvLayer(3, 64, 224, 3))
        with self.assertRaisesRegexp(KeyError, 'Network: .*prev.*p1.*'):
            network.add('p1', PoolingLayer(64, 7, 32), prevs='p1')

    def test_add_invalid_type(self):
        ''' Modifier add invalid type. '''
        network = Network('test_net')
        network.set_input(InputLayer(3, 224))

        with self.assertRaisesRegexp(TypeError, 'Network: .*Layer.*'):
            network.add('c1', (3, 64, 224, 3))

    def test_add_unmatch_prev(self):
        ''' Modifier add unmatch prevs. '''
        network = Network('test_net')
        network.set_input(InputLayer(3, 224))
        network.add('c1', ConvLayer(3, 64, 224, 3))

        with self.assertRaisesRegexp(ValueError,
                                     'Network: .*c1.*p1.*mismatch fmap.*'):
            network.add('p1', PoolingLayer(64, 7, 2))
        self.assertEqual(len(network), 1)
        with self.assertRaisesRegexp(ValueError,
                                     'Network: .*c1.*c2.*mismatch fmap.*'):
            network.add('c2', ConvLayer(64, 128, 220, 3))
        self.assertEqual(len(network), 1)

        with self.assertRaisesRegexp(ValueError, 'Network: .*merge.*c1.*p1.*'):
            network.add('p1', PoolingLayer(32, 7, 32))
        self.assertEqual(len(network), 1)
        with self.assertRaisesRegexp(ValueError, 'Network: .*merge.*c1.*c2.*'):
            network.add('c2', ConvLayer(32, 128, 224, 3))
        self.assertEqual(len(network), 1)

        network.add('c2', ConvLayer(64, 128, 224, 3))

        with self.assertRaisesRegexp(ValueError,
                                     r'Network: .*merge.*c1\s*c2.*p1.*'):
            network.add('p1', PoolingLayer(128, 7, 32), prevs=('c1', 'c2'))
        self.assertEqual(len(network), 2)

    def test_prev_layers(self):
        ''' Get prev_layers. '''
        self.network.add('f2', FCLayer(64, 2000, 7), prevs='p1')
        self.network.add('f3', FCLayer(3000, 1000), prevs=('f1', 'f2'))
        self.network.add('f4', FCLayer(1000, 1000), prevs=('f1', 'f3'))

        prevs, symbol = self.network.prev_layers('f1')
        self.assertTupleEqual(prevs, ('p1', ))
        self.assertEqual(symbol, '|')

        prevs, symbol = self.network.prev_layers('f2')
        self.assertTupleEqual(prevs, ('p1', ))
        self.assertEqual(symbol, '|')
        prevs, symbol = self.network.prev_layers('f3')
        self.assertTupleEqual(prevs, ('f1', 'f2'))
        self.assertEqual(symbol, '|')

        prevs, symbol = self.network.prev_layers('f4')
        self.assertTupleEqual(prevs, ('f1', 'f3'))
        self.assertEqual(symbol, '+')

    def test_prev_layers_first(self):
        ''' Get prev_layers first layer. '''
        self.network.add('c2',
                         ConvLayer(3, 3, 224, 1),
                         prevs=self.network.INPUT_LAYER_KEY)
        self.network.add('c3',
                         ConvLayer(3, 4, 224, 1),
                         prevs=(self.network.INPUT_LAYER_KEY, 'c2'))

        prevs, symbol = self.network.prev_layers('c1')
        self.assertTupleEqual(prevs, (None, ))
        self.assertEqual(symbol, '|')

        prevs, symbol = self.network.prev_layers('c2')
        self.assertTupleEqual(prevs, (None, ))
        self.assertEqual(symbol, '|')

        prevs, symbol = self.network.prev_layers('c3')
        self.assertTupleEqual(prevs, (None, 'c2'))
        self.assertEqual(symbol, '+')

    def test_prev_layers_input(self):
        ''' Get prev_layers input layer. '''
        with self.assertRaisesRegexp(ValueError, 'Network: .*input.*'):
            _ = self.network.prev_layers(self.network.INPUT_LAYER_KEY)

    def test_next_layers(self):
        ''' Get next_layers. '''
        self.network.add('f2', FCLayer(64, 2000, 7), prevs='p1')
        self.network.add('f3', FCLayer(3000, 1000), prevs=('f1', 'f2'))
        self.network.add('f4', FCLayer(1000, 1000), prevs=('f1', 'f3'))

        nexts = self.network.next_layers('p1')
        self.assertTupleEqual(nexts, ('f1', 'f2'))

        nexts = self.network.next_layers('f1')
        self.assertTupleEqual(nexts, ('f3', 'f4'))

        nexts = self.network.next_layers('f2')
        self.assertTupleEqual(nexts, ('f3', ))

        nexts = self.network.next_layers('f3')
        self.assertTupleEqual(nexts, ('f4', ))

    def test_next_layers_last(self):
        ''' Get next_layers first layer. '''
        nexts = self.network.next_layers('f1')
        self.assertTupleEqual(nexts, (None, ))

        self.network.add('f2', FCLayer(64, 2000, 7), prevs='p1')

        nexts = self.network.next_layers('f1')
        self.assertTupleEqual(nexts, (None, ))
        nexts = self.network.next_layers('f2')
        self.assertTupleEqual(nexts, (None, ))

    def test_next_layers_input(self):
        ''' Get next_layers input layer. '''
        nexts = self.network.next_layers(self.network.INPUT_LAYER_KEY)
        self.assertTupleEqual(nexts, ('c1', ))

        self.network.add('c2',
                         ConvLayer(3, 3, 224, 1),
                         prevs=self.network.INPUT_LAYER_KEY)
        self.network.add('c3',
                         ConvLayer(3, 4, 224, 1),
                         prevs=(self.network.INPUT_LAYER_KEY, 'c2'))
        nexts = self.network.next_layers(self.network.INPUT_LAYER_KEY)
        self.assertTupleEqual(nexts, ('c1', 'c2', 'c3'))

    def test_first_layers(self):
        ''' Get first_layers. '''
        firsts = self.network.first_layers()
        self.assertTupleEqual(firsts, ('c1', ))

        self.network.add('c2',
                         ConvLayer(3, 3, 224, 1),
                         prevs=self.network.INPUT_LAYER_KEY)
        self.network.add('c3',
                         ConvLayer(3, 4, 224, 1),
                         prevs=(self.network.INPUT_LAYER_KEY, 'c2'))

        firsts = self.network.first_layers()
        self.assertTupleEqual(firsts, ('c1', 'c2'))
        self.assertIn('c1', firsts)
        self.assertNotIn('c3', firsts)

    def test_last_layers(self):
        ''' Get last_layers. '''
        lasts = self.network.last_layers()
        self.assertTupleEqual(lasts, ('f1', ))

        self.network.add('f2', FCLayer(64, 2000, 7), prevs='p1')

        lasts = self.network.last_layers()
        self.assertTupleEqual(lasts, ('f1', 'f2'))

    def test_contains(self):
        ''' Whether contains. '''
        self.assertIn('c1', self.network)
        self.assertIn('p1', self.network)
        self.assertIn('f1', self.network)
        self.assertNotIn('f2', self.network)

        self.network.add('f2', FCLayer(64, 2000, 7), prevs='p1')
        self.assertIn('f2', self.network)

    def test_len(self):
        ''' Accessor len. '''
        self.assertEqual(len(self.network), 3)

        network = Network('test_net')
        self.assertEqual(len(network), 0)
        network.set_input(InputLayer(3, 224))
        self.assertEqual(len(network), 0)
        network.add('c1', ConvLayer(3, 4, 224, 1))
        self.assertEqual(len(network), 1)

        self.network.add('f2', FCLayer(64, 2000, 7), prevs='p1')
        self.assertEqual(len(self.network), 4)
        self.network.add('f3', FCLayer(3000, 1000), prevs=('f1', 'f2'))
        self.assertEqual(len(self.network), 5)
        self.network.add('f4', FCLayer(1000, 1000), prevs=('f1', 'f3'))
        self.assertEqual(len(self.network), 6)

    def test_iter(self):
        ''' Accessor iter. '''
        num = 0
        for layer in self.network:
            self.assertIn(layer, self.network)
            self.assertIsInstance(self.network[layer], Layer)
            num += 1
        self.assertEqual(len(self.network), num)

        network = Network('test_net')
        network.set_input(InputLayer(3, 224))
        with self.assertRaises(StopIteration):
            _ = next(iter(network))

    def test_getitem(self):
        ''' Accessor getitem. '''
        self.assertIsInstance(self.network['c1'], ConvLayer)
        self.assertIsInstance(self.network['p1'], PoolingLayer)
        self.assertIsInstance(self.network['f1'], FCLayer)

    def test_getitem_error(self):
        ''' Accessor getitem. '''
        with self.assertRaisesRegexp(KeyError, 'Network: .*c2.*'):
            _ = self.network['c2']

    def test_str(self):
        ''' Accessor str. '''
        string = str(self.network)
        for layer in self.network:
            self.assertIn(layer, string)
コード例 #14
0
class TestNNDataflowScheme(unittest.TestCase):
    ''' Tests for NNDataflowScheme. '''

    def setUp(self):
        self.network = Network('test_net')
        self.network.set_input(InputLayer(3, 224))
        self.network.add('c1', ConvLayer(3, 64, 224, 3))
        self.network.add('p1', PoolingLayer(64, 7, 32), prevs='c1')
        self.network.add('p2', PoolingLayer(64, 7, 32), prevs='c1')
        self.network.add('f1', FCLayer(64, 1000, 7), prevs=['p1', 'p2'])

        self.batch_size = 4

        self.input_layout = partition.get_ofmap_layout(
            self.network.input_layer(), self.batch_size,
            PartitionScheme(order=range(pe.NUM), pdims=[(1, 1)] * pe.NUM),
            NodeRegion(origin=PhyDim2(0, 0), dim=PhyDim2(2, 1),
                       type=NodeRegion.DATA))

        self.c1res = SchedulingResult(
            dict_loop=OrderedDict([('cost', 1.), ('time', 2.), ('ops', 4.),
                                   ('access', [[7, 8, 9]] * me.NUM),
                                  ]),
            dict_part=OrderedDict([('cost', 0.5), ('total_nhops', [4, 5, 6]),
                                   ('num_nodes', 4),
                                  ]),
            ofmap_layout=partition.get_ofmap_layout(
                self.network['c1'], self.batch_size,
                PartitionScheme(order=range(pe.NUM), pdims=[(1, 1)] * pe.NUM),
                NodeRegion(origin=PhyDim2(0, 0), dim=PhyDim2(1, 2),
                           type=NodeRegion.DATA)))

        self.pres = SchedulingResult(
            dict_loop=OrderedDict([('cost', 0.1), ('time', 0.05), ('ops', 0.1),
                                   ('access', [[.7, .8, .9]] * me.NUM),
                                  ]),
            dict_part=OrderedDict([('cost', 0.5), ('total_nhops', [.4, .5, .6]),
                                   ('num_nodes', 2),
                                  ]),
            ofmap_layout=partition.get_ofmap_layout(
                self.network['p1'], self.batch_size,
                PartitionScheme(order=range(pe.NUM), pdims=[(1, 1)] * pe.NUM),
                NodeRegion(origin=PhyDim2(0, 0), dim=PhyDim2(1, 2),
                           type=NodeRegion.DATA)))

        self.dtfl = NNDataflowScheme(self.network, self.input_layout)
        self.dtfl['c1'] = self.c1res
        self.dtfl['p1'] = self.pres
        self.dtfl['p2'] = self.pres

    def test_init(self):
        ''' Initial. '''
        df = NNDataflowScheme(self.network, self.input_layout)

        self.assertEqual(df.network, self.network)
        self.assertEqual(df.input_layout, self.input_layout)

        self.assertEqual(df.total_cost, 0)
        self.assertEqual(df.total_time, 0)
        self.assertFalse(df.res_dict)

        self.assertFalse(df)
        self.assertEqual(df.total_ops, 0)
        self.assertSequenceEqual(df.total_accesses, [0] * me.NUM)
        self.assertEqual(df.total_noc_hops, 0)

    def test_init_invalid_network(self):
        ''' Invalid network. '''
        with self.assertRaisesRegexp(TypeError,
                                     'NNDataflowScheme: .*network*'):
            _ = NNDataflowScheme(self.network['c1'], self.input_layout)

    def test_init_invalid_input_layout(self):
        ''' Invalid input_layout. '''
        with self.assertRaisesRegexp(TypeError,
                                     'NNDataflowScheme: .*input_layout*'):
            _ = NNDataflowScheme(self.network, self.input_layout.frmap)

    def test_setgetitem(self):
        ''' __set/getitem__. '''
        df = NNDataflowScheme(self.network, self.input_layout)

        df['c1'] = self.c1res
        self.assertEqual(df['c1'], self.c1res)

    def test_getitem_not_in(self):
        ''' __getitem__ not in. '''
        df = NNDataflowScheme(self.network, self.input_layout)

        with self.assertRaises(KeyError):
            _ = df['c1']

    def test_setitem_not_in_network(self):
        ''' __setitem__ not in network. '''
        df = NNDataflowScheme(self.network, self.input_layout)

        with self.assertRaisesRegexp(KeyError, 'NNDataflowScheme: .*cc.*'):
            df['cc'] = self.c1res

    def test_setitem_invalid_value(self):
        ''' __setitem__ invalid value. '''
        df = NNDataflowScheme(self.network, self.input_layout)

        with self.assertRaisesRegexp(TypeError,
                                     'NNDataflowScheme: .*SchedulingResult*'):
            df['c1'] = self.c1res.dict_loop

    def test_setitem_already_exists(self):
        ''' __setitem__ already exists. '''
        df = NNDataflowScheme(self.network, self.input_layout)
        df['c1'] = self.c1res

        with self.assertRaisesRegexp(KeyError, 'NNDataflowScheme: .*c1*'):
            df['c1'] = self.c1res

    def test_setitem_prev_not_in(self):
        ''' __setitem__ already exists. '''
        df = NNDataflowScheme(self.network, self.input_layout)

        with self.assertRaisesRegexp(KeyError, 'NNDataflowScheme: .*p1*'):
            df['p1'] = self.pres

    def test_delitem(self):
        ''' __delitem__. '''
        df = NNDataflowScheme(self.network, self.input_layout)
        df['c1'] = self.c1res

        with self.assertRaisesRegexp(KeyError, 'NNDataflowScheme: .*'):
            del df['c1']

    def test_iter_len(self):
        ''' __iter__ and __len__. '''
        self.assertEqual(len(self.dtfl), 3)

        lst = [l for l in self.dtfl]
        self.assertIn('c1', lst)
        self.assertIn('p1', lst)
        self.assertIn('p2', lst)
        self.assertNotIn('f1', lst)

    def test_copy(self):
        ''' copy. '''
        df = self.dtfl
        df2 = df.copy()

        self.assertAlmostEqual(df.total_cost, df2.total_cost)
        self.assertAlmostEqual(df.total_time, df2.total_time)
        self.assertDictEqual(df.res_dict, df2.res_dict)

        # Shallow copy.
        for layer_name in df:
            self.assertEqual(id(df[layer_name]), id(df2[layer_name]))

    def test_properties(self):
        ''' Property accessors. '''
        self.assertAlmostEqual(self.dtfl.total_cost, 1.5 + 0.6 * 2)
        self.assertAlmostEqual(self.dtfl.total_time, 2 + 0.05 * 2)

        self.assertAlmostEqual(self.dtfl.total_ops, 4 + 0.1 * 2)
        for a in self.dtfl.total_accesses:
            self.assertAlmostEqual(a, (7 + 8 + 9) + (.7 + .8 + .9) * 2)
        self.assertAlmostEqual(self.dtfl.total_noc_hops,
                               (4 + 5 + 6) + (.4 + .5 + .6) * 2)
        self.assertAlmostEqual(self.dtfl.total_node_time, 2 * 4 + 0.05 * 2 * 2)

    def test_stats_active_node_pes(self):
        ''' Per-layer stats: active node PEs. '''
        stats = self.dtfl.perlayer_stats('active_node_pes')
        self.assertEqual(len(stats), len(self.dtfl))
        self.assertAlmostEqual(stats['c1'], 0.5)
        self.assertAlmostEqual(stats['p1'], 1)
        self.assertAlmostEqual(stats['p2'], 1)

    def test_stats_total_dram_bw(self):
        ''' Per-layer stats: total DRAM bandwidth. '''
        stats = self.dtfl.perlayer_stats('total_dram_bandwidth')
        self.assertEqual(len(stats), len(self.dtfl))
        self.assertAlmostEqual(stats['c1'], (7 + 8 + 9) / 2.)
        self.assertAlmostEqual(stats['p1'], (.7 + .8 + .9) / 0.05)
        self.assertAlmostEqual(stats['p2'], (.7 + .8 + .9) / 0.05)

    def test_stats_not_supported(self):
        ''' Per-layer stats: not supported. '''
        with self.assertRaisesRegexp(AttributeError,
                                     'NNDataflowScheme: .*not_supported.*'):
            _ = self.dtfl.perlayer_stats('not_supported')