diff options
-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})" ); } |