started work on state reduction alcorithm
This commit is contained in:
commit
143d92f68f
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
target/
|
||||
.vscode/
|
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal file
|
@ -0,0 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "state-machine-creator"
|
||||
version = "0.1.0"
|
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "state-machine-creator"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
145
src/flowtable.rs
Normal file
145
src/flowtable.rs
Normal file
|
@ -0,0 +1,145 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use crate::statematrix::StateMatrix;
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub enum FlowTableValue {
|
||||
#[default] DontCare,
|
||||
Value(usize)
|
||||
}
|
||||
|
||||
impl FlowTableValue {
|
||||
fn is_dont_care(&self) -> bool {
|
||||
match self {
|
||||
Self::DontCare => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn unwrap(&self) -> usize {
|
||||
match self {
|
||||
Self::DontCare => panic!("Unwrapped dont care value"),
|
||||
Self::Value(x) => *x
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FlowTableValue {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::DontCare => write!(f, "-"),
|
||||
Self::Value(val) => write!(f, "{val}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for FlowTableValue {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match self {
|
||||
Self::DontCare => true,
|
||||
|
||||
Self::Value(left) => match other {
|
||||
Self::DontCare => true,
|
||||
Self::Value(right) => left == right
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for FlowTableValue {}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
struct FlowTableEntry {
|
||||
to: FlowTableValue,
|
||||
output: FlowTableValue
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FlowTable {
|
||||
entries: Vec<FlowTableEntry>,
|
||||
num_states: usize,
|
||||
num_inputs: usize
|
||||
}
|
||||
|
||||
impl FlowTable {
|
||||
pub fn new(num_states: usize, num_inputs: usize) -> FlowTable {
|
||||
FlowTable {
|
||||
entries: vec![FlowTableEntry::default(); num_states * num_inputs],
|
||||
num_states: num_states,
|
||||
num_inputs: num_inputs
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_entry(&mut self, state: usize, input: usize, next_state: FlowTableValue, output: FlowTableValue) {
|
||||
self.entries[state * self.num_inputs + input] = FlowTableEntry {
|
||||
to: next_state,
|
||||
output: output
|
||||
}
|
||||
}
|
||||
|
||||
fn add_rows_to_matrix(&self, matrix: &mut StateMatrix, first_row: usize, second_row: usize) {
|
||||
for input in 0..self.num_inputs {
|
||||
let left = &self.entries[first_row * self.num_inputs + input];
|
||||
let right = &self.entries[second_row * self.num_inputs + input];
|
||||
|
||||
if left.output != right.output {
|
||||
matrix.set_incompatible(first_row, second_row)
|
||||
} else {
|
||||
if left.output.is_dont_care() || right.output.is_dont_care() ||
|
||||
left.to.is_dont_care() || right.to.is_dont_care() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if left.output.unwrap() == left.output.unwrap() && left.to.unwrap() != right.to.unwrap() {
|
||||
matrix.add_pair(first_row, second_row, (left.to.unwrap(), right.to.unwrap()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reduce(self) -> FlowTable {
|
||||
let mut matrix = StateMatrix::new(self.num_states);
|
||||
|
||||
for first in 0..self.num_states {
|
||||
for second in (first + 1)..self.num_states {
|
||||
self.add_rows_to_matrix(&mut matrix, first, second)
|
||||
}
|
||||
}
|
||||
|
||||
dbg!(matrix);
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FlowTable {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, " |")?;
|
||||
for i in 0..self.num_inputs {
|
||||
write!(f, "| {} ", char::from_digit((i + 10) as u32, 36).unwrap().to_ascii_uppercase())?;
|
||||
}
|
||||
writeln!(f)?;
|
||||
|
||||
write!(f, "-----+")?;
|
||||
for _ in 0..self.num_inputs {
|
||||
write!(f, "+-----")?;
|
||||
}
|
||||
writeln!(f)?;
|
||||
|
||||
for state in 0..self.num_states {
|
||||
write!(f, " {state} |")?;
|
||||
for i in 0..self.num_inputs {
|
||||
write!(f, "| {},{} ", self.entries[state * self.num_inputs + i].to, self.entries[state * self.num_inputs + i].output)?;
|
||||
}
|
||||
writeln!(f)?;
|
||||
|
||||
write!(f, "-----+")?;
|
||||
for _ in 0..self.num_inputs {
|
||||
write!(f, "+-----")?;
|
||||
}
|
||||
writeln!(f)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
40
src/main.rs
Normal file
40
src/main.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
use flowtable::{FlowTable, FlowTableValue};
|
||||
|
||||
mod statematrix;
|
||||
mod flowtable;
|
||||
|
||||
fn main() {
|
||||
let mut flowtable = FlowTable::new(5, 4);
|
||||
|
||||
flowtable.set_entry(0, 0, FlowTableValue::Value(1), FlowTableValue::Value(0));
|
||||
flowtable.set_entry(0, 1, FlowTableValue::DontCare, FlowTableValue::Value(1));
|
||||
flowtable.set_entry(0, 2, FlowTableValue::Value(2), FlowTableValue::DontCare);
|
||||
flowtable.set_entry(0, 3, FlowTableValue::Value(1), FlowTableValue::Value(0));
|
||||
|
||||
flowtable.set_entry(1, 0, FlowTableValue::Value(2), FlowTableValue::Value(0));
|
||||
flowtable.set_entry(1, 1, FlowTableValue::Value(4), FlowTableValue::Value(1));
|
||||
flowtable.set_entry(1, 2, FlowTableValue::Value(1), FlowTableValue::Value(0));
|
||||
flowtable.set_entry(1, 3, FlowTableValue::DontCare, FlowTableValue::DontCare);
|
||||
|
||||
flowtable.set_entry(2, 0, FlowTableValue::Value(2), FlowTableValue::Value(0));
|
||||
flowtable.set_entry(2, 1, FlowTableValue::Value(3), FlowTableValue::Value(1));
|
||||
flowtable.set_entry(2, 2, FlowTableValue::DontCare, FlowTableValue::DontCare);
|
||||
flowtable.set_entry(2, 3, FlowTableValue::Value(4), FlowTableValue::Value(0));
|
||||
|
||||
flowtable.set_entry(3, 0, FlowTableValue::DontCare, FlowTableValue::DontCare);
|
||||
flowtable.set_entry(3, 1, FlowTableValue::Value(0), FlowTableValue::Value(1));
|
||||
flowtable.set_entry(3, 2, FlowTableValue::Value(1), FlowTableValue::DontCare);
|
||||
flowtable.set_entry(3, 3, FlowTableValue::DontCare, FlowTableValue::DontCare);
|
||||
|
||||
flowtable.set_entry(4, 0, FlowTableValue::DontCare, FlowTableValue::DontCare);
|
||||
flowtable.set_entry(4, 1, FlowTableValue::DontCare, FlowTableValue::DontCare);
|
||||
flowtable.set_entry(4, 2, FlowTableValue::Value(1), FlowTableValue::Value(1));
|
||||
flowtable.set_entry(4, 3, FlowTableValue::DontCare, FlowTableValue::DontCare);
|
||||
|
||||
println!("original:");
|
||||
println!("{flowtable}");
|
||||
flowtable = flowtable.reduce();
|
||||
|
||||
println!("reduced:");
|
||||
println!("{flowtable}");
|
||||
}
|
49
src/statematrix.rs
Normal file
49
src/statematrix.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
#[derive(Debug, Clone)]
|
||||
enum Entry {
|
||||
Incompatible,
|
||||
Implications(Vec<(usize, usize)>)
|
||||
}
|
||||
|
||||
impl Default for Entry {
|
||||
fn default() -> Self {
|
||||
Entry::Implications(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct StateMatrix {
|
||||
entries: Vec<Entry>,
|
||||
width: usize
|
||||
}
|
||||
|
||||
impl StateMatrix {
|
||||
pub fn new(num_states: usize) -> StateMatrix {
|
||||
let matrix_width = num_states - 1;
|
||||
|
||||
StateMatrix {
|
||||
width: matrix_width,
|
||||
entries: vec![Entry::default(); num_states * (num_states - 1) / 2]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_pair(&mut self, first: usize, second: usize, pair: (usize, usize)) {
|
||||
let index = second * (second - 1) / 2 + first;
|
||||
|
||||
match &mut self.entries[index] {
|
||||
Entry::Implications(pairs) => {
|
||||
pairs.push(pair);
|
||||
return;
|
||||
},
|
||||
|
||||
Entry::Incompatible => {}
|
||||
}
|
||||
|
||||
self.entries[index] = Entry::Implications(vec![pair]);
|
||||
}
|
||||
|
||||
pub fn set_incompatible(&mut self, first: usize, second: usize) {
|
||||
let index = second * (second - 1) / 2 + first;
|
||||
|
||||
self.entries[index] = Entry::Incompatible;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue