<commit_before>use std::path::Path;
use std::str::FromStr;
use temperature::{self, Simulator};

use platform::{Element, ElementKind, Platform, Profile, ProfileBuilder};
use schedule::Decision;
use system::Job;
use {Config, Result};

/// A platform producing power and temperature data.
pub struct Thermal {
    elements: Vec<Element>,
    simulator: Simulator,
    builder: ProfileBuilder,
}

impl Thermal {
    /// Create a platform.
    pub fn new(config: &Config) -> Result<Thermal> {
        let (elements, simulator) = try!(construct_temperature(config.branch("temperature")
                                                                     .as_ref().unwrap_or(config)));

        let builder = try!(construct_power(&elements, config.branch("power").as_ref()
                                                            .unwrap_or(config)));

        Ok(Thermal { elements: elements, simulator: simulator, builder: builder })
    }
}

impl Platform for Thermal {
    type Data = (Profile, Profile);

    #[inline(always)]
    fn elements(&self) -> &[Element] {
        &self.elements
    }

    fn next(&mut self, time: f64) -> Option<Self::Data> {
        let power = self.builder.pull(time);
        let mut temperature = power.clone_zero();
        self.simulator.next(&power, &mut temperature);
        Some((power, temperature))
    }

    fn push(&mut self, job: &Job, decision: &Decision) -> Result<()> {
        let (from, onto) = (&job.elements, &self.elements);
        for &(i, j) in &decision.mapping {
            let (from, onto) = (&from[i], &onto[j]);
            self.builder.push(onto.id, decision.start, job.time_step, &from.dynamic_power);
        }
        Ok(())
    }
}

fn construct_power(elements: &[Element], config: &Config) -> Result<ProfileBuilder> {
    use workload;

    let units = elements.len();
    let time_step = *some!(config.get::<f64>("time_step"), "a time step is required");

    let path = path!(config, "a leakage pattern is required");
    info!(target: "Platform", "Modeling leakage power based on {:?}...", &path);
    let candidates = try!(workload::Element::collect(path));

    let mut leakage_power = vec![0.0; units];
    for i in 0..units {
        if let Some(element) = candidates.iter().find(|element| element.kind == elements[i].kind) {
            leakage_power[i] = element.leakage_power;
        } else {
            raise!("cannot find leakage data for a processing element");
        }
    }

    Ok(ProfileBuilder::new(units, time_step, leakage_power))
}

fn construct_temperature(config: &Config) -> Result<(Vec<Element>, Simulator)> {
    let path = path!(config, "a thermal specification is required");
    info!(target: "Platform", "Modeling temperature based on {:?}...", &path);
    let (elements, circuit) = match path.extension() {
        Some(extension) if extension == "stk" => try!(construct_threed_ice(&path)),
        _ => raise!("the format of {:?} is unknown", &path),
    };<commit_msg>Platform: scale leakage power based on area<commit_after>use std::path::Path;
use std::str::FromStr;
use temperature::{self, Simulator};

use platform::{Element, ElementKind, Platform, Profile, ProfileBuilder};
use schedule::Decision;
use system::Job;
use {Config, Result};

/// A platform producing power and temperature data.
pub struct Thermal {
    elements: Vec<Element>,
    simulator: Simulator,
    builder: ProfileBuilder,
}

impl Thermal {
    /// Create a platform.
    pub fn new(config: &Config) -> Result<Thermal> {
        let (elements, simulator) = try!(construct_temperature(config.branch("temperature")
                                                                     .as_ref().unwrap_or(config)));

        let builder = try!(construct_power(&elements, config.branch("power").as_ref()
                                                            .unwrap_or(config)));

        Ok(Thermal { elements: elements, simulator: simulator, builder: builder })
    }
}

impl Platform for Thermal {
    type Data = (Profile, Profile);

    #[inline(always)]
    fn elements(&self) -> &[Element] {
        &self.elements
    }

    fn next(&mut self, time: f64) -> Option<Self::Data> {
        let power = self.builder.pull(time);
        let mut temperature = power.clone_zero();
        self.simulator.next(&power, &mut temperature);
        Some((power, temperature))
    }

    fn push(&mut self, job: &Job, decision: &Decision) -> Result<()> {
        let (from, onto) = (&job.elements, &self.elements);
        for &(i, j) in &decision.mapping {
            let (from, onto) = (&from[i], &onto[j]);
            self.builder.push(onto.id, decision.start, job.time_step, &from.dynamic_power);
        }
        Ok(())
    }
}

fn construct_power(elements: &[Element], config: &Config) -> Result<ProfileBuilder> {
    use workload;

    let units = elements.len();
    let time_step = *some!(config.get::<f64>("time_step"), "a time step is required");

    let path = path!(config, "a leakage pattern is required");
    info!(target: "Platform", "Modeling leakage power based on {:?}...", &path);
    let models = try!(workload::Element::collect(path));

    let mut leakage_power = vec![0.0; units];
    for (i, element) in elements.iter().enumerate() {
        if let Some(model) = models.iter().find(|model| model.kind == element.kind) {
            debug_assert!(element.area > 0.0 && model.area > 0.0);
            leakage_power[i] = (element.area / model.area) * model.leakage_power;
        } else {
            raise!("cannot find leakage data for a processing element");
        }
    }

    Ok(ProfileBuilder::new(units, time_step, leakage_power))
}

fn construct_temperature(config: &Config) -> Result<(Vec<Element>, Simulator)> {
    let path = path!(config, "a thermal specification is required");
    info!(target: "Platform", "Modeling temperature based on {:?}...", &path);
    let (elements, circuit) = match path.extension() {
        Some(extension) if extension == "stk" => try!(construct_threed_ice(&path)),
        _ => raise!("the format of {:?} is unknown", &path),
    };
{'fraction_non_alphanumeric': 0.1534921939194741, 'fraction_numerical': 0.002793755135579293, 'mean_word_length': 2.8228643216080402, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7220095', 'n_tokens_mistral': 1781, 'n_tokens_neox': 1731, 'n_words': 463}