summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.rs163
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})"
);
}