use llhd::{Block, ConstTime, Entity, Module, ModuleContext, Process, Type, ValueId, ValueRef};
use num::zero;
use std::{
cmp::Ordering,
collections::{BinaryHeap, HashMap},
sync::Mutex,
};
pub struct State<'tm> {
module: &'tm Module,
context: ModuleContext<'tm>,
time: ConstTime,
signals: Vec<Signal>,
probes: HashMap<SignalRef, Vec<String>>,
scope: Scope,
insts: Vec<Mutex<Instance<'tm>>>,
events: BinaryHeap<Event>,
timed: BinaryHeap<TimedInstance>,
}
impl<'tm> State<'tm> {
pub fn new(
module: &'tm Module,
signals: Vec<Signal>,
probes: HashMap<SignalRef, Vec<String>>,
scope: Scope,
insts: Vec<Mutex<Instance<'tm>>>,
) -> State<'tm> {
State {
module: module,
context: ModuleContext::new(module),
time: ConstTime::new(zero(), zero(), zero()),
signals,
probes,
scope,
insts,
events: BinaryHeap::new(),
timed: BinaryHeap::new(),
}
}
pub fn module(&self) -> &'tm Module {
self.module
}
pub fn context(&self) -> &ModuleContext {
&self.context
}
pub fn time(&self) -> &ConstTime {
&self.time
}
pub fn set_time(&mut self, time: ConstTime) {
self.time = time
}
pub fn instances(&self) -> &[Mutex<Instance<'tm>>] {
&self.insts
}
pub fn instances_mut(&mut self) -> &mut [Mutex<Instance<'tm>>] {
&mut self.insts
}
pub fn instance(&self, ir: InstanceRef) -> &Mutex<Instance<'tm>> {
&self.insts[ir.0]
}
pub fn signal(&self, sr: SignalRef) -> &Signal {
&self.signals[sr.0]
}
pub fn signal_mut(&mut self, sr: SignalRef) -> &mut Signal {
&mut self.signals[sr.0]
}
pub fn signals(&self) -> &[Signal] {
&self.signals
}
pub fn probes(&self) -> &HashMap<SignalRef, Vec<String>> {
&self.probes
}
pub fn scope(&self) -> &Scope {
&self.scope
}
pub fn schedule_events<I>(&mut self, iter: I)
where
I: Iterator<Item = Event>,
{
let time = self.time.clone();
self.events.extend(iter.map(|i| {
assert!(i.time > time);
i
}));
}
pub fn schedule_timed<I>(&mut self, iter: I)
where
I: Iterator<Item = TimedInstance>,
{
let time = self.time.clone();
self.timed.extend(iter.map(|i| {
assert!(i.time > time);
i
}));
}
pub fn take_next_events(&mut self) -> Vec<Event> {
let mut v = Vec::new();
while self
.events
.peek()
.map(|x| x.time == self.time)
.unwrap_or(false)
{
v.push(self.events.pop().unwrap());
}
v
}
pub fn take_next_timed(&mut self) -> Vec<TimedInstance> {
let mut v = Vec::new();
while self
.timed
.peek()
.map(|x| x.time == self.time)
.unwrap_or(false)
{
v.push(self.timed.pop().unwrap());
}
v
}
pub fn next_time(&self) -> Option<ConstTime> {
use std::cmp::min;
match (
self.events.peek().map(|e| &e.time),
self.timed.peek().map(|t| &t.time),
) {
(Some(e), Some(t)) => Some(min(e, t).clone()),
(Some(e), None) => Some(e.clone()),
(None, Some(t)) => Some(t.clone()),
(None, None) => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct SignalRef(usize);
impl SignalRef {
pub fn new(id: usize) -> SignalRef {
SignalRef(id)
}
pub fn as_usize(&self) -> usize {
self.0
}
}
pub struct Signal {
ty: Type,
value: ValueRef,
}
impl Signal {
pub fn new(ty: Type, value: ValueRef) -> Signal {
Signal {
ty: ty,
value: value,
}
}
pub fn ty(&self) -> &Type {
&self.ty
}
pub fn value(&self) -> &ValueRef {
&self.value
}
pub fn set_value(&mut self, value: ValueRef) -> bool {
if self.value != value {
self.value = value;
true
} else {
false
}
}
}
pub struct Instance<'tm> {
values: HashMap<ValueId, ValueSlot>,
kind: InstanceKind<'tm>,
state: InstanceState,
inputs: Vec<SignalRef>,
outputs: Vec<SignalRef>,
}
impl<'tm> Instance<'tm> {
pub fn new(
values: HashMap<ValueId, ValueSlot>,
kind: InstanceKind<'tm>,
inputs: Vec<SignalRef>,
outputs: Vec<SignalRef>,
) -> Instance<'tm> {
Instance {
values: values,
kind: kind,
state: InstanceState::Ready,
inputs: inputs,
outputs: outputs,
}
}
pub fn state(&self) -> &InstanceState {
&self.state
}
pub fn set_state(&mut self, state: InstanceState) {
self.state = state;
}
pub fn kind(&self) -> &InstanceKind<'tm> {
&self.kind
}
pub fn kind_mut(&mut self) -> &mut InstanceKind<'tm> {
&mut self.kind
}
pub fn values(&self) -> &HashMap<ValueId, ValueSlot> {
&self.values
}
pub fn value(&self, id: ValueId) -> &ValueSlot {
self.values.get(&id).unwrap()
}
pub fn set_value(&mut self, id: ValueId, value: ValueSlot) {
self.values.insert(id, value);
}
pub fn inputs(&self) -> &[SignalRef] {
&self.inputs
}
pub fn outputs(&self) -> &[SignalRef] {
&self.outputs
}
pub fn name(&self) -> &str {
match self.kind {
InstanceKind::Process { prok, .. } => prok.name(),
InstanceKind::Entity { entity, .. } => entity.name(),
}
}
}
#[derive(Debug, Clone)]
pub enum ValueSlot {
Signal(SignalRef),
Variable(ValueRef),
Const(ValueRef),
VariablePointer(ValuePointer<ValueId>),
SignalPointer(ValuePointer<SignalRef>),
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct ValuePointer<T> {
pub target: T,
pub select: Vec<ValueSelect>,
pub discard: (usize, usize),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum ValueSelect {
Element(usize),
Slice(usize, usize),
}
pub enum InstanceKind<'tm> {
Process {
prok: &'tm Process,
next_block: Option<&'tm Block>,
},
Entity {
entity: &'tm Entity,
},
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum InstanceState {
Ready,
Wait(Option<ConstTime>, Vec<SignalRef>),
Done,
}
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct InstanceRef(usize);
impl InstanceRef {
pub fn new(id: usize) -> InstanceRef {
InstanceRef(id)
}
}
#[derive(Debug, Eq, PartialEq)]
pub struct Event {
pub time: ConstTime,
pub signal: ValuePointer<SignalRef>,
pub value: ValueRef,
}
impl Ord for Event {
fn cmp(&self, rhs: &Event) -> Ordering {
match self.time.cmp(&rhs.time) {
Ordering::Equal => self.signal.cmp(&rhs.signal),
Ordering::Greater => Ordering::Less,
Ordering::Less => Ordering::Greater,
}
}
}
impl PartialOrd for Event {
fn partial_cmp(&self, rhs: &Event) -> Option<Ordering> {
Some(self.cmp(rhs))
}
}
#[derive(Debug, Eq, PartialEq)]
pub struct TimedInstance {
pub time: ConstTime,
pub inst: InstanceRef,
}
impl Ord for TimedInstance {
fn cmp(&self, rhs: &TimedInstance) -> Ordering {
match self.time.cmp(&rhs.time) {
Ordering::Equal => self.inst.cmp(&rhs.inst),
Ordering::Greater => Ordering::Less,
Ordering::Less => Ordering::Greater,
}
}
}
impl PartialOrd for TimedInstance {
fn partial_cmp(&self, rhs: &TimedInstance) -> Option<Ordering> {
Some(self.cmp(rhs))
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Scope {
pub name: String,
pub probes: HashMap<SignalRef, Vec<String>>,
pub subscopes: Vec<Scope>,
}
impl Scope {
pub fn new(name: impl Into<String>) -> Scope {
Scope {
name: name.into(),
probes: Default::default(),
subscopes: vec![],
}
}
pub fn add_subscope(&mut self, scope: Scope) {
self.subscopes.push(scope);
}
pub fn add_probe(&mut self, signal: SignalRef, name: String) {
self.probes.entry(signal).or_insert(Vec::new()).push(name);
}
}