Assingment

advertisement
MAPS 7873 Assignment 3
MAPS 7873
Assignment 3: Occam Programming
This assignment concerns using occam to develop parallel programs. You should
use the jEdit/Transterpreter IDE to complete this assignment.
There are two parts to this assignment, in summary these are:
1. The Car Park Simulator
Total Marks 50
You are asked to complete the functionality of the provided incomplete program
(details later in this specification). A complete version of the program will be
demonstrated to you so that you know how it should appear. There are two versions,
one simple one that outputs the progress of the program with scrolling messages to
the console , and a second more graphical one that simulates on screen the action of
the car park. The simple version is useful as it has less obfuscating processes to get
in the way of your understanding of the code. However, your efforts should be
applied to the graphical version as it is this version that should be submitted.
2. The Super-Scalar Processor Simulator
Total Marks 30
This sounds worse than it is! You are asked to write a complete occam program that
simulates a dual-pipeline processor very simply – instructions are continually fed into
the processor (as if they were being fetched) and are dispatched to one of two
execution pipelines, whichever is ‘free’ (i.e. has finished executing the previous
instruction). Each instruction is simply defined by a number, 1, 2 or 3, which
represents its relative execution time, and this is generated randomly. The main
constraint is that the instructions, although executed on either pipeline nondeterministically, must be ‘retired’ in the order they were originally generated (i.e. this
is an ‘in-order’ processor).
Submission Requirements
Deadline: Wednesday, 19th May 2010, 11.59pm.
There are 80 marks available. This assignment contributes 40% to the overall
assessment of the module.
You should submit the following occam source files to the MAPS Blackboard site
(assignments area), contained in a single zip file called surname_assignment3.zip:
surname_carpark.occ
surname_processor.occ
surname_DFDs.doc
(or .docx)
You should also submit paper listings of these two programs and DFD’s through
ACES post-grad reception in Harmer as normal. Please ensure these are suitably
formatted with no word-wrap and no inappropriate orphan/widow lines (use
landscape printing if necessary), and are clearly labelled with their titles and your full
name.
If you have more than one version of these programs, feel free to add them to your
submission for consideration – ensure you add comments to explain their differences
and add a sequential number to their filenames (surname_carpark1.occ,
surname_carpark2.occ, etc).
Page 1
MAPS 7873 Assignment 3
1. The Car Park Simulator
Tasks
50 Marks
Obtain and inspect these incomplete listings from Bb:
MAPS Car Park User Simple incomplete.occ
MAPS Car Park User Graphic incomplete.occ
These are listed along with a screen shot of the output later in this specification. The
following tasks should be applied to the graphical version of the program eventually,
although it is recommended that you trial your attempts on the simple version first as
it has been provided to help you understand the function of the program more easily.
1.
raw the DFD for the car park program (see below).
D
2 marks
2.
C
omplete the missing parts of the program correctly.
For this purpose comments with the format:
-- ??? some useful comment here
have been left in the listings as guidance to what is required. In this document
they are highlighted in bold. Normal comments beginning with '--' alone are
'normal' comments and do not indicate anything's missing!
The ???'s signal that something's missing in the program. There is generally
one of these comments per line of code missing although you will need to add
SEQ statements and correct the indentation as demanded by occam syntax.
Additional information is given in the code where necessary to aid you.
The programs will not compile as is although they could without all the missing
code being inserted, they just won't work correctly! The program should
eventually function correctly to get the full marks.
You will need to understand the structure of the program from consideration of
the DFD and existing code and use your (growing) knowledge of occam and
message passing methods to get the program working properly.
A reasonable starting point would be to get 'simulate.pads'
implemented. It may also be a useful strategy to use separate test
programs to independently test some processes outside of the main
Car Park code.
30 marks
3.
A
lter the entrance.gate process so that a car driver will patiently wait
10 seconds at an entrance gate if the car park is full before driving off
disappointed– if a car exits in the meantime they are allowed in.
More cars should not arrive at this gate whilst waiting (the program
does not implement queuing and you're not expected to add it!).
5 marks
Page 2
MAPS 7873 Assignment 3
4.
A
dd functionality that provides random arrival and exit of cars at a
suitable maximum interval (e.g. between 5 and 10 seconds) in addition
to keyboard input.
5 marks
5.
F
or extra marks, show cars parking randomly in unoccupied parking
slots in the car park. You are not expected to animate the cars moving
from entrance gate to a parking slot, but simply show the legend 'CAR'
appearing in a space (see below).
Cars chosen to exit the car park (these should also be chosen
randomly) should be removed (deleted in fact, overwritten with '...')
from that parking place. You will need to add a data structure that
records each parking place’s location and status. To make this a little
easier implement a reduced version of this scheme using just one
(regular shaped) area of the car park (e.g. see layout below).
8 marks
The graphical car park layout is as follows(showing some 'parked' cars):
___________________
___________________
|...
...
... exit 2 ...
...
CAR|
|...
...
...
...
...
...|
|...
...
...
CAR
CAR
...|
|...
...
...
...
...
CAR|
|...
...
...
CAR
...
...|
|...
...
...
CAR
...
...|
selected random parking
zone for Task 5.
(18 places)
exit 1
exit 3
|...
...
...
...
...|
|...
...
...
...
...|
|...
...
...
...
...|
|...
...
...
...
...|
|...
...
...
...
...|
|...
...
...
...
...|
|_____Gate A______________________Gate B____|
The DFD
The data flow diagram should be deduced from this extract from the main process
(with constants inserted); the process names are in bold:
PROC simulate.car.park (CHAN OF BYTE keyb?, screen!, sink!)
[2]
[2]
[3]
[3]
CHAN
CHAN
CHAN
CHAN
OF
OF
OF
OF
BYTE
BOOL
BOOL
BYTE
car.arrived, pad.in:
request.space, open.gate:
car.left, pad.out:
screens:
PAR
PAR i=0 FOR 2 -- entrances
PAR
entrance.pad (pad.in[i]?, car.arrived[i]!)
entrance.gate
(car.arrived[i]?,request.space[i]!,open.gate[i]?,screens[i]!)
PAR i=0 FOR 3 -- exits
exit.pad (pad.out [i]?, car.left [i]!)
car.park.control (request.space?,open.gate!,car.left?,screens[entrances]!)
Page 3
MAPS 7873 Assignment 3
simulate.pads (pad.in!, pad.out!, keyb?)
screen.handler (screens?, screen!)
:
Notes
1. The input library call that is generally employed to get characters from the
keyboard:
in.skip (keypress,keyb)
can often be replaced by a rather more direct input from the keyboard:
keyb ? keypress
where keyb ? is the channel in the main process connected to the keyboard, and
keypress is a BYTE variable.
2. Input from a keyboard is in ASCII (character) form, hence typing numbers such as
0 or 1 actually returns '0' and '1' which have decimal values 48 and 49! Hence if
you wish to use '0' and '1' as integers, array indices or similar they must be
converted by subtracting 48 from them. This can be done as follows, assuming the
variable 'key' contains the character '0', '1', '2' (up to '9' in fact):
INT index:
VAL BYTE zero.char IS '0': -- ASCII '0' = 48 but this is more obvious
SEQ
index := INT (key - zero.char) -- convert from ASCII
some.array [index] := foo
-- can now use to index an array
(Nb. this method will not work with multi-digit numbers!)
Note also the use of the INT to retype the (key - zero.char) from BYTE type
to INTeger for use as an array index.
Page 4
MAPS 7873 Assignment 3
2. The Super-Scalar Processor Simulator
Tasks
30 Marks
You should develop an occam program that simulates a simple dual-pipeline
processor. The program should generate a constant stream of ‘instructions’ which
are fed to one of two execution pipelines, as depicted below:
display generated
instruction on the
console
Generate instructions randomly
Each is either 1, 2 or 3
'Q' from keyboard terminates
The program should only terminate when you enter a ‘Q’ or 'q' at
the keyboard. To keep the program simple this only need
terminate the process that is generating the instructions, and
does not need to be propagated to the other running
processes (these will subsequently 'crash' - most
left pipeline
probably due to the dreaded deadlock!).
dispatcher
right pipeline
Delay by 1,2,
Each 'instruction' should be generated randomly and
or 3 time
each should simply be represented as a number,
units
either a '1', a '2' or a '3', and echoed to the console
display. This number simply indicates how long the
instruction will take to execute in a pipeline. This means that
if a ‘3’ instruction is in the left hand pipeline, the right-hand
pipeline could potentially execute three ‘1’ instructions during
the same time period. The execution ‘hardware’ (process) will
be delayed 1, 2 or 3 time units depending on the instruction it
has dispatched to it (there is no real execution going on in this
simulation). Instructions should be dispatched to the first
execution pipeline (left or right) that has finished ‘executing’ its
current instruction, or non-deterministically if they are both free.
You will need the occam ALT construct to provide this and
other key features of the program.
Delay by 1,2,
or 3 time
units
retire instructions
display retired
instructions on
console (in-order) or
(OOO)
The retirement ‘hardware’ (process) simply displays the instruction number 1, 2, or 3,
on the screen.
You could develop the program using just these requirements to begin with, and this
would be a sort of OOO (out-of-order) processor as you’re not guaranteed that the
order of arrival of instructions is the same as retirement. However, there is a major
constraint in that the instructions must be displayed (retired) in the order they were
originally generated. Hence, you will need to number (or otherwise tag) the
generated instructions sequentially and communicate this somehow through the
system so that the retirement hardware can hold up one of the pipelines when it
needs to wait for the correct next instruction in sequence to come through the other
(that is, synchronise them).
The output can be simple messages to the console, however, extra credit will be
given if a simple graphical simulation/depiction of instructions being generated and
Page 5
MAPS 7873 Assignment 3
dispatched to the left or right pipelines, and showing them coming out of the
retirement process in the correct (or out-of) order, is provided.

esign a DFD for the processor program

evelop a simple ‘out-of-order’ simulation program in occam

evelop the ‘in-order’ simulation fully

raphical simulation
D
2 marks
D
10 marks
D
10 marks
G
8 marks
Code Documentation
As always, to obtain full marks your code should be well commented, well-structured
and understandable.
BEER PRIZE of sorts
If you are still thirsting for more - and I couldn't blame you! - consider how you would
propagate the termination signal through the processor so that all of the processes
halt gracefully. A few IF statements and adopting the number '9' as a halt 'instruction'
in the pipeline and retirement processes is one possibility. A series of special
'terminate' channels paralleling the other data paths is another (then you will need
ALT's!*). If you implement this, I'll buy you a beer (or equivalent)!
* This termination problem can be subtly dealt with in occam by using tagged protocols, but this is
beyond the scope of this module.
Page 6
MAPS 7873 Assignment 3
Car Park Program (with simple console output) INCOMPLETE VERSION
-- MAPS Car Park simulation
A.Oram 2010
-- INCOMPLETE VERSION FOR MAPS ASSIGNMENT 3
-- This version is simple with single line console outputs.
#INCLUDE "course.module"
-- I/O library
--------------- Constants etc ------------------------------------- This car park has only 5 spaces available, 2 entrances and 3 exits ------VAL num.spaces IS 5: -- Change this as desired
VAL entrances IS 2:
-- Entrances are identified as 'A', 'B'
VAL exits IS 3:
-- Exits identified as 0,1,2
--------------- Processes --------------------------------------PROC show.spaces.remaining (VAL INT car.count, CHAN OF BYTE screen!)
SEQ
IF
car.count < num.spaces
SEQ
out.string ("Spaces = ",0,screen)
out.int (num.spaces-car.count,0, screen)
out.ch ('*n',0,screen)
TRUE
out.string ("Car park is FULL*n",0,screen)
:
------------------------------------------------------------------------PROC entrance.pad (CHAN OF BYTE pad.in?, car.detected!)
BYTE pad.id:
-- ???
SEQ
pad.in ? pad.id
car.detected ! pad.id
:
-------------------------------------------------------PROC entrance.gate (CHAN OF BYTE -- ???,
CHAN OF BOOL request.space!, open.up?,
CHAN OF BYTE screen!)
BYTE gate.id:
BOOL answer:
VAL BOOL yes IS TRUE:
VAL BOOL any.space IS TRUE:
-- ???
SEQ
car.detected ? gate.id
-- wait for a car to arrive at gate
out.string ("Car at Gate ",0,screen) -- car has arrived
out.ch (gate.id /\ #DF,0, screen)
-- (force gate id to uppercase)
out.string ("*n",0,screen)
-- ??? ask controller if there's free space
-- ??? get a response from controller
IF
-- ??? there's space
SEQ
out.string ("Gate ",0,screen)
-- "open" the gate here
out.ch (gate.id /\ #DF,0, screen)
out.string (" open*n",0,screen)
-- ??? no space left! Leave gate closed
SKIP
:
Page 7
MAPS 7873 Assignment 3
--------------------------------------------------------------PROC exit.pad (CHAN OF BOOL pad.out?, car.detected!)
BOOL car.left:
-- ???
pad.out ? car.left
car.detected ! car.left
:
---------------------------------------------------------------PROC car.park.control ([]CHAN OF BOOL -- ???,
[]CHAN OF BOOL open.gate!, car.left?,
CHAN OF BYTE screen!)
INT num.cars.parked:
VAL welcome IS TRUE:
VAL sorry...full IS FALSE:
BOOL request.space:
BOOL car.has.left:
SEQ
num.cars.parked := 0
-- initialise car counter
-- ??? park is 24/7 !
-- ??? deal with cars coming and going
-- deal with cars wanting to get in --------------------------------ALT i = 0 FOR entrances
-- ???
-- ??? car detected and there's space, let 'em in
SEQ
open.gate[i] ! welcome
num.cars.parked := num.cars.parked + 1
out.string ("Car entered car park...*n",0,screen)
-- ??? car detected but we're full, turn them away
SEQ
open.gate[i] ! sorry...full
out.string ("FULL - Car refused entry...*n",0,screen)
-- deal with cars leaving ------------------------------------------ALT i = 0 FOR exits
-- ???
-- ??? a car has left the car park
SEQ
num.cars.parked := num.cars.parked - 1
out.string ("Car left car park...*n",0,screen)
-- ??? a non-existent parked car is trying to leave!
out.string ("Impossible! Car park is empty!*n",0,screen)
-- after dealing with each entry/exit update the 'spaces' display ----show.spaces.remaining (num.cars.parked,screen)
:
Page 8
MAPS 7873 Assignment 3
---------------------------------------------------------------------PROC simulate.pads ([]CHAN OF BYTE pad.in!,
[]CHAN OF BOOL pad.out!, CHAN OF BYTE keyb?)
BYTE key:
INT id:
VAL BYTE zero.char -- ???:
VAL entranceA IS 0: -- useful constants for indexing the channels
VAL entranceB IS 1:
-- ???
SEQ
-- ??? Input a key from the keyboard - use variable 'key'
-- ??? When 'A' or 'a' is entered
-- ??? tell entrance A that a car has arrived
-- ??? When 'B' or 'b' is entered
-- ??? tell entrance B that a car has arrived
-- ??? When '0', '1', or '2' is entered
-- ??? tell exit pad at exit [0], exit [1] or exit [2] as appropriate that
-- ??? car has exitted.
-- ??? If any other key has been pressed, ignore it.
:
-----------------------------------------------------------------------PROC screen.handler ([]CHAN OF BYTE screen.channels, CHAN OF BYTE screen)
BYTE data:
WHILE TRUE
ALT i = 0 FOR SIZE screen.channels
screen.channels [i]? data
screen ! data
:
------------- CAR PARK main process here! -------------------------------------PROC simulate.car.park (CHAN OF BYTE keyb?, screen!, sink!)
VAL []BYTE instructions IS "Use *'A*', *'B*' to indicate car arrivals.*nUse *'0*',
*'1*' or *'2*' to indicate car departures.*n":
[entrances] CHAN OF BYTE car.arrived, pad.in:
[entrances] CHAN OF BOOL request.space, open.gate:
[exits]
CHAN OF BOOL car.left, pad.out:
[entrances+1] CHAN OF BYTE screens: -- the +1 extra channel is for the controller!
SEQ -- initialise everything and draw car park
erase.screen (screen)
out.string ("Simple Car Park Simulator (A,Oram 2010)*n",0, screen)
out.string (instructions,0,screen)
show.spaces.remaining (0,screen)
out.ch (FLUSH,0,screen)
-- ensure it displays
-- now kick everything off in parallel!
PAR
PAR i=0 FOR entrances
PAR
entrance.pad (pad.in[i]?, car.arrived[i]!)
entrance.gate (car.arrived[i]?, request.space[i]!, open.gate[i]?, screens[i]!)
PAR i=0 FOR exits
exit.pad (pad.out [i]?, car.left [i]!)
car.park.control (request.space?, open.gate!, car.left?, screens[entrances]!)
--------------- now the simulated pads and screen handler -------simulate.pads (pad.in!, pad.out!, keyb?)
screen.handler (screens?, screen!)
:
Page 9
MAPS 7873 Assignment 3
Screen dumps whilst running the simple car park simulator
Page 10
MAPS 7873 Assignment 3
Car Park Program (with graphical simulation) INCOMPLETE VERSION
-----------------------
MAPS Car Park simulation
A.Oram 2010
INCOMPLETE VERSION FOR MAPS ASSIGNMENT 3
This version uses more graphical simulation output.
The number of exits and entrances are fixed.
The car park looks like this:
___________________
___________________
|...
...
... exit 2 ...
...
...|
|...
...
...
...
...
...|
|...
...
...
...
...
...|
|...
...
...
...
...
...|
|...
...
...
...
...
...|
|...
...
...
...
...
...|
exit 1
exit 3
|...
...
...
...
...|
|...
...
...
...
...|
|...
...
...
...
...|
|...
...
...
...
...|
|...
...
...
...
...|
|...
...
...
...
...|
|_____Gate A______________________Gate B____|
#INCLUDE "course.module"
-- I/O library
--------------- Constants etc ------------------------------------------------VAL INT one.sec IS 500000: -- reduce this to speed things up! Nb 1,000,000 = 1
sec
---- This car park has 55 spaces available, 2 entrances and 3 exits ----------VAL num.spaces IS 5: -- Change this as desired for testing
VAL entrances IS 2:
-- Entrances are identified as 'A' and 'B'
VAL exits IS 3:
-- Exits identified as 1,2,3
VAL carpark IS
[" ___________________
___________________ ",
"|...
...
...
...
...
...|",
"|...
...
...
...
...|",
"|_____Gate A______________________Gate B____|"]:
places
VAL
VAL
VAL
VAL
BYTE
BYTE
BYTE
BYTE
top IS 5:
left IS 10:
bottom IS 16:
right IS 45:
-----
y
x
y
x
-----
layout of car park
need six of these lines
need six of these lines
...'s indicate parking
coord of top left corner of park
coord
dimension of car park
dimension
-- set up positions of entrances and exits
VAL exit.pos IS [[left,top+7],[left+21,top+3],[left+44,top+7]]:
VAL gates IS [[left+8,top+bottom],[left+36,top+bottom]]:
-------------- Other constants --------------------------------------------VAL INT x IS 0: -- to distinguish coordinates in the array structures
VAL INT y IS 1:
VAL INT D1 IS 1: -- movement increments for animation
VAL INT D0 IS 0:
Page 11
MAPS 7873 Assignment 3
--------------- Screen and general purpose processes ----------------------PROC delay (VAL INT seconds)
TIMER time:
INT now:
SEQ
time ? now
time ? AFTER now PLUS (seconds * one.sec)
:
---------------------------------------------------------------------------PROC show.car.park.layout (CHAN OF BYTE screen)
SEQ
cursor.x.y (left,top,screen)
-- library call
out.string (carpark[0],0, screen)
-- library call
SEQ i = 1 FOR 6 -- draw top half of carpark
BYTE ib:
SEQ
ib := BYTE i
cursor.x.y (left,top+ib,screen)
out.string (carpark[1],0,screen)
SEQ i = 9 FOR 6 -- draw bottom half of carpark
BYTE ib:
SEQ
ib := BYTE i
cursor.x.y (left,top+ib,screen)
out.string (carpark[2],0,screen)
cursor.x.y (left,top+15,screen)
out.string (carpark[3],0,screen)
:
----------------------------------------------------------------PROC show.spaces.remaining (VAL INT car.count, CHAN OF BYTE screen!)
SEQ
cursor.x.y (left + 17, top+bottom,screen)
IF
car.count < num.spaces
SEQ
out.string ("Spaces = ",0,screen)
out.int (num.spaces-car.count,0, screen)
TRUE
out.string ("
FULL
",0,screen)
:
----------------------------------------------------------------PROC out.string.x.y (VAL []BYTE string, VAL BYTE x,y, CHAN OF BYTE screen!)
SEQ
cursor.x.y (x,y,screen)
-- library call
out.string (string,0,screen)
-- library call
:
----------------------------------------------------------------PROC show.status (VAL []BYTE message, CHAN OF BYTE screen!)
SEQ
cursor.x.y (22,3, screen)
-- library call
erase.eol (screen)
-- library call
out.string (message,0,screen)
-- library call
:
----------------------------------------------------------------PROC show.car.x.y (VAL BYTE x,y, CHAN OF BYTE screen!)
SEQ
cursor.x.y (x,y,screen)
out.string ("CAR",0,screen)
cursor.x.y (1,1,screen)
out.ch (FLUSH,0, screen)
-- library call
:
Page 12
MAPS 7873 Assignment 3
-----------------------------------------------------------------PROC clear.car.x.y (VAL BYTE x,y, CHAN OF BYTE screen!)
SEQ
cursor.x.y (x,y,screen)
out.string ("
",0,screen)
cursor.x.y (1,1,screen)
out.ch (FLUSH,0, screen)
:
-----------------------------------------------------------------PROC animate.car (VAL BYTE start.x,start.y,
VAL INT delta.x, delta.y,
VAL INT distance, CHAN OF BYTE screen)
-- Set 'delta.x' to positive value to move right, negative value to move left.
-- Set 'delta.y' to positive value to move down, negative value to move up.
-- The value set will be the number of screen positions moved, so '1', '-1'
-- or '0' (no move in that orientation) will be normal.
-- 'distance' is the number of 'delta's to move.
BYTE next.x, next.y:
SEQ
next.x := start.x
next.y := start.y
SEQ i = 1 FOR distance
-- move this number of times
SEQ
show.car.x.y (next.x, next.y,screen)
delay (1) -- leave on screen for a short period
clear.car.x.y (next.x, next.y,screen)
IF
delta.x < 0
next.x := next.x - (BYTE (-delta.x))
TRUE
next.x := next.x + (BYTE (delta.x))
IF
delta.y < 0
next.y := next.y - (BYTE (-delta.y))
TRUE
next.y := next.y + (BYTE (delta.y))
show.car.x.y (next.x, next.y, screen) -- leave car on screen
:
-----------------------------------------------------------------------------PROC show.car.leaving (VAL INT exit.num, CHAN OF BYTE screen)
INT Dx,Dy:
VAL INT steps IS 4: -- number of positions to move car through exit
SEQ
Dx := 0
Dy := 0
CASE exit.num -- set up movement direction depending on where exit is
0
Dx := -1
1
Dy := -1
2
Dx := 1
ELSE
SKIP
animate.car (exit.pos[exit.num][x],exit.pos[exit.num][y],Dx,Dy,steps,screen)
Dx := (INT (exit.pos[exit.num][x])) + (steps*Dx) -- locate end point of
Dy := (INT (exit.pos[exit.num][y])) + (steps*Dy) -- movement so we can
clear.car.x.y (BYTE Dx,BYTE Dy,screen)
-- clear it from the screen
:
Page 13
MAPS 7873 Assignment 3
-------------------- These are the car park processes ------------------------PROC entrance.pad (CHAN OF BYTE pad.in?, car.detected!)
BYTE pad.id:
-- ???
SEQ
pad.in ? pad.id
car.detected ! pad.id
:
-------------------------------------------------------PROC entrance.gate (CHAN OF BYTE -- ???,
CHAN OF BOOL request.space!, open.up?,
CHAN OF BYTE screen!)
BYTE gate.id:
INT gate.num:
BOOL answer:
VAL BOOL yes IS TRUE:
VAL BOOL any.space IS TRUE:
VAL BYTE char.A IS 'A':
-- ???
SEQ
car.detected ? gate.id
-- wait for a car to arrive at gate
gate.id := gate.id /\ #DF
-- convert gate id to upper case
gate.num := INT (gate.id - char.A) -- and then convert to 0 or 1
animate.car (gates[gate.num][x],gates[gate.num][y]+4,D0,-D1,4,screen)
delay (3)
-- show car at gate briefly
-- ??? ask controller if there's free space
-- ??? get a response from controller
IF
-- ??? there's space
SEQ -- move car through the gate
clear.car.x.y (gates[gate.num][x],gates[gate.num][y],screen)
show.car.x.y (gates[gate.num][x],gates[gate.num][y]-2,screen)
delay (3) -- "close" the gate after a short delay
-- 'park' the car by clearing it from screen
clear.car.x.y (gates[gate.num][x],gates[gate.num][y]-2,screen)
-- ??? no space left! Leave gate closed and make car go away!
SEQ
animate.car (gates[gate.num][x],gates[gate.num][y],D0,D1,4,screen)
clear.car.x.y (gates[gate.num][x],gates[gate.num][y]+3,screen)
:
--------------------------------------------------------------PROC exit.pad (CHAN OF BOOL pad.out?, car.detected!)
BOOL car.left:
-- ???
pad.out ? car.left
car.detected ! car.left
:
Page 14
MAPS 7873 Assignment 3
---------------------------------------------------------------PROC car.park.control ([]CHAN OF BOOL -- ???,
[]CHAN OF BOOL open.gate!, car.left?,
CHAN OF BYTE screen!)
INT num.cars.parked:
VAL welcome IS TRUE:
VAL sorry...full IS FALSE:
BOOL request.space:
BOOL car.has.left:
SEQ
num.cars.parked := 0
-- initialise car counter
-- ??? park is 24/7 !
-- ??? deal with cars coming and going
-- deal with cars wanting to get in --------------------------------ALT i = 0 FOR entrances
-- ???
-- ??? car detected and there's space, let 'em in
SEQ -- car detected and there's space, let 'em in
open.gate[i] ! welcome
num.cars.parked := num.cars.parked + 1
show.status ("Car entered car park...",screen)
-- ??? car detected but we're full, turn them away
SEQ -- car detected but we're full, turn them away
open.gate[i] ! sorry...full
show.status ("FULL - Car refused entry...",screen)
-- deal with cars leaving ------------------------------------------ALT i = 0 FOR exits
-- ???
-- ??? a car has left the car park
SEQ
num.cars.parked := num.cars.parked - 1
show.status ("Car left car park...",screen)
show.car.leaving (i, screen)
-- ??? a non-existent parked car is trying to leave!
show.status ("Impossible! Car park is empty!",screen)
-- after dealing with each entry/exit update the 'spaces' display ----show.spaces.remaining (num.cars.parked,screen)
cursor.x.y (1,1,screen) -- park cursor (no pun intended) top,left corner
out.ch (FLUSH,0,screen)
-- make it all appear!
:
---------------------------------------------------------------------PROC simulate.pads ([]CHAN OF BYTE pad.in!, []CHAN OF BOOL pad.out!, CHAN OF
BYTE keyb?)
BYTE key:
INT id:
VAL BYTE zero.char -- ???:
VAL entranceA IS 0: -- useful constants for indexing the channels
VAL entranceB IS 1:
-- ???
SEQ
-- ??? Input a key from the keyboard - use variable 'key'
-- ??? When 'A' or 'a' is entered
-- ??? tell entrance A that a car has arrived
-- ??? When 'B' or 'b' is entered
-- ??? tell entrance B that a car has arrived
-- ??? When '0', '1', or '2' is entered
-- ??? tell exit pad at exit [0], exit [1] or exit [2] as appropriate that
-- ??? car has exitted.
-- ??? If any other key has been pressed, ignore it.
:
Page 15
MAPS 7873 Assignment 3
-----------------------------------------------------------------------PROC screen.handler ([]CHAN OF BYTE screen.channels, CHAN OF BYTE screen)
BYTE data:
WHILE TRUE
ALT i = 0 FOR SIZE screen.channels
screen.channels [i]? data
screen ! data
:
------------- CAR PARK main process here! -------------------------------------PROC simulate.car.park (CHAN OF BYTE keyb?, screen!, sink!)
VAL []BYTE instructions IS "Arrive: *'A*',*'B*' Depart: *'1*',*'2*'*'3*'":
[entrances] CHAN OF BYTE car.arrived, pad.in:
[entrances] CHAN OF BOOL request.space, open.gate:
[exits]
CHAN OF BOOL car.left, pad.out:
[entrances+1] CHAN OF BYTE screens: -- the +1 extra screen channel is for the
controller!
SEQ -- initialise everything and draw car park
erase.screen (screen)
out.string.x.y ("CAR PARK SIMULATOR (A.Oram 2010)",22,1,screen)
out.string.x.y (instructions,15,2,screen)
show.car.park.layout (screen)
show.spaces.remaining (0,screen)
cursor.x.y (1,1,screen) -- park (!) cursor in top left corner
out.ch (FLUSH,0,screen) -- ensure it displays
-- now kick everything off in parallel!
PAR
PAR i=0 FOR entrances
PAR
entrance.pad (pad.in[i]?, car.arrived[i]!)
entrance.gate (car.arrived[i]?,request.space[i]!,open.gate[i]?,screens[i]!)
PAR i=0 FOR exits
exit.pad (pad.out [i]?, car.left [i]!)
car.park.control (request.space?,open.gate!,car.left?,screens[entrances]!)
--------------- now the simulated pads and screen handler -------simulate.pads (pad.in!, pad.out!, keyb?)
screen.handler (screens?, screen!)
:
Screen dump whilst running the graphical car park simulator
Page 16
MAPS 7873 Assignment 3
Page 17
Download