diff options
Diffstat (limited to '')
| -rw-r--r-- | src/main.rs | 163 | 
1 files changed, 72 insertions, 91 deletions
| diff --git a/src/main.rs b/src/main.rs index a1ee3c1..cb8c5f1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -243,6 +243,29 @@ enum Logic {  }  impl Logic { +    fn gate(&self) -> &'static str { +        match self { +            Logic::Not(_) => "NOT", +            Logic::And(_) => "AND", +            Logic::Or(_) => "OR", +            Logic::Nand(_) => "NAND", +            Logic::Nor(_) => "NOR", + +            _ => panic!("Cannot take gate name out of logic"), +        } +    } + +    fn input_count(&self) -> usize { +        match self { +            Logic::Not(_) => 1, +            Logic::And(logics) | Logic::Or(logics) | Logic::Nand(logics) | Logic::Nor(logics) => { +                logics.len() +            } + +            _ => panic!("Cannot take gate name out of logic"), +        } +    } +      fn inverse(&self) -> Self {          match self {              Logic::Constant(v) => Logic::Constant(!*v), @@ -498,6 +521,19 @@ impl<'input> From<&'input str> for ChipSeries<'input> {      }  } +fn pick_chip_by_logic<'input>( +    series: &ChipSeries<'input>, +    gate: &str, +    inputs: usize, +) -> Option<&'input str> { +    if let Some(chip) = series.logic_to_chip.get(&(gate, inputs)) { +        Some(*chip) +    } else { +        // todo!() +        None +    } +} +  fn logic_to_chips<'input>(      logic: &Logic,      series: &ChipSeries<'input>, @@ -511,7 +547,7 @@ fn logic_to_chips<'input>(              continue;          } -        let gate = match logic { +        let (gate, inputs) = match logic {              Logic::Constant(_) => continue,              Logic::Variable(_) => continue, @@ -541,7 +577,14 @@ fn logic_to_chips<'input>(              }          }; -        let chip = series.logic_to_chip[&gate]; +        let chip = match pick_chip_by_logic(series, gate, inputs) { +            Some(chip) => chip, +            _ => { +                chips.entry("Unresolved").or_insert((0, 1)).0 += 1; +                continue; +            } +        }; +          chips              .entry(chip)              .or_insert((0, series.chip_specification[chip].gate_count)) @@ -554,7 +597,7 @@ fn logic_to_chips<'input>(  fn logic_to_sequences<'input>(      logic: &Logic,      series: &ChipSeries<'input>, -) -> Vec<Vec<(&'input str, &'input str)>> { +) -> Vec<Vec<(&'input str, Option<&'input str>)>> {      let mut sequences = vec![];      let mut queue = VecDeque::from([(logic, vec![])]); @@ -564,38 +607,14 @@ fn logic_to_sequences<'input>(              Logic::Variable(_) => sequences.push(seq),              Logic::Not(logic) => { -                let chip = series.logic_to_chip[&("NOT", 1)]; +                let chip = pick_chip_by_logic(series, "NOT", 1);                  seq.push(("NOT", chip));                  queue.push_back((logic, seq));              } -            Logic::And(logics) => { -                let chip = series.logic_to_chip[&("AND", logics.len())]; -                seq.push(("AND", chip)); -                for logic in logics { -                    queue.push_back((logic, seq.clone())); -                } -            } - -            Logic::Or(logics) => { -                let chip = series.logic_to_chip[&("OR", logics.len())]; -                seq.push(("OR", chip)); -                for logic in logics { -                    queue.push_back((logic, seq.clone())); -                } -            } - -            Logic::Nand(logics) => { -                let chip = series.logic_to_chip[&("NAND", logics.len())]; -                seq.push(("NAND", chip)); -                for logic in logics { -                    queue.push_back((logic, seq.clone())); -                } -            } - -            Logic::Nor(logics) => { -                let chip = series.logic_to_chip[&("NOR", logics.len())]; -                seq.push(("NOR", chip)); +            Logic::And(logics) | Logic::Or(logics) | Logic::Nand(logics) | Logic::Nor(logics) => { +                let chip = pick_chip_by_logic(series, logic.gate(), logic.input_count()); +                seq.push((logic.gate(), chip));                  for logic in logics {                      queue.push_back((logic, seq.clone()));                  } @@ -607,12 +626,13 @@ fn logic_to_sequences<'input>(  }  fn sequence_to_delay<'input>( -    sequence: &[(&'input str, &'input str)], +    sequence: &[(&'input str, Option<&'input str>)],      series: &ChipSeries<'input>,  ) -> usize {      sequence          .iter() -        .map(|(_, chip)| series.chip_specification[chip].delay()) +        .filter(|(_, chip)| chip.is_some()) +        .map(|(_, chip)| series.chip_specification[chip.unwrap()].delay())          .sum()  } @@ -652,7 +672,7 @@ fn logic_to_input_current<'input>(              continue;          } -        let gate = match logic { +        let (gate, inputs) = match logic {              Logic::Constant(_) => continue,              Logic::Variable(_) => continue, @@ -661,28 +681,16 @@ fn logic_to_input_current<'input>(                  ("NOT", 1)              } -            Logic::And(logics) => { +            Logic::And(logics) | Logic::Or(logics) | Logic::Nand(logics) | Logic::Nor(logics) => {                  logics.iter().for_each(|logic| queue.push_back(logic)); -                ("AND", logics.len()) -            } - -            Logic::Or(logics) => { -                logics.iter().for_each(|logic| queue.push_back(logic)); -                ("OR", logics.len()) -            } - -            Logic::Nand(logics) => { -                logics.iter().for_each(|logic| queue.push_back(logic)); -                ("NAND", logics.len()) -            } - -            Logic::Nor(logics) => { -                logics.iter().for_each(|logic| queue.push_back(logic)); -                ("NOR", logics.len()) +                (logic.gate(), logic.input_count())              }          }; -        let chip = series.logic_to_chip[&gate]; +        let chip = match pick_chip_by_logic(series, gate, inputs) { +            Some(chip) => chip, +            _ => continue, +        };          let ChipInfo {              input_current_low, @@ -701,37 +709,7 @@ fn logic_to_input_current<'input>(                  }              } -            Logic::And(logics) => { -                for l in logics { -                    if let Logic::Variable(name) = l { -                        let (low, high) = consumptions.entry(name.as_str()).or_default(); -                        *low += input_current_low; -                        *high += input_current_high; -                    } -                } -            } - -            Logic::Or(logics) => { -                for l in logics { -                    if let Logic::Variable(name) = l { -                        let (low, high) = consumptions.entry(name.as_str()).or_default(); -                        *low += input_current_low; -                        *high += input_current_high; -                    } -                } -            } - -            Logic::Nand(logics) => { -                for l in logics { -                    if let Logic::Variable(name) = l { -                        let (low, high) = consumptions.entry(name.as_str()).or_default(); -                        *low += input_current_low; -                        *high += input_current_high; -                    } -                } -            } - -            Logic::Nor(logics) => { +            Logic::And(logics) | Logic::Or(logics) | Logic::Nand(logics) | Logic::Nor(logics) => {                  for l in logics {                      if let Logic::Variable(name) = l {                          let (low, high) = consumptions.entry(name.as_str()).or_default(); @@ -862,9 +840,18 @@ fn main() {              let mut total_used_consumption = 0.;              for (chip, (used, size)) in chips.into_iter().sorted() { -                let chip_info = chip_series.chip_specification[chip]; -                let chip_usage = used as f32 / size as f32; +                println!( +                    "    - {chip}: {} шт (использовано {used} элементов -> {used}/{size} = {})", +                    used.div_ceil(size), +                    used as f32 / size as f32 +                ); + +                let chip_info = match chip_series.chip_specification.get(chip) { +                    Some(info) => info, +                    None => continue, +                }; +                let chip_usage = used as f32 / size as f32;                  let chip_consumption = used.div_ceil(size) * chip_info.consumption();                  let chip_used_consumption = chip_usage * chip_info.consumption() as f32; @@ -872,12 +859,6 @@ fn main() {                  total_used_consumption += chip_used_consumption as f32;                  println!( -                    "    - {chip}: {} шт (использовано {used} элементов -> {used}/{size} = {})", -                    used.div_ceil(size), -                    used as f32 / size as f32 -                ); - -                println!(                      "      Максимальное потребление: {chip_consumption} мкВт (реальное использованное: {chip_used_consumption})"                  );              } | 
