Skip to content
Permalink
Browse files

Introduce process chains as fundamental way of connecting processes

  • Loading branch information...
kevinmehall committed Mar 18, 2018
1 parent 59b47e5 commit 06e4fa62ed60912b11c90f124c85ac01e5cc5ac3
@@ -16,17 +16,17 @@ protocol I2C() {
}

with I2C()
def read_reg(reg, val) {
def read_reg(reg, val) = {
start(ADDR_WR); data(#w, reg); start(ADDR_RD); data(#r, val); stop()
}

with I2C()
def write_reg(reg, val) {
def write_reg(reg, val) = {
start(ADDR_WR); data(#w, reg); data(#w, val); stop()
}

with I2C()
def mma84(): Seq(-4..4, -4..4, -4..4) {
def mma84() = Seq(-4..4, -4..4, -4..4) {
read_reg(WHO_AM_I, 'h2a);
write_reg(CTRL_REG1, 'h31);
write_reg(XYZ_DATA_CFG, 'h00);
@@ -8,7 +8,7 @@ protocol SPI() {
}

with Seq(#l|#h, #l|#h, #l|#h)
def spi(): SPI() {
def spi() = SPI() {
repeat <: #10 { val(#h, <: #l, <: #l) }
repeat {
on start() {}
@@ -29,4 +29,4 @@ def spi(): SPI() {
}
}

test @roundtrip(Seq(#l|#h, #l|#h, #l|#h)) {} spi() { start(); data('01011101); data('11110000); end(); start(); data('00001000); end() };
test @roundtrip(Seq(#l|#h, #l|#h, #l|#h)) {} | spi() | { start(); data('01011101); data('11110000); end(); start(); data('00001000); end() };
@@ -2,7 +2,7 @@
#[macro_use] extern crate log;
extern crate libusb;

use signalspec::{ Ctxt, Fields, Field, Connection, Process, PrimitiveDef, PrimitiveDefFields, Value, DataMode, Type };
use signalspec::{ Ctxt, Fields, Field, Connection, PrimitiveProcess, PrimitiveDef, PrimitiveDefFields, Value, DataMode, Type };

mod starfish_usb;
use starfish_usb::{ StarfishUsb, find_device };
@@ -29,7 +29,7 @@ fn u8_to_bitvec(v: u8) -> Value {

#[derive(Debug)]
struct StarfishProcess;
impl Process for StarfishProcess {
impl PrimitiveProcess for StarfishProcess {
fn run(&self, _: &mut Connection, upwards: &mut Connection) -> bool {
let context = libusb::Context::new().unwrap();
let dev = match find_device(&context, 0x59e3, 0x5555) {
@@ -6,7 +6,7 @@ extern crate ref_slice;
use std::io;
use ref_slice::ref_slice;

use signalspec::{ Connection, Process, Value, DataMode, Item, Ctxt, PrimitiveDef, PrimitiveDefFields, Fields };
use signalspec::{ Connection, PrimitiveProcess, Value, DataMode, Item, Ctxt, PrimitiveDef, PrimitiveDefFields, Fields };

/// Represent a shape as a VCD scope declaration, creating mapping from message index to VCD idcode
fn shape_to_scope(s: &Item) -> (vcd::Scope, Vec<vcd::IdCode>) {
@@ -49,7 +49,7 @@ fn shape_to_scope(s: &Item) -> (vcd::Scope, Vec<vcd::IdCode>) {

#[derive(Debug)]
struct VcdWrite(Item);
impl Process for VcdWrite {
impl PrimitiveProcess for VcdWrite {
fn run(&self, downwards: &mut Connection, upwards: &mut Connection) -> bool {
let mut c = downwards.write_bytes();
let mut w = vcd::Writer::new(&mut c);
@@ -126,7 +126,7 @@ fn shape_from_scope(s: &Item, v: &vcd::Scope) -> Vec<vcd::IdCode> {

#[derive(Debug)]
struct VcdRead(Item);
impl Process for VcdRead {
impl PrimitiveProcess for VcdRead {
fn run(&self, downwards: &mut Connection, upwards: &mut Connection) -> bool {
let mut c = io::BufReader::new(downwards.read_bytes());
let mut r = vcd::Parser::new(&mut c);
@@ -14,13 +14,21 @@ pub struct Block {

#[derive(Debug, Clone)]
pub enum Action {
Process(Vec<Process>),
Repeat(Option<SpannedExpr>, Block),
Call(String, SpannedExpr, Option<Block>),
On(String, SpannedExpr, Option<Block>),
For(Vec<(String, SpannedExpr)>, Block),
Alt(SpannedExpr, Vec<AltArm>),
}

#[derive(Debug, Clone)]
pub enum Process {
Call(String, SpannedExpr),
Seq(ProtocolRef, Block),
InferSeq(Block),
Literal(ProcessLiteralDirection, ProtocolRef, Block),
}

#[derive(Debug, Clone)]
pub struct AltArm {
pub discriminant: SpannedExpr,
@@ -38,9 +46,8 @@ pub enum ModuleEntry {
pub struct Def {
pub name: String,
pub param: SpannedExpr,
pub top: Option<ProtocolRef>,
pub bottom: ProtocolRef,
pub block: Block,
pub processes: Vec<Process>,
}

pub struct PrimitiveHeader {
@@ -91,13 +98,6 @@ pub enum Expr {
Var(String),
}

#[derive(Debug, Clone)]
pub enum Process {
Call(String, SpannedExpr),
Literal(ProcessLiteralDirection, ProtocolRef, Block),
Block(Block)
}

#[derive(Debug, Copy, Clone)]
pub enum ProcessLiteralDirection {
Up,
@@ -106,14 +106,21 @@ impl ResolveInfo {
assert_eq!(up, ri.repeat_up_heuristic);
ri
}


}

pub fn infer_top_fields(step: &StepInfo, top_fields: &mut Fields) {
use self::Step::*;
match step.step {
Nop | Token(..) => (),
Nop => (),

Process(ref processes) => {
if let Some(ref last) = processes.processes.last() {
if last.fields_up.len() > 0 {
unimplemented!();
}
}
}

TokenTop(ref msg, ref body) => {

// Update the upward shape's direction with results of analyzing the usage of
@@ -143,15 +150,5 @@ pub fn infer_top_fields(step: &StepInfo, top_fields: &mut Fields) {
infer_top_fields(body, top_fields);
}
}

Fork(_, _, ref upper) => {
// Only the upper process has these top fields. The lower process already had its
// direction inferred (they're stored in the middle field of this enum).
infer_top_fields(upper, top_fields)
}

Primitive(_) => {
// Primitives can only exist in calls, and do not affect the top direction of the containing process
}
}
}
@@ -1,5 +1,6 @@
use super::step::{ StepInfo, Message };
use super::step::Step::*;
use process::{ProcessInfo, ProcessChain, Process};

use data::{ Type, Value };
use connection::{ Connection, ConnectionMessage };
use language::ValueID;
@@ -8,10 +9,10 @@ use super::matchset::MatchSet;
use std::i64;
use scoped_pool::Pool;

pub fn run(step: &StepInfo, downwards: &mut Connection, upwards: &mut Connection) -> bool {
pub fn run(processes: &ProcessChain, downwards: &mut Connection, upwards: &mut Connection) -> bool {
let pool = Pool::new(4);
let mut cx = RunCx { downwards, upwards, vars_down: State::new(), vars_up: State::new(), threadpool: &pool };
let result = run_inner(step, &mut cx);
let result = run_processes(&processes.processes, &mut cx);
pool.shutdown();
result
}
@@ -136,29 +137,85 @@ fn message_match(state: &mut State, msg: &Message, rx: Result<ConnectionMessage,
}
}

fn run_inner(step: &StepInfo, cx: &mut RunCx) -> bool {
match step.step {
Nop => true,
Token(ref msg) => {
cx.send_lower(msg).ok();
fn run_processes(processes: &[ProcessInfo], cx: &mut RunCx) -> bool {
let (child, chain) = match processes.split_first() {
Some(x) => x,
None => return true
};

if chain.len() == 0 {
run_process(child, cx)
} else {
let (mut conn_u, mut conn_l) = Connection::new(&child.fields_up);
let mut upper_cx = RunCx {
downwards: &mut conn_u,
upwards: cx.upwards,
vars_down: cx.vars_down.clone(),
vars_up: State::new(),
threadpool: cx.threadpool
};
let mut lower_cx = RunCx {
downwards: cx.downwards,
upwards: &mut conn_l,
vars_down: cx.vars_down.clone(),
vars_up: State::new(),
threadpool: cx.threadpool
};

let mut ok1 = false;
let mut ok2 = false;

cx.threadpool.scoped(|scoped| {
scoped.execute(|| {
ok1 = run_processes(chain, &mut upper_cx);
upper_cx.downwards.end();
debug!("Fork upper end");
});
ok2 = run_process(child, &mut lower_cx);
lower_cx.upwards.end();
debug!("Fork lower end");
});

debug!("fork join");

cx.vars_up.merge(upper_cx.vars_up);
cx.vars_up.merge(lower_cx.vars_up);

ok1 && ok2
}
}

fn run_process(process: &ProcessInfo, cx: &mut RunCx) -> bool {
match process.process {
Process::Token(ref msg) => {
cx.send_lower(msg).ok();
let rx = cx.downwards.recv();
message_match(&mut cx.vars_up, msg, rx)
}
Process::Seq(ref step) => run_step(step, cx),
Process::Primitive(ref p) => p.run(cx.downwards, cx.upwards),
}
}

fn run_step(step: &StepInfo, cx: &mut RunCx) -> bool {
use super::step::Step::*;
match step.step {
Nop => true,
Process(ref p) => run_processes(&p.processes, cx),
TokenTop(ref msg, ref inner) => {
let rx = cx.upwards.recv();
if !message_match(&mut cx.vars_down, msg, rx) {
return false;
}

if !run_inner(inner, cx) { return false; }
if !run_step(inner, cx) { return false; }

cx.send_upper(msg).ok();
true
}
Seq(ref steps) => {
for step in steps {
if !run_inner(step, cx) { return false; }
if !run_step(step, cx) { return false; }
}
true
}
@@ -174,7 +231,7 @@ fn run_inner(step: &StepInfo, cx: &mut RunCx) -> bool {
};

while c < hi && cx.test(&inner.first) {
if !run_inner(inner, cx) { return false; }
if !run_step(inner, cx) { return false; }
c += 1;
}

@@ -188,7 +245,7 @@ fn run_inner(step: &StepInfo, cx: &mut RunCx) -> bool {
other => panic!("Count evaluated to non-integer {:?}", other)
};
for _ in 0..c {
if !run_inner(inner, cx) { return false; }
if !run_step(inner, cx) { return false; }
}
true
}
@@ -216,7 +273,7 @@ fn run_inner(step: &StepInfo, cx: &mut RunCx) -> bool {
}
}

if !run_inner(inner, cx) { return false; }
if !run_step(inner, cx) { return false; }

for &mut (id, _, ref mut up, _) in &mut lstate {
if let Some(u) = up {
@@ -242,7 +299,7 @@ fn run_inner(step: &StepInfo, cx: &mut RunCx) -> bool {
r.eval_up(&mut |var, val| cx.vars_up.set(var, val), v);
}

return run_inner(inner, cx);
return run_step(inner, cx);
}
}
false
@@ -256,54 +313,11 @@ fn run_inner(step: &StepInfo, cx: &mut RunCx) -> bool {
});

if matches {
return run_inner(inner, cx);
return run_step(inner, cx);
}
}
false
}
}

Fork(ref lower, ref fields, ref upper) => {
let (mut conn_u, mut conn_l) = Connection::new(fields);
let mut upper_cx = RunCx {
downwards: &mut conn_u,
upwards: cx.upwards,
vars_down: cx.vars_down.clone(),
vars_up: State::new(),
threadpool: cx.threadpool
};
let mut lower_cx = RunCx {
downwards: cx.downwards,
upwards: &mut conn_l,
vars_down: cx.vars_down.clone(),
vars_up: State::new(),
threadpool: cx.threadpool
};

let mut ok1 = false;
let mut ok2 = false;

cx.threadpool.scoped(|scoped| {
scoped.execute(|| {
ok1 = run_inner(upper, &mut upper_cx);
upper_cx.downwards.end();
debug!("Fork upper end");
});
ok2 = run_inner(lower, &mut lower_cx);
lower_cx.upwards.end();
debug!("Fork lower end");
});

debug!("fork join");

cx.vars_up.merge(upper_cx.vars_up);
cx.vars_up.merge(lower_cx.vars_up);

ok1 && ok2
}

Primitive(ref p) => {
p.run(cx.downwards, cx.upwards)
}
}
}
@@ -1,4 +1,4 @@
mod ast;
pub mod ast;
mod scope;
mod expr;
mod eval;
@@ -19,7 +19,7 @@ pub use self::scope::{ Item, Scope };
pub use self::eval::{ Expr, add_primitive_fns };
pub use self::function::PrimitiveFn;
pub use self::primitive::{ PrimitiveDef, PrimitiveDefFields, call_primitive };
pub use self::step::{ Step, StepInfo };
pub use self::step::{ Step, StepInfo, Message };
pub use self::exec::run;

pub use self::grammar::literal as parse_literal;
Oops, something went wrong.

0 comments on commit 06e4fa6

Please sign in to comment.
You can’t perform that action at this time.