230 likes | 356 Vues
This document outlines best practices for employing Specification and Description Language (SDL) in product development, focusing on design models, performance considerations, and platform interface issues. It highlights common pitfalls such as deadlocks and confusion arising from semantically correct but syntactically complex models. Recommendations for achieving deterministic designs while managing nondeterminism and fairness are presented. By illustrating both good and bad design examples, this guide aims to simplify SDL implementation and enhance model accuracy in software design.
E N D
Guidelinesfor Using SDLin Product Development Frank Weil Motorola Global Software Group – Software Design Automation
Overview • General Recommendations for Design Models • Recommendations on SDL Usage for Design • Performance Considerations • Platform Interfaces • Portability Issues • Example Models
SDL for Design Two inherent problems: • Bad things can happen behind the scenes • Deadlocks • Signal send to a dead / invalid / unreachable process • … • It is hard to prove correctness! • Syntactically/semantically correct models can be confusing • Subrange constants are ignored in data type definition • Unused signals, data types, variables, procedures, … • … • Excuse: “If they new the semantics better, it would not be confusing” • Obvious things should have obvious semantics
General Recommendations • Nondeterminism and Fairness • SDL has several nondeterministic features • A good design should be deterministic • Nondeterminism does not imply fairness • Abstraction • Everything should be made as simple as possible,but no simpler! - Albert Einstein • Model must capture concepts, not irrelevant details
Examples Models • First, a bad example • Then, a good example for comparison • Read the paper for details (please?)
system SAM04_bad_example 1(1) newtype call_info struct header Integer; path Natural; dest destination_select; toggle Boolean; payload payload_t; signal packet(call_info); level Real; signal new_packet(call_info); endnewtype; signal control(Natural); signal updates(update_type); syntype destination_select = Destinations signal status(STATUS); constants 0 : 255 signal command(cmd_type, Buffer); endsyntype; signal config; syntype update_type = Integer constants 0, 2, 4, 8 endsyntype; newtype STATUS literals standby, current, update endnewtype; syntype update_interval = Natural constants -10 : 10 endsyntype; syntype cmd_type = Charstring endsyntype; syntype Buffer = Charstring endsyntype; syntype Destinations = Integer constants 1 : 100 endsyntype; syntype payload_t = Charstring constants size(10) endsyntype; signallist inbound_signals = packet, control, command, config; signallist outbound_signals = updates, new_packet; outbound1 (outbound_signals) switch traffic outbound2 (inbound_signals) (outbound_signals)
block switch 1(1) inbound traffic router (inbound_signals) internal (outbound_signals) packet outbound1 odd handler(0) even outbound2 (outbound_signals)
process router synonym 911 cmd_type = 'EMERGENCY'; procedure log; synonym REMOVE_CMD cmd_type = 'REMOVE'; fpar in stat Integer; synonym max_proc processes = 5; external; syntype processes = Integer timer TIM; dcl i, d, pow Integer; constants 1 : 5 dcl j processes; endsyntype; dcl ci, ci_tmp call_info; dcl ct cmd_type; dcl ts Boolean := false; dcl b Buffer; /* 16-bit unsigned int, LSB first */ j := 1 d := 1 (false) (true) j <= max_proc set(100, TIM) Handler 'done with initialization' j := j + 1 idle 1(2)
process router idle TIM packet(ci) command(ct, b) (REMOVE_CMD) log(1) ci_tmp := ci ct (911) set(now+7.325, TIM) d := num(b(0)) ts := not ts idle idle idle idle i := 1 ci_tmp!dest := d pow := 2 (false) ci_tmp!toggle := ts i <= 15 (true) packet(ci_tmp) via internal d := d + num(b(i)) * pow pow := pow * 2 i := i + 1 2(2)
process handler 1(1) dcl ci call_info; packet(ci) ci!path (0) (1) ci!payload := 'even' ci!payload := 'odd' ci!toggle ci!toggle (true) (true) (false) (false) ci!payload := ci!payload // 'T' ci!payload :=ci!payload // 'T ' idle idle idle ci!payload := ci!payload // 'F' ci!payload := ci!payload // 'F ' else new_packet(ci) Via even ci!level = 3.0 (true) ci!level := ci!level * 5 ci!header else (0) new_packet(ci) VIA odd
synonym 911 cmd_type = 'EMERGENCY'; synonym REMOVE_CMD cmd_type = 'REMOVE'; number as identifier Charstring instead of enum process router 1(2) synonym max_proc processes = 5; syntype processes = Integer timer TIM; dcl i, d, pow Integer; constants 1 : 5 dcl j processes; endsyntype; dcl ci, ci_tmp call_info; dcl ct cmd_type; dcl ts Boolean := false; dcl b Buffer; /* 16-bit unsigned int, LSB first */ j := 1 can be decluttered d := 1 (false) (true) loop control is wrong j <= max_proc Time literal case insensitivity set(100, TIM) Handler informal text as comment 'done with initialization' j := j + 1 idle
process router idle TIM packet(ci) command(ct, b) (REMOVE_CMD) log(1) ci_tmp := ci ct (911) ts := not ts set(now+7.325, TIM) d := num(b(0)) idle idle idle idle i := 1 ci_tmp!dest := d pow := 2 (false) ci_tmp!toggle := ts i <= 15 (true) packet(ci_tmp) via internal d := d + num(b(i)) * pow pow := pow * 2 i := i + 1 2(2) procedure log; fpar in stat Integer; C reserved word external; marshaling invalid String access copy of large data structure Duration precision possibly incompatible ranges ambiguous signal send can be decluttered
process handler 1(1) dcl ci call_info; packet(ci) ci!path (0) (1) ci!payload := 'even' ci!payload := 'odd' idle idle idle ci!toggle ci!toggle (true) (true) (false) (false) ci!payload := ci!payload // 'T' ci!payload :=ci!payload // 'T ' ci!payload := ci!payload // 'F' ci!payload := ci!payload // 'F ' else new_packet(ci) Via even ci!level = 3.0 (true) ci!level := ci!level * 5 ci!header else (0) new_packet(ci) VIA odd can be decluttered Charstring size constraint violation Real equality case insensitivity send to a dead process
block switch 1(1) inbound traffic router (inbound_signals) internal (outbound_signals) packet outbound1 odd handler(0) even outbound2 (outbound_signals) C keyword no max number of process instances
1(1) system SAM04_bad_example newtype call_info struct header Integer; underconstrained sort path Natural; dest destination_select; toggle Boolean; payload payload_t; signal packet(call_info); level Real; signal new_packet(call_info); endnewtype; signal control(Natural); signal updates(update_type); syntype destination_select = Destinations signal not used in this version signal status(STATUS); constants 0 : 255 signal command(cmd_type, Buffer); endsyntype; signal config; syntype update_type = Integer constants 0, 2, 4, 8 nonsensical / confusing data type definitions endsyntype; newtype STATUS literals standby, current, update endnewtype; unused signals and data types syntype update_interval = Natural constants -10 : 10 endsyntype; marshaling syntype cmd_type = Charstring endsyntype; syntype Buffer = Charstring endsyntype; unbounded / incorrectly bounded aggregate data types syntype Destinations = Integer constants 1 : 100 endsyntype; syntype payload_t = Charstring constants size(10) endsyntype; signallist inbound_signals = packet, control, command, config; signallist outbound_signals = updates, new_packet; outbound1 (outbound_signals) switch traffic outbound2 (inbound_signals) (outbound_signals) C keyword
system SAM04_good_example 1(1) newtype call_info struct header Integer; path path_t; dest destination_select; toggle Boolean; signal packet(call_info); payload payload_t; signal new_packet(call_info); level Real; signal emergency(Integer); endnewtype; signal remove; signal config; syntype path_t = Natural constants 0 : 1 endsyntype; syntype destination_select = Natural constants 0 : 255 endsyntype; syntype payload_t = Charstring constants size(5) endsyntype; signallist inbound_signals = packet, emergency, remove, config; signallist outbound_signals = new_packet; outbound1 traffic (outbound_signals) switcher (inbound_signals) outbound2 (outbound_signals)
1(1) block switcher synonym max_proc Natural = 5; signal dead(processes), okay; syntype processes = Natural constants 1 : max_proc endsyntype; inbound traffic router(1,1) (inbound_signals) dead internal packet, (outbound_signals) outbound1 okay odd handler (0, max_proc) even outbound2 (outbound_signals)
process router 1(2) timer TIM; dcl d destination_select := 1; dcl j processes := 1; dcl ci call_info; dcl ts Boolean := false; dcl count processes := max_proc; set_next_handler newtype pids Array(processes, Pid) endnewtype; dcl handlers pids; dcl next_handler processes := 1; procedure heartbeat; fpar in stat Integer; external; * config handled in phase 2 handler(j) - handlers(j) := offspring (true) (false) j < max_proc j := j + 1 set(now + 100000, TIM) done with initialization idle
process router 2(2) idle dead(j) TIM packet(ci) emergency(d) remove ci!dest := d, okay to sender heartbeat(1) ts := not ts ci!toggle := ts (1) packet(ci) count set(now+7325, TIM) to handlers(next_handler) else handlers(j) := Null, set_next_handler count := count - 1 -
process handler 1(1) dcl ci call_info; ; fpar me processes; dying build_payload okay * near idle - packet(ci) ci!payload := call build_payload(ci!path, ci!toggle) (0) (1) ci!path (false) call near(ci!level, 3.0) (true) ci!level := ci!level * 5 new_packet(ci) via even new_packet(ci) via odd else ci!header (0) dead(me) dying -
procedure build_payload 1(1) ; fpar in path path_t, in toggle Boolean; syntype position = Integer returns payload_t; constants 4 : 5 endsyntype; dcl insert position; dcl payload payload_t; (0) (1) path payload := 'even ', payload := 'odd ', insert := 5 insert := 4 toggle (true) (false) payload(insert) := 'T' payload(insert) := 'F' payload
procedure near 1(1) ; fpar in a Real, in b Real; synonym epsilon Real = 0.0001; returns Boolean; fix((a - b) / epsilon) = 0