#    Copyright 2017 ARM Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import division
import csv
import re

from devlib.platform.gem5 import Gem5SimulationPlatform
from devlib.instrument import Instrument, CONTINUOUS, MeasurementsCsv
from devlib.exception import TargetError, HostError


class Gem5PowerInstrument(Instrument):
    '''
    Instrument enabling power monitoring in gem5
    '''

    mode = CONTINUOUS
    roi_label = 'power_instrument'
    
    def __init__(self, target, power_sites):
        '''
        Parameter power_sites is a list of gem5 identifiers for power values. 
        One example of such a field:
            system.cluster0.cores0.power_model.static_power
        '''
        if not isinstance(target.platform, Gem5SimulationPlatform):
            raise TargetError('Gem5PowerInstrument requires a gem5 platform')
        if not target.has('gem5stats'):
            raise TargetError('Gem5StatsModule is not loaded')
        super(Gem5PowerInstrument, self).__init__(target)

        # power_sites is assumed to be a list later
        if isinstance(power_sites, list):
            self.power_sites = power_sites
        else:
            self.power_sites = [power_sites]
        self.add_channel('sim_seconds', 'time')
        for field in self.power_sites:
            self.add_channel(field, 'power')
        self.target.gem5stats.book_roi(self.roi_label)
        self.sample_period_ns = 10000000
        self.target.gem5stats.start_periodic_dump(0, self.sample_period_ns)
        self._base_stats_dump = 0

    def start(self):
        self.target.gem5stats.roi_start(self.roi_label)

    def stop(self):
        self.target.gem5stats.roi_end(self.roi_label)
       
    def get_data(self, outfile):
        active_sites = [c.site for c in self.active_channels]
        with open(outfile, 'wb') as wfh:
            writer = csv.writer(wfh)
            writer.writerow([c.label for c in self.active_channels]) # headers
            for rec, rois in self.target.gem5stats.match_iter(active_sites, 
                    [self.roi_label], self._base_stats_dump):
                writer.writerow([float(rec[s]) for s in active_sites])
        return MeasurementsCsv(outfile, self.active_channels)
    
    def reset(self, sites=None, kinds=None, channels=None):
        super(Gem5PowerInstrument, self).reset(sites, kinds, channels)
        self._base_stats_dump = self.target.gem5stats.next_dump_no()

