pub mod pin;
pub mod pin_group;
pub mod pin_header;
pub mod pin_store;
use super::super::dut::Dut;
use crate::error::Error;
use crate::generator::ast::Node;
use crate::standards::actions::*;
use crate::testers::vector_based::api::{cycle, repeat, repeat2, repeat2_node};
use crate::{node, Transaction, TEST};
use regex::Regex;
use super::Model;
use indexmap::IndexMap;
use pin::{Pin, PinAction, ResolvePinActions};
use pin_group::PinGroup;
use pin_store::PinStore;
pub type PinGroupIdendifer = (usize, String);
#[derive(Debug, Clone)]
pub struct PinCollection<'a> {
grp_ids: Option<Vec<(usize, usize)>>,
pins: Vec<&'a Pin>,
}
impl<'a> PinCollection<'a> {
pub fn from_group(dut: &'a crate::Dut, grp_name: &str, model_id: usize) -> crate::Result<Self> {
let pins = dut._resolve_to_flattened_pins(&vec![(model_id, grp_name.to_string())])?;
Ok(Self {
grp_ids: Some(vec![(
dut._get_pin_group(model_id, grp_name)?.id,
pins.len(),
)]),
pins: pins,
})
}
pub fn from_pin_store(dut: &'a crate::Dut, ps: &PinStore) -> crate::Result<Self> {
Ok(Self {
grp_ids: None,
pins: ps.pin_ids.iter().map(|id| &dut.pins[*id]).collect(),
})
}
pub fn from_pin_group(dut: &'a crate::Dut, grp: &PinGroup) -> crate::Result<Self> {
Ok(Self {
grp_ids: Some(vec![(grp.id, grp.pin_ids.len())]),
pins: grp.pin_ids.iter().map(|id| &dut.pins[*id]).collect(),
})
}
pub fn pin_names(&self) -> Vec<String> {
self.pins.iter().map(|p| p.name.to_string()).collect()
}
pub fn contains_group_identifier(
&self,
dut: &Dut,
id: PinGroupIdendifer,
) -> crate::Result<bool> {
let grp = dut._get_pin_group(id.0, &id.1)?;
Ok(self.contains(&grp.pin_ids))
}
pub fn as_ids(&self) -> Vec<usize> {
self.pins.iter().map(|p| p.id).collect()
}
fn contains(&self, query_ids: &Vec<usize>) -> bool {
let p_ids = self.as_ids();
if query_ids.len() == 0 {
return false;
}
if let Some(pos) = p_ids.iter().position(|&i| i == *query_ids.first().unwrap()) {
for (idx, id) in query_ids[1..].iter().enumerate() {
if *id != p_ids[pos + idx] {
return false;
}
}
true
} else {
false
}
}
pub fn drive_high(&self) -> &Self {
TEST.append(&mut self.drive_high_nodes());
&self
}
pub fn drive_high_nodes(&self) -> Vec<Node> {
self.drive_nodes(true)
}
pub fn drive_low(&self) -> &Self {
TEST.append(&mut self.drive_low_nodes());
&self
}
pub fn drive_low_nodes(&self) -> Vec<Node> {
self.drive_nodes(false)
}
pub fn drive(&self, state: bool) -> &Self {
TEST.append(&mut self.drive_nodes(state));
&self
}
pub fn drive_nodes(&self, state: bool) -> Vec<Node> {
if state {
self.set_action_nodes(DRIVE_HIGH)
} else {
self.set_action_nodes(DRIVE_LOW)
}
}
pub fn verify_high(&self) -> &Self {
TEST.append(&mut self.verify_high_nodes());
&self
}
pub fn verify_high_nodes(&self) -> Vec<Node> {
self.verify_nodes(true)
}
pub fn verify_low(&self) -> &Self {
TEST.append(&mut self.verify_low_nodes());
&self
}
pub fn verify_low_nodes(&self) -> Vec<Node> {
self.verify_nodes(false)
}
pub fn verify(&self, state: bool) -> &Self {
TEST.append(&mut self.verify_nodes(state));
&self
}
pub fn verify_nodes(&self, state: bool) -> Vec<Node> {
if state {
self.set_action_nodes(VERIFY_HIGH)
} else {
self.set_action_nodes(VERIFY_LOW)
}
}
pub fn capture(&self) -> &Self {
TEST.append(&mut self.capture_nodes());
&self
}
pub fn capture_nodes(&self) -> Vec<Node> {
self.set_action_nodes(CAPTURE)
}
pub fn highz(&self) -> &Self {
TEST.append(&mut self.highz_nodes());
&self
}
pub fn highz_nodes(&self) -> Vec<Node> {
self.set_action_nodes(HIGHZ)
}
pub fn set_action(&self, action: &str) -> &Self {
TEST.append(&mut self.set_action_nodes(action));
&self
}
pub fn set_actions<T: AsRef<str> + std::fmt::Display>(
&self,
actions: &Vec<T>,
) -> crate::Result<&Self> {
if actions.len() != self.pins.len() {
return Err(Error::new(&format!(
"Error in PinCollection (set_actions): Expected length of actions ({}) to equal length of pin collection ({})",
actions.len(),
self.pins.len()
)));
}
for (i, a) in actions.iter().enumerate() {
let p = &self.pins[i];
let mut paction = p.action.write().unwrap();
*paction = PinAction::new(a);
TEST.push(node!(PinAction, p.id, a.to_string(), None));
}
Ok(&self)
}
pub fn set_action_nodes(&self, action: &str) -> Vec<Node> {
if let Some(grps) = &self.grp_ids {
let mut retn = vec![];
let mut pin_ids_offset = 0;
for (_i, grp) in grps.iter().enumerate() {
let mut grp_node = node!(
PinGroupAction,
grp.0,
vec![action.to_string(); self.pins.len()],
None
);
grp_node.add_children(
(0..grp.1)
.map(|pin_i| {
let p = &self.pins[pin_ids_offset + pin_i];
let mut paction = p.action.write().unwrap();
*paction = PinAction::new(action);
node!(PinAction, p.id, action.to_string(), None)
})
.collect(),
);
retn.push(grp_node);
pin_ids_offset += grp.1;
}
retn
} else {
self.pins
.iter()
.map(|p| {
let mut paction = p.action.write().unwrap();
*paction = PinAction::new(action);
node!(PinAction, p.id, action.to_string(), None)
})
.collect()
}
}
pub fn set_from_transaction(&self, trans: &Transaction) -> crate::Result<&Self> {
TEST.append(&mut self.set_from_transaction_nodes(trans)?);
Ok(&self)
}
pub fn set_from_transaction_nodes(&self, trans: &Transaction) -> crate::Result<Vec<Node>> {
self.verify_size(trans)?;
let bit_actions = trans.to_symbols()?;
self.update_from_bit_actions(&bit_actions)
}
pub fn get_actions(&self) -> Vec<PinAction> {
self.pins
.iter()
.map(|p| p.action.read().unwrap().clone())
.collect()
}
pub fn get_reset_actions(&self) -> Vec<PinAction> {
self.pins
.iter()
.map(|p| {
if let Some(ra) = &p.reset_action {
ra.clone()
} else {
PinAction::highz()
}
})
.collect()
}
pub fn reset(&self) -> &Self {
self.pins.iter().for_each(|p| {
let a;
if let Some(ra) = &p.reset_action {
a = ra.clone();
} else {
a = PinAction::highz();
}
let mut paction = p.action.write().unwrap();
*paction = a.clone();
TEST.push(node!(PinAction, p.id, a.to_string(), None));
});
&self
}
fn verify_size(&self, trans: &Transaction) -> crate::Result<()> {
if trans.width != self.pins.len() {
Err(Error::new(&format!(
"Error in PinCollection: Transaction of width {} does not match PinCollection size {}. PC: {:?}, Transaction: {:?}",
trans.width,
self.pins.len(),
self,
trans
)))
} else {
Ok(())
}
}
fn update_from_bit_actions(&self, bit_actions: &Vec<String>) -> crate::Result<Vec<Node>> {
let mut action_nodes: Vec<Node> = vec![];
let mut this_grp_nodes: Vec<Node> = vec![];
let mut this_grp_action: Vec<String> = vec![];
let mut current_cnt = 0;
let mut grp_idx = 0;
for (i, bit_action) in bit_actions.iter().enumerate() {
if self.grp_ids.is_some() {
let p = &self.pins[i];
this_grp_nodes.push(node!(PinAction, p.id, bit_action.to_string(), None));
this_grp_action.push(bit_action.to_string());
let mut paction = p.action.write().unwrap();
*paction = PinAction::new(bit_action);
current_cnt += 1;
if current_cnt == self.grp_ids.as_ref().unwrap()[grp_idx].1 {
let mut n = node!(
PinGroupAction,
self.grp_ids.as_ref().unwrap()[grp_idx].0,
this_grp_action,
None
);
n.add_children(this_grp_nodes);
action_nodes.push(n);
this_grp_nodes = vec![];
grp_idx += 1;
current_cnt = 0;
this_grp_action = vec![];
}
} else {
let p = &self.pins[i];
let mut paction = p.action.write().unwrap();
*paction = PinAction::new(bit_action);
action_nodes.push(node!(PinAction, p.id, bit_action.to_string(), None));
}
}
Ok(action_nodes)
}
pub fn push_transaction(&self, trans: &Transaction) -> crate::Result<&Self> {
TEST.append(&mut self.push_transaction_nodes(trans)?);
Ok(&self)
}
pub fn push_transaction_nodes(&self, trans: &Transaction) -> crate::Result<Vec<Node>> {
let bit_actions = trans.to_symbols()?;
let mut pin_states: Vec<Node> = vec![];
for (_idx, chunk) in bit_actions.chunks(self.pins.len()).enumerate() {
let mut this_cycle: Vec<Node> = vec![];
let mut this_grp_nodes: Vec<Node> = vec![];
let mut this_grp_action: Vec<String> = vec![];
let mut current_cnt = 0;
let mut grp_idx = 0;
for (pos, bit_action) in chunk.iter().enumerate() {
if self.grp_ids.is_some() {
let p = &self.pins[pos];
this_grp_nodes.push(node!(PinAction, p.id, bit_action.to_string(), None));
this_grp_action.push(bit_action.to_string());
let mut paction = p.action.write().unwrap();
*paction = PinAction::new(bit_action);
current_cnt += 1;
if current_cnt == self.grp_ids.as_ref().unwrap()[grp_idx].1 {
let mut n = node!(
PinGroupAction,
self.grp_ids.as_ref().unwrap()[grp_idx].0,
this_grp_action,
None
);
n.add_children(this_grp_nodes);
this_cycle.push(n);
this_grp_nodes = vec![];
grp_idx += 1;
current_cnt = 0;
this_grp_action = vec![];
}
} else {
let p = &self.pins[pos];
let mut paction = p.action.write().unwrap();
*paction = PinAction::new(bit_action);
this_cycle.push(node!(PinAction, p.id, bit_action.to_string(), None));
}
}
pin_states.append(&mut this_cycle);
pin_states.push(repeat2_node(1, !trans.overlay_string.is_some()));
}
Ok(pin_states)
}
pub fn cycle(&self) -> &Self {
cycle();
&self
}
pub fn cycles(&self, count: usize) -> &Self {
self.repeat(count as u32)
}
pub fn repeat(&self, count: u32) -> &Self {
repeat(count);
&self
}
pub fn repeat2(&self, count: u32, compressable: bool) -> &Self {
repeat2(count, compressable);
&self
}
}
#[derive(Debug, Copy, Clone)]
pub enum Endianness {
LittleEndian,
BigEndian,
}
impl Model {
pub fn register_pin(
&mut self,
pin_group_id: usize,
physical_pin_id: usize,
name: &str,
reset_action: Option<PinAction>,
endianness: Option<Endianness>,
) -> Result<(PinGroup, Pin), Error> {
let pin_group = PinGroup::new(
self.id,
pin_group_id,
name,
vec![physical_pin_id],
endianness,
);
let physical_pin = Pin::new(self.id, physical_pin_id, name.to_string(), reset_action);
self.pin_groups.insert(name.to_string(), pin_group_id);
self.pins.insert(name.to_string(), physical_pin_id);
Ok((pin_group, physical_pin))
}
pub fn register_pin_group(
&mut self,
pin_group_id: usize,
name: &str,
pin_ids: Vec<usize>,
endianness: Option<Endianness>,
) -> Result<PinGroup, Error> {
let pin_group = PinGroup::new(
self.id,
pin_group_id,
&name.to_string(),
pin_ids,
endianness,
);
self.pin_groups.insert(name.to_string(), pin_group_id);
Ok(pin_group)
}
pub fn get_pin_id(&self, name: &str) -> Option<usize> {
match self.pins.get(name) {
Some(t) => Some(*t),
None => None,
}
}
pub fn get_pin_group_id(&self, name: &str) -> Option<usize> {
match self.pin_groups.get(name) {
Some(t) => Some(*t),
None => None,
}
}
}
impl Dut {
pub fn add_pin(
&mut self,
model_id: usize,
name: &str,
width: Option<u32>,
offset: Option<u32>,
reset_action: Option<Vec<PinAction>>,
endianness: Option<Endianness>,
) -> Result<&PinGroup, Error> {
if !width.is_some() && offset.is_some() {
return Err(Error::new(&format!(
"Can not add pin {} with a given offset but no width option!",
name
)));
} else if self.get_pin_group(model_id, name).is_some() {
return Err(Error::new(&format!(
"Pin '{}' already exists on model '{}'!",
name, self.models[model_id].name
)));
}
if let Some(ref r) = reset_action {
if r.len() != (width.unwrap_or(1) as usize) {
return Err(Error::new(&format!(
"PinActions of length {} must match width {}!",
r.len(),
width.unwrap_or(1)
)));
}
}
let mut names: Vec<String> = vec![];
if let Some(w) = width {
if w < 1 {
return Err(Error::new(&format!(
"Width cannot be less than 1! Received {}",
w
)));
}
let o = offset.unwrap_or(0);
for i in o..(o + w) {
let n = format!("{}{}", name, i).to_string();
if self.get_pin_group(model_id, name).is_some() {
return Err(Error::new(&format!(
"Can not add pin {}, derived by adding pin {} of width {} with offset {}, because it conflicts with a current pin or alias name!",
n,
name,
w,
o,
)));
}
names.push(n);
}
} else {
names.push(name.to_string());
}
let (mut pin_group_id, mut physical_pin_id);
{
pin_group_id = self.pin_groups.len();
physical_pin_id = self.pins.len();
}
{
let model = &mut self.models[model_id];
let mut ra = None;
for (i, n) in names.iter().enumerate() {
if let Some(ref r) = reset_action {
ra = Some(r[i].clone());
}
let (pin_group, mut physical_pin) = model.register_pin(
pin_group_id,
physical_pin_id,
&n,
ra.clone(),
endianness,
)?;
if names.len() > 1 {
physical_pin.groups.insert(name.to_string(), i);
}
self.pin_groups.push(pin_group);
self.pins.push(physical_pin);
pin_group_id += 1;
physical_pin_id += 1;
}
}
if offset.is_some() || width.is_some() {
self.group_pins_by_name(model_id, name, names, endianness)?;
Ok(&self.pin_groups[pin_group_id])
} else {
Ok(&self.pin_groups[pin_group_id - 1])
}
}
pub fn add_pin_alias(&mut self, model_id: usize, name: &str, alias: &str) -> Result<(), Error> {
if self.models[model_id].pin_groups.contains_key(alias) {
return Err(Error::new(&format!(
"Could not alias '{}' to '{}', as '{}' already exists!",
name, alias, alias
)));
}
let (grp, id, ids);
if let Some(idx) = self.models[model_id].pin_groups.get(name) {
id = self.pin_groups.len();
let p = &self.pin_groups[*idx];
grp = PinGroup::new(
model_id,
id,
alias,
p.pin_ids.clone(),
Option::Some(p.endianness),
);
ids = p.pin_ids.clone();
} else {
return Err(Error::new(&format!(
"Could not alias '{}' to '{}', as '{}' doesn't exists!",
name, alias, name
)));
}
for pid in ids {
let p = &mut self.pins[pid];
p.aliases.push(alias.to_string())
}
self.models[model_id]
.pin_groups
.insert(alias.to_string(), id);
self.pin_groups.push(grp);
Ok(())
}
pub fn group_pins_by_name(
&mut self,
model_id: usize,
name: &str,
pins: Vec<String>,
endianness: Option<Endianness>,
) -> Result<&PinGroup, Error> {
let id;
{
id = self.pin_groups.len();
}
let pnames = self.verify_names(model_id, &pins)?;
for (i, pname) in pnames.iter().enumerate() {
let p = self._get_mut_pin(model_id, pname)?;
p.groups.insert(String::from(name), i);
}
let ids = pnames
.iter()
.map(|p| self._get_pin(model_id, p).unwrap().id)
.collect();
let model = &mut self.models[model_id];
self.pin_groups
.push(model.register_pin_group(id, name, ids, endianness)?);
Ok(&self.pin_groups[id])
}
pub fn verify_names(&self, model_id: usize, names: &Vec<String>) -> Result<Vec<String>, Error> {
let mut physical_names: Vec<String> = vec![];
for (_i, pin_name) in names.iter().enumerate() {
if pin_name.starts_with("/") && pin_name.ends_with("/") {
let mut regex_str = pin_name.clone();
regex_str.pop();
regex_str.remove(0);
let regex = Regex::new(®ex_str).unwrap();
let mut _pin_names: Vec<String> = vec![];
for (name_str, grp_id) in self.models[model_id].pin_groups.iter() {
if regex.is_match(name_str) {
let grp = &self.pin_groups[*grp_id];
let n = grp
.pin_ids
.iter()
.map(|pid| self.pins[*pid].name.to_string())
.collect::<Vec<String>>();
for _name_str in n.iter() {
if physical_names.contains(_name_str) {
return Err(Error::new(&format!("Can not collect pin '{}' from regex /{}/ because it (or an alias of it) has already been collected (resolves to physical pin '{}')!", name_str, regex_str, _name_str)));
}
}
_pin_names.extend(n);
}
}
_pin_names.sort();
physical_names.extend(_pin_names);
} else if let Some(p) = self.resolve_to_physical_pin(model_id, pin_name) {
if physical_names.contains(&p.name) {
return Err(Error::new(&format!("Can not collect pin '{}' because it (or an alias of it) has already been collected (resolves to physical pin '{}')!", pin_name, p.name)));
}
if let Some(p) = self.get_pin_group(model_id, pin_name) {
let n = p
.pin_ids
.iter()
.map(|pid| self.pins[*pid].name.clone())
.collect::<Vec<String>>();
physical_names.extend_from_slice(&n);
}
} else {
return Err(Error::new(&format!(
"Can not collect pin '{}' because it does not exist!",
pin_name
)));
}
}
Ok(physical_names.clone())
}
pub fn collect_grp_ids_as_pin_ids(
&self,
grps: &Vec<(String, usize)>,
) -> crate::Result<Vec<usize>> {
let mut physical_ids: Vec<usize> = vec![];
for (_i, identifier) in grps.iter().enumerate() {
if identifier.0.starts_with("/") && identifier.0.ends_with("/") {
let mut regex_str = identifier.0.clone();
regex_str.pop();
regex_str.remove(0);
let regex = Regex::new(®ex_str).unwrap();
let mut _pin_names: Vec<usize> = vec![];
for (name_str, grp_id) in self.models[identifier.1].pin_groups.iter() {
if regex.is_match(name_str) {
let grp = &self.pin_groups[*grp_id];
for pid in grp.pin_ids.iter() {
if physical_ids.contains(&pid) {
return Err(Error::new(&format!(
"Can not collect pin '{}' from regex /{}/ because it (or an alias of it) has already been collected (resolves to physical pin '{}')!",
name_str,
regex_str,
&self.pins[*pid].name
)));
}
}
_pin_names.extend(&grp.pin_ids.clone());
}
}
_pin_names.sort();
physical_ids.extend(_pin_names);
} else if let Some(p) = self.resolve_to_physical_pin(identifier.1, &identifier.0) {
if physical_ids.contains(&p.id) {
return Err(Error::new(&format!("Can not collect pin '{}' because it (or an alias of it) has already been collected (resolves to physical pin '{}')!", identifier.0, p.name)));
}
if let Some(p) = self.get_pin_group(identifier.1, &identifier.0) {
physical_ids.extend(&p.pin_ids.clone());
}
} else {
return Err(Error::new(&format!(
"Can not collect pin '{}' because it does not exist!",
identifier.0
)));
}
}
Ok(physical_ids.clone())
}
pub fn collect(
&self,
grps: &Vec<(String, usize)>,
endianness: Option<Endianness>,
) -> Result<PinStore, Error> {
let pids = self.collect_grp_ids_as_pin_ids(grps)?;
Ok(PinStore::new(pids, endianness))
}
pub fn pin_names_contain(
&self,
model_id: usize,
names: &Vec<String>,
query_name: &str,
) -> Result<bool, Error> {
let result = self.find_in_names(model_id, names, query_name)?.is_some();
Ok(result)
}
pub fn find_in_names(
&self,
model_id: usize,
names: &Vec<String>,
query_name: &str,
) -> Result<Option<usize>, Error> {
if let Some(p) = self.get_pin(model_id, query_name) {
let idx = names
.iter()
.position(|name| p.name == *name || p.aliases.contains(name));
if let Some(_idx) = idx {
Ok(Option::Some(_idx))
} else {
Ok(Option::None)
}
} else {
Err(Error::new(&format!(
"The query name {} does not exists! Cannot check this query's groups!",
query_name
)))
}
}
pub fn index_of(
&self,
model_id: usize,
name: &str,
query_name: &str,
) -> Result<Option<usize>, Error> {
if !self.models[model_id].pin_groups.contains_key(name) {
return Err(Error::new(&format!(
"Group {} does not exists! Cannot lookup index for {} in this group!",
name, query_name
)));
}
if let Some(p) = self.get_pin(model_id, query_name) {
if let Some(idx) = p.groups.get(name) {
Ok(Option::Some(*idx))
} else {
Ok(Option::None)
}
} else {
Err(Error::new(&format!(
"The query name {} does not exists! Cannot check this query's groups!",
query_name
)))
}
}
pub fn resolve_to_physical_pin(&self, model_id: usize, name: &str) -> Option<&Pin> {
if let Some(grp) = self.get_pin_group(model_id, name) {
return Some(&self.pins[grp.pin_ids[0]]);
}
Option::None
}
pub fn data_fits_in_pins(&mut self, pins: &Vec<String>, data: u32) -> Result<(), Error> {
let two: u32 = 2;
if data > (two.pow(pins.len() as u32) - 1) {
Err(Error::new(&format!(
"Data {} does not fit in Pin collection of size {} - Cannot set data!",
data,
pins.len()
)))
} else {
Ok(())
}
}
pub fn verify_data_fits(&mut self, width: u32, data: u32) -> Result<(), Error> {
let two: u32 = 2;
if data > (two.pow(width) - 1) {
Err(Error::new(&format!(
"Data {} does not fit in pins with width of {}!",
data, width
)))
} else {
Ok(())
}
}
pub fn verify_action_string_fits(
&self,
width: u32,
action_string: &Vec<u8>,
) -> Result<(), Error> {
if action_string.len() != (width as usize) {
Err(Error::new(&format!(
"Action string of length {} must match width {}!",
action_string.len(),
width
)))
} else {
Ok(())
}
}
pub fn pin_group_contains(
&self,
model_id: usize,
name: &str,
query_name: &str,
) -> Result<bool, Error> {
let result = self.index_of(model_id, name, query_name)?.is_some();
Ok(result)
}
pub fn contains(&self, model_id: usize, name: &str) -> bool {
return self.get_pin_group(model_id, name).is_some();
}
pub fn _contains(&self, model_id: usize, name: &str) -> bool {
return self.get_pin(model_id, name).is_some();
}
pub fn _resolve_group_to_physical_pins(
&self,
model_id: usize,
name: &str,
) -> Result<Vec<&Pin>, Error> {
let mut retn: Vec<&Pin> = vec![];
let grp = self._get_pin_group(model_id, name)?;
for p_id in grp.pin_ids.iter() {
retn.push(&self.pins[*p_id]);
}
Ok(retn)
}
pub fn _resolve_groups_to_physical_pin_ids(
&self,
pins: &Vec<(usize, String)>,
) -> Result<Vec<Vec<usize>>, Error> {
let mut retn: Vec<Vec<usize>> = vec![];
for lookup in pins.iter() {
let ppins = self._resolve_group_to_physical_pins(lookup.0, &lookup.1)?;
retn.push(ppins.iter().map(|p| p.id).collect::<Vec<usize>>());
}
Ok(retn)
}
pub fn _resolve_to_flattened_pins(
&self,
pins: &Vec<(usize, String)>,
) -> Result<Vec<&Pin>, Error> {
let mut retn: Vec<&Pin> = vec![];
for lookup in pins.iter() {
let mut ppins = self._resolve_group_to_physical_pins(lookup.0, &lookup.1)?;
retn.append(&mut ppins);
}
Ok(retn)
}
pub fn pin_group_to_ids(
&self,
model_id: usize,
pin_grp_name: &str,
) -> Result<(Vec<usize>, usize), Error> {
let p_ids: Vec<usize> = self
._resolve_group_to_physical_pins(model_id, pin_grp_name)?
.iter()
.map(|p| p.id)
.collect();
Ok((p_ids, self._get_pin_group(model_id, pin_grp_name)?.id))
}
}
#[derive(Debug, Clone)]
pub struct StateTracker {
pins: IndexMap<String, Vec<String>>,
model_id: usize,
}
impl StateTracker {
pub fn new(model_id: usize, pin_header_id: Option<usize>, dut: &Dut) -> Self {
let mut pins: IndexMap<String, Vec<String>> = IndexMap::new();
if let Some(id) = pin_header_id {
for n in dut.pin_headers[id].pin_names.iter() {
let mut states: Vec<String> = vec![];
for p in dut._resolve_group_to_physical_pins(model_id, n).unwrap() {
if let Some(r) = p.reset_action.as_ref() {
states.push(r.to_string());
} else {
states.push("Z".to_string());
}
}
pins.insert(n.clone(), states);
}
} else {
for phys in dut.pins.iter() {
if phys.model_id == 0 {
pins.insert(phys.name.clone(), {
if let Some(r) = phys.reset_action.as_ref() {
vec![r.to_string()]
} else {
vec!["Z".to_string()]
}
});
}
}
}
Self {
pins: pins,
model_id: model_id,
}
}
pub fn update(&mut self, grp_id: usize, actions: &Vec<String>, dut: &Dut) -> Result<(), Error> {
for (i, pid) in dut.pin_groups[grp_id].pin_ids.iter().enumerate() {
let p = &dut.pins[*pid];
if let Some(states) = self.pins.get_mut(&p.name) {
states[0] = actions[i].clone();
continue;
}
for (grp, offset) in p.groups.iter() {
if let Some(states) = self.pins.get_mut(grp) {
states[*offset] = actions[i].clone();
continue;
}
}
for alias in p.aliases.iter() {
if let Some(states) = self.pins.get_mut(alias) {
states[0] = actions[i].clone();
continue;
}
}
}
Ok(())
}
pub fn to_symbols(
&self,
target: String,
_dut: &Dut,
t: &super::timesets::timeset::Timeset,
) -> Result<Vec<String>, Error> {
let mut syms: Vec<String> = vec![];
for (_n, states) in self.pins.iter() {
let mut s: Vec<String> = vec![];
for action in states.iter() {
s.push(t._resolve_pin_action(target.clone(), &PinAction::new(action))?);
}
syms.push(s.join(""));
}
Ok(syms)
}
pub fn names(&self) -> Vec<String> {
self.pins
.keys()
.map(|n| n.to_string())
.collect::<Vec<String>>()
}
pub fn contains_action(&self, action: PinAction) -> bool {
for (_pin, actions) in self.pins.iter() {
if actions.iter().any(|a| a.to_string() == action.to_string()) {
return true;
}
}
false
}
}