use std::{collections::HashMap, hash::Hash, str::FromStr};
use crate::ast::{GroupComments, GroupId};
use super::logic;
#[derive(Default, Debug)]
#[derive(liberty_macros::Group)]
pub struct Statetable {
#[liberty(id)]
_id: GroupId<Self>,
#[liberty(comments)]
_comments: GroupComments<Self>,
#[liberty(undefined)]
_undefined: crate::ast::AttributeList,
#[liberty(simple)]
table: Table,
}
#[derive(Debug, Default, Clone, Hash, Eq, PartialEq)]
pub struct StatetableId {
pub input_npde: Vec<String>,
pub internal_node: Vec<String>,
}
impl crate::ast::HashedGroup for Statetable {
type Id = StatetableId;
fn title(&self) -> Vec<String> {
let id = self.id().clone();
vec![id.input_npde.join(" "), id.internal_node.join(" ")]
}
fn gen_id(&self, mut title: Vec<String>) -> Result<Self::Id, crate::ast::IdError> {
let l = title.len();
if l != 2 {
return Err(crate::ast::IdError::LengthDismatch(2, l, title));
}
let internal_node = if let Some(s) = title.pop() {
s.split_ascii_whitespace()
.map(ToString::to_string)
.collect::<Vec<String>>()
} else {
return Err(crate::ast::IdError::Other("Unkown pop error".into()));
};
let input_npde = if let Some(s) = title.pop() {
s.split_ascii_whitespace()
.map(ToString::to_string)
.collect::<Vec<String>>()
} else {
return Err(crate::ast::IdError::Other("Unkown pop error".into()));
};
Ok(Self::Id { input_npde, internal_node })
}
fn id(&self) -> GroupId<Self> {
self._id.clone()
}
}
#[derive(Default, Debug)]
pub struct Table {
pub v: Vec<(InputNodeValue, CurrentInternalNodeValue, NextInternalNodeValue)>,
}
impl std::fmt::Display for Table {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&self.v, f)
}
}
#[derive(Debug, Clone, Copy)]
#[derive(Hash, PartialEq, Eq)]
#[derive(strum_macros::EnumString, strum_macros::EnumIter)]
pub enum InputNodeValue {
#[strum(serialize = "L")]
Low,
#[strum(serialize = "H")]
High,
#[strum(serialize = "-")]
DontCare,
#[strum(serialize = "L/H")]
LowHigh,
#[strum(serialize = "H/L")]
HighLow,
#[strum(serialize = "R")]
Rise,
#[strum(serialize = "F")]
Fall,
#[strum(serialize = "~R")]
NotFall,
#[strum(serialize = "~F")]
NotRise,
}
#[derive(Debug, Clone, Copy)]
#[derive(Hash, PartialEq, Eq)]
#[derive(strum_macros::EnumString, strum_macros::EnumIter)]
pub enum CurrentInternalNodeValue {
#[strum(serialize = "L")]
Low,
#[strum(serialize = "H")]
High,
#[strum(serialize = "-")]
DontCare,
#[strum(serialize = "L/H")]
LowHigh,
#[strum(serialize = "H/L")]
HighLow,
#[strum(serialize = "X")]
Unknown,
#[strum(serialize = "N")]
Hold,
}
#[derive(Debug, Clone, Copy)]
#[derive(Hash, PartialEq, Eq)]
#[derive(strum_macros::EnumString, strum_macros::EnumIter)]
pub enum NextInternalNodeValue {
#[strum(serialize = "L")]
Low,
#[strum(serialize = "H")]
High,
#[strum(serialize = "-")]
DontCare,
#[strum(serialize = "L/H")]
LowHigh,
#[strum(serialize = "H/L")]
HighLow,
}
impl FromStr for Table {
type Err = std::fmt::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
todo!()
}
}
impl crate::ast::SimpleAttri for Table {
fn nom_parse<'a>(
i: &'a str,
line_num: &mut usize,
) -> nom::IResult<
&'a str,
Result<Self, (Self::Err, crate::ast::AttriValue)>,
nom::error::Error<&'a str>,
> {
let (input, simple_multi) = crate::ast::parser::simple_multi(i, line_num)?;
match Self::parse(simple_multi) {
Ok(s) => Ok((input, Ok(s))),
Err(e) => {
Ok((input, Err((e, crate::ast::AttriValue::Simple(simple_multi.to_string())))))
}
}
}
}
#[test]
fn statetable_test() {
let _ = crate::ast::test_parse_group::<Statetable>(
r#"(" CLK EN SE",ENL) {
table : " H L L : - : L ,\
H L H : - : H ,\
H H L : - : H ,\
H H H : - : H ,\
L - - : - : N ";
}
"#,
);
}