use crate::protocol::eval::*; use crate::protocol::*; use crate::runtime2::*; use super::{CompCtx, CompPDL}; use super::component_ip::*; pub enum CompScheduling { Immediate, Requeue, Sleep, Exit, } /// Generic representation of a component (as viewed by a scheduler). pub(crate) trait Component { /// Called if the component is created by another component and the messages /// are being transferred between the two. fn adopt_message(&mut self, comp_ctx: &mut CompCtx, message: DataMessage); /// Called if the component receives a new message. The component is /// responsible for deciding where that messages goes. fn handle_message(&mut self, sched_ctx: &mut SchedulerCtx, comp_ctx: &mut CompCtx, message: Message); /// Called if the component's routine should be executed. The return value /// can be used to indicate when the routine should be run again. fn run(&mut self, sched_ctx: &mut SchedulerCtx, comp_ctx: &mut CompCtx) -> Result; } /// Creates a new component based on its definition. Meaning that if it is a /// user-defined component then we set up the PDL code state. Otherwise we /// construct a custom component. This does NOT take care of port and message /// management. pub(crate) fn create_component( protocol: &ProtocolDescription, definition_id: ProcedureDefinitionId, type_id: TypeId, arguments: ValueGroup, num_ports: usize ) -> Box { let definition = &protocol.heap[definition_id]; debug_assert!(definition.kind == ProcedureKind::Primitive || definition.kind == ProcedureKind::Composite); if definition.source.is_builtin() { // Builtin component let component = match definition.source { ProcedureSource::CompRandomU32 => Box::new(ComponentRandomU32::new(arguments)), _ => unreachable!(), }; return component; } else { // User-defined component let prompt = Prompt::new( &protocol.types, &protocol.heap, definition_id, type_id, arguments ); let component = CompPDL::new(prompt, num_ports); return Box::new(component); } } #[inline] pub(crate) fn port_id_from_eval(port_id: EvalPortId) -> PortId { return PortId(port_id.id); } #[inline] pub(crate) fn port_id_to_eval(port_id: PortId) -> EvalPortId { return EvalPortId{ id: port_id.0 }; }