CO538 Anonymous Questions and Answers Keyword Index |
This page provides a keyword index to questions and answers. Clicking on a keyword will take you to a page containing all questions and answers for that keyword, grouped by year.
To submit a question, use the anonymous questions page. You may find the keyword index and/or top-level index useful for locating past questions and answers.
Keyword reference for q4
2012 |
Submission reference: IN2179
Hello, I have everything working fine but I remember in one of the answers previously that you suggested speed.control to ALT between 3 guards, a timeout guard, a speed control guard and an input guard. I was wondering if there was any difference between that 3 guard ALT and a PRI ALT with just a speed control guard and a timeout guard, which is what I currently have.
Certainly there will be a difference. For one thing, it means when speed.control is waiting for its normal input, it can't process speed control commands. For this exercise, that probably doesn't matter since input data will mostly be pending and it won't have to wait for long. For other applications of speed.control, where the input data was sometimes stalled, this could be bad – it would hold up whatever process was trying to change the speed (and if that process were also interacting with whatever was supplying the input data, that would cause deadlock).
However, not dealing with such possibilities will only be lightly penalised ... this time! Unnecessarily constraining the way a process can sync with its environment is something always to avoid.
The PRI in your question is not relevant to the above concern.
Keywords: q4
Submission reference: IN2178
Hello there,
For Q4 all seems well in Gaul, however there is just one issue. Originally, when the BELL character is output (BELL flashes my output window), the ability to change speed stops, all output stops as well. Is this the desired beaviour or should it be that output continues? I have it so that output will continue such that when the limit is reached the value fed into pause is halved if at 256 lines per second (or doubled if at 1 lines per second) before the bell is output. That way the the limit is reached and imediately reset to the previous speed and the error is shown. Which way is better or desired?
Also is the diagram compulsory? My ASCII art isn't exactly da Vinci standard.
Thank you for your help.
It is not desired behaviour that the system stops working when a command to change speed would push that speed outside its defined limits. As the question says:
"... the attempt should be ignored and an error message generated. To keep things simple and not interfere with the columns of numbers being output, this error message should be a single BELL character ... sent to the error! channel."
You said: "when the limit is reached the value fed into pause is halved if at 256 lines per second (or doubled if at 1 lines per second) before the bell is output." That implies you do not allow your system to reach either of the defined limiting speeds? If so, that is wrong. What should happen is that if the command would push the speed above 256 lines/second (respectively below 1 line/second), the speed should be changed to 256 lines/second (respectively 1 line/second).
The two diagrams (for pairs2 and q4) are compulsory. You do not have to do ASCII art! There are four options:
Submission reference: IN2177
I have tried my best at implementing the approach that was suggested in my seminar where I take the raw BYTE information from print.streams, feed it through my monitor process which implements the freeze functionality and then feed it through a speed.control component before outputting it to the screen!.
Unfortunately, what I thought worked for this approach doesn't seem to and just introduces deadlock when the program first runs. I've written everything out as a diagram and can't get my head round why this is happening - it all looks as if it should work (to me anyway!)
Copied below are the relevant sections of my code. I wondered if you would be able to give me any suggestions of what's happening or why the deadlock is occurring and/or what would be the best way for me to implement the final stages of speed control? Freeze/flip etc. are all working.
Thank you very much in advance for your help.
(Ed: code deleted)
I've contacted the seminar leaders ... who all deny suggesting the approach you describe. We think you must have misunderstood some of the discussion on this.
See the third and fourth paragraphs of the answer to Question 21 (2012). The approach you describe appears attractive but, for the reasons described in that third paragraph, is unsafe. Deadlock is very likely to happen as soon as a cycle of communications is attempted (whenever monitor communicates to one of the processes it is controlling ... all of which are feeding back communications to monitor). A safe design is outlined in the fourth paragraph just referenced.
You said your implementation of this (wrong) approach "introduces deadlock when the program first runs". The deadlock in that approach only happens when monitor responds to a command to reset one of the three resettable components. If you get deadlock as it starts (i.e. without keying in 'n', 'i' or 'p'), you have another problem – check your wiring, check your speed.control has a loop, ...
Thought: it may be that you misunderstood your seminar leader when the freeze control in Exercise 3 was being discussed? In that system, "the raw BYTE information from" demo "is taken and fed through" a control "process which implements the freeze functionality". Now, there is no feedback loop of message traffic in the network for that exercise – so this is safe. Your seminar leader may have said that exactly this approach also works for Exercise 4 and that is true, but not the way you have taken it. A freeze.control process placed between print.streams and the external screen! channel is good. But that freeze.control process is not the monitor – it is a different process, something extra.
Re. other bits of your code: your speed.control has an ALT with only one guard – see the third paragraph in the answer to Question 14 (2012). I think you mean to poll that channel (i.e. you need to PRI ALT that guard against a SKIP, see "Choice" slide 30).
Keywords: q4
Submission reference: IN2176
For the diagrams for Assessment 3, do you want us to label the channels or just leave them unlabelled? Thanks.
See the last paragraph in the answer to Question 23 (2012).
Keywords: q4
Submission reference: IN2175
For the graphs, the email said we must provide diagrams for pairs2 and:
- your overall "q4" network. Along with other processes, this should show the modified "numbers2", "integrate2" and "pairs2" just as black boxes (no internal details, as in the diagram on page 5 of 'more-exercises.pdf').
Do you want the internal details of monitor, speed, freeze, print.streams? Or just show the channels?
The only diagram language we have presented ("Overview" slides 28-35) is for networks of processes running in parallel. The modified numbers2, integrate2 and pairs2 processes are implemented by such networks, so diagrams are part of their design spec and should be documented somewhere. We've already given you the diagrams for numbers2 and integrate2, so we have only asked for a diagram for pairs2 (from these three).
For the processes monitor, speed.control and freeze, we are only expecting implementations that are purely sequential (i.e. contain no internal PAR networks). Therefore, there is nothing to diagram: just draw these processes as shaded (or empty) boxes (or whatever shape you like). We do not draw diagrams for sequential code – programming language syntax is good enough, or should be!
Of course, should you happen to implement monitor, speed.control or freeze as a network of internal processes running in parallel, please submit the diagrams showing this. However, sequential logic is simplest for these.
The process print.streams (which we provided) has an internal PAR, but the processes set up are short-lived (just a single channel input) and have no channel connections with each other. Its logic is mainly sequential, going parallel temporarily at the start of each loop. Such changing forms cannot be diagrammed statically. Instead, we need a movie (or, at least, a cartoon strip) showing the changing forms. For print.streams, we would need two diagrams showing its two states (and document somewhere that it continually switches between them):
(sequential state) ---------------------------------- | | in[0] | | ------->-------| | | | | | in[1] | | out ------->-------| print.streams |------->------- | (col.width, delay) | | | in[2] | | ------->-------| | | | | | ---------------------------------- (parallel state) ---------------------------------- | | in[0] | ------------------- | ------->-------|------| | | | ------------------- | | | in[1] | ------------------- | out ------->-------|------| | |------->------- | ------------------- | | | in[2] | ------------------- | ------->-------|------| | | | ------------------- | | | | print.streams | | (col.width, delay) | ----------------------------------
The sequential state of the above is just blank (as are all sequential states). The parallel state is fairly bland: the internal processes are anonymous and unconnected (each being a single input from an external channel). So, this is not really worth doing and we haven't asked for it. Anyway, we provided this process – the diagrams we want are for new processes you are writing.
Aside: occam-pi supports concurrency that can be very dynamic. Modelling complex systems, such as biological mechanisms, often requires dynamism as living entities (represented by concurrent processes) are "born", move around some world (represented by more concurrent processes), break old connections (channels) and make new ones, combine with each other, split apart and, eventually, "die". Programming such systems is aided by drawing "cartoon strips" showing the possible sequences of network configurations in representative parts of the whole system and representative circumstances – we need these cartoon strips for initial design and subsequent implementation and maintenance. An example is shown in the "Overview" slides 71-82: we still have to talk you through those slides but, hopefully, you can see the idea.
Summary: there are no internal concurrency details for monitor, speed.control or freeze to diagram (unless you have an interesting, but unexpected by us, implementation!). We provided print.streams, so we have not asked you to diagram that (and it's not really worth doing – see above). Your implementations of pairs2 and the whole system q4 each have (or should have) a fixed internal network of sub-processes, so we have asked for one diagram each for them. The q4 process will have instances of monitor, speed.control, freeze and print.streams: these should be shown as empty (or shaded) boxes.
As said in the posting to everyone, external channels must be labelled (with the parameter names used in your code) and the directions of all channels must be indicated (by arrow-heads). Internal channels need not be labelled – but, if they are, either label them with the name of the internal channel used in your code or by the keyboard characters that cause messages to be sent along them (note: the latter is only for the channels leaving the monitor process, as shown in the exercise sheet).
Keywords: q4
Referrers: Question 24 (2012)
Submission reference: IN2174
For Assessment 3, will be be marked down if there is a delay from when buttons are pressed? At the moment there is a 3 line delay from then 'n' is pressed till when the numbers column resets to 0, will this be a problem?
No – that's OK. See Question 14 (2010).
Keywords: q4
Submission reference: IN2172
I have tried to implement the same functionality from my working question 3 for freezing in question 4 by taking the whole of a multiplex? array of channels (which has the information to be printed) on through the monitor process.
I know I must be doing soemthing wrong because it doesn't compile and gives the error "left-hand side must be of type CHAN, PORT, or TIMER" twice relating to two of the lines. I've looked at it for ages and can't work out why it's saying this as the thing in question is of []CHAN INT type and if it wasn't my idea of how to implement freeze that I did in class for Q3 wouldn't work.
Here is my full code for the monitor process and q4 network:
PROC monitor (CHAN BYTE keyboard?, CHAN INT reset.numbers!, CHAN INT reset.integrate!, pairs.flip!, []CHAN INT multiplex?, out!) BYTE keyboardBuffer: INITIAL BOOL running IS TRUE: INITIAL MOBILE []INT multiplexBuffer IS MOBILE [SIZE multiplex?]INT: -- Not sure if I need to do the above? -- Copied it from print.streams so I could declare an array of size -- unknown to the compiler. WHILE TRUE ALT keyboard ? keyboardBuffer ... Ed: response hidden (may change value of 'running') running & multiplex ? multiplexBuffer -- <<< COMPILER ERROR HERE out ! multiplexBuffer -- <<< COMPILER ERROR HERE :
Sorry – I can't parse/understand the second sentence in the second paragraph of your question.
I'm assuming your multiplex channel array are the three channels the flow from the two delta processes and pairs2. Rather than route this array back through monitor, it would be simpler to route a single channel from print.streams instead – that carries all the information (needed eventually to get to the screen!).
However, routing any of these channels back through monitor is a classical mistake. It sets up a feedback loop over which you have no control of the amount of traffic (because numbers2 is always generating). If the loop gets full with every process trying to output something, deadlock results. If we design a feedback loop in our circuits (and we do this frequently), we must be able to limit the amount of traffic (as in the resettable versions of the parallel implementations of numbers and integrate, used elsewhere in this exercise).
Presumably, you are doing this so that the monitor can freeze and/or control the speed of this traffic flow. But this is dangerous (see last paragraph). Instead, get monitor to send messages to other processes to do the freezing and speed control. This can be done without setting up any feedback loops.
Your lines that don't compile:
running & multiplex ? multiplexBuffer -- <<< COMPILER ERROR HERE out ! multiplexBuffer -- <<< COMPILER ERROR HERE
make some sense. I think you are wanting to use as a guard the arrival of messages on all of the multiplex? channels, the catching of the messages in corresponding elements of the multiplexBuffer data array, and with the response being the forwarding of all those messages to the out! channels.
However, the input and output symbols (? and !) can only be used for receiving or sending messages from or to a single channel, not an array of channels (which is why your lines won't compile). Your second line could be implemented as follows:
PAR i = 0 FOR SIZE out! -- these will out[i] ! multiplexBuffer[i] -- compile
But occam-pi does not allow the parallel replication of primitive processes as an individual guard, so there's nothing we can do to rescue the first of your two lines. There are ALT replicators in occam-pi (see "Choice" slides 109 onwards), but we've not done them yet in the course. Anyway, they do not do what you were wanting here.
However, what you should not have been wanting to do that. What you were trying to do was too complex (a single channel could have been used) and unsafe (the feedback loop in the resulting design has an uncontrolled volume of traffic and would lead to deadlock).
Keywords: q4
Referrers: Question 25 (2012)
Submission reference: IN2173
I am on the last stage of the assessment that asks us to implement the speed.control process.
Should we be keeping the array of 3 channels both going into and coming out of the speed.control process (and then going into print.streams), or is there a better way to do this still without altering print.streams?
Also, any general advice on what to think about when implementing speed.control is much appreciated as I am having difficulty getting my head around how to control the number of lines that will be output each second!
Only one of the channels into print.streams needs controlling. You need to work out why this is true – it's important that you see this.
Once you understand the above, your speed.control process needs only one channel in and one out. Of course, a control? channel is needed as well, on which speed-up or slow-down messages arrive.
For a required speed (lines per second), work out the delay needed between lines and use the given 'pause' process. See either of the model answers ('a1.occ' or 'a2.occ') for code that sets the line speed at the start of execution (but does not let you vary it).
However, that solution has a problem. If we have the pause delay up to one second (i.e. one output line per second) and we want to speed it up, the response to a '+' keystroke will be sluggish. If we key the '+' at the start of a one second pause in the output, nothing can change in the output until that one second pause has completed.
It would be much better for the system to respond to the '+' straight away and for the output to speed up immediately. This can't be done using the given 'pause' process – a timeout guard in the ALT is needed.
Keywords: q4
Submission reference: IN2171
Hello, for q4 do we leave the comments at the beginning of the file in or shall we delete them?
It would be nice to delete those comments (that we wrote) from your submission file – lets us get to your code quicker (and saves paper if we print). But we haven't asked for this, so it's perfectly OK to leave them.
Of course, you should include appropriate comments about your own code.
Keywords: q4
Submission reference: IN2170
I'm having a problem with my monitor method in Q4. If I write:
BYTE k: keyboard ? k number ! k
obviously this won't work because of the change in data type. I've been stuck on this for the past few days, wondering if you could work out where I'm going wrong. I can't seem for the stream to continue – it just outputs nothing.
PROC monitor (CHAN BYTE keyboard?, CHAN INT number!, integrate!) WHILE TRUE PRI ALT BYTE k: keyboard ? k ... (Ed: response hidden, but looks good) BYTE k: keyboard ? k SKIP -- Ed: was this where you wanted: number ! k :
First, the monitor needed for Q4 is a process and definitely not a method! ;)
But I don't know why you want to send down an INT-carrying channel a character received from a BYTE-carrying channel? If you really wanted to do that, you would have to cast the character into an INT:
BYTE k: keyboard ? k number ! INT k -- send ASCII code (as an integer)
See "Basics" slide 30, the program casting.occ in your examples folder and the Q&As linked from "cast" in the keyword-index of the anon Q&As ... for further information about type casting in occam-pi.
However, I'm sure you don't want to do this (and you certainly don't need to).
The code you posted (outlined in the question above) shows that you also have some misunderstanding about the ALT (or PRI ALT). You have two guards that are the same! This means: wait for the guard to become ready, when one becomes ready both become ready (because they are the same), the second guard will never be chosen (because it is listed after another guard that's ready in a PRI ALT), so execute the first guard and the process it is defending. Again, I'm sure that's not what you intended.
The monitor process does not need an ALT (or PRI ALT). All it has to do is wait for something to arrive on its keyboard? channel and respond (as you are doing in the response I hid in the code in your question).
Hope this helps.
Submission reference: IN2169
I am currently on the speed.control part of my Q4.
I have initialised delay and have set it so that each button (+ and -) changes it how they should (I don't want to give too much away - if you need to look at my code, I can email it).
What happens is that it's SUPPOSED to start at 32 lines/sec. However, for reasons unknown to me, it starts at 16 lines/sec. Here's what happens if I press +/-:
Starts at 16 lines/sec MINUS - It stays at 16 lines/sec (as if it were at 32 lines/sec) MINUS - It goes to 8 lines/sec MINUS - It goes to 4 lines/sec MINUS - It goes to 2 lines/sec MINUS - It goes to 1 line/sec PLUS - 2 lines/sec PLUS - 4 lines/sec PLUS - 8 lines/sec PLUS - 16 lines/sec PLUS - Stays at 16 lines/sec PLUS - Stays at 16 lines/sec
I have not yet implemented the BELL part of it, so I tested PLUS out by constantly spamming it when I was at my 16 lines/sec. Eventually, it gets to something ridiculous like 1000 lines/sec and actually does change to it, so it goes from 16 to 1000 if I hit + the right amount of times. I can not actually MINUSfrom there.
Where could I be going wrong in my code for this to happen? I know that I haven't implemented BELL yet, but I can't imagine not having that would stop my code from coming out at 32, 64, 128 etc lines/sec.
Thank you for mailing me your code separately. I hope my reply was helpful.
For the others, a common mistake was being made (though this doesn't explain all the bad behaviour described, but is probably one of the causes). This mistake was placing the speed control process between print.streams and the external screen! channel. If you do this and delay (by the computed amount) every BYTE that passes, it is controlling characters (not lines) per second. If the average line length were 60 characters, then the lines per second being managed would be 60 times slower than intended.
A quick fix is only to do the pause when an end-of-line ('*c') goes past! However, there is a more efficient (and simpler) way.
Keywords: q4
Submission reference: IN2168
What is the exact syntax for outputting BELL along the
error ! BELL
and getting an "I/O list item 1 does not match protocol" compile error.
That compiler error message is generated if BELL has a type that is different from that carried by the error! channel.
The include directive:
#INCLUDE "course.module"
in the program file makes available lots of things, including BELL (which is defined as a BYTE constant with VALue 7, the ASCII code for bell). So long as you haven't re-declared BELL with another type in your own code following that directive, it has type BYTE.
How is the error! channel declared, somewhere above your line that doesn't compile? It should be a "CHAN BYTE error!" parameter. If it is, then your line will compile. Honest!
For the code to execute correctly, that "CHAN BYTE error!" parameter must be connected to the second output channel parameter of the main q4 process (also called error! in your starter code file, q4.occ). At least, the ASCII code in BELL will be delivered to the terminal window running your program. So long as that terminal window is configured to react to that code (e.g. by pinging or flashing the screen or both, as does the occPlug window), then all will be well.
Beware that some older releases of the Transterpreter required the error! to be flushed, in the same way as needed by the screen! channel. The current Windows version (20110201.1855) does not have that requirement.
Correct (Unix) behaviour for the standard error channel is that anything sent there is delivered immediately to the terminal window. For the standard screen channel, characters are buffered until either an end-of-line ('*c') or flush (FLUSH) is received, or the buffer becomes full: when any of these things happen, the buffer is flushed to the terminal window.
Submission reference: IN2167
In the last lecture (Friday, 19 Oct), someone asked about the position of the replace gadget in the integrate process with a reset line ("Choice" slide 52): could it have been placed on either of the other two internal channels instead? Could you go over that again please?
I don't think I answered that question very well, changing my mind to say: "yes, it doesn't really matter where the replace is placed in the circuit". That's true ... but only if we take a fairly relaxed view of the semantics of the device. If we take a strict view, there are low-level differences in the behaviours possible from the device, depending where that replace is placed – see below. However, for real-time control applications, such as the inertial navigation component described in "Choice" slides 53-56 (and in the "occam Approach to Transputer Engineering" paper), we can take the relaxed view – see the end of this answer.
A simpler system to consider first is the numbers.reset circuit in slide 49. If no resets are sent, this just generates: 0, 1, 2, 3, 4, 5, etc. Suppose we send the number 42 down the reset line just once. The output sequence depends, of course, on when that reset happens. Possible output sequences are:
42, 43, 44, 45, 46, 47, ... 0, 42, 43, 44, 45, 46, ... 0, 1, 42, 43, 44, 45, ... 0, 1, 2, 42, 43, 44, ... 0, 1, 2, 3, 42, 43, ... 0, 1, 2, 3, 4, 42, ... etc.
However, if the replace gadget were spliced into the d channel (between succ and prefix), there is no way the 42 could ever get in quick enough to prevent the first 0 from coming out – i.e. the first output sequence line above would not be possible.
If replace were spliced into the c channel (between delta and succ), not only could the first 0 not be replaced but the reset sequence could only start from 43. Possible output sequences are:
0, 43, 44, 45, 46, 47, ... 0, 1, 43, 44, 45, 46, ... 0, 1, 2, 43, 44, 45, ... 0, 1, 2, 3, 43, 44, ... 0, 1, 2, 3, 4, 43, ... etc.
So, the actual reset number, 42, would not come out.
Compare the above with what the numbers.reset serial implementation (slide 50) can do with the same scenario (a single reset of 42). If the reset happens early enough, the 42 will overwrite the variable n on the first loop and will come out first – the 0 will not be seen. I hope it is clear that the possible output sequences are the same as the first set above – i.e. the same as those produced by the parallel implementation (slide 49), with the replace gadget between prefix and delta. So, for this scenario anyway (and actually for all), the two implementations of numbers.reset (slides 49 and 50) give rise to the same component – at least, if we are only considering the possible output sequences they produce. If the position of replace in slide 49 is changed, we have noted differences in the possible output sequences, which may or may not be significant (depending on the application in which it is used).
The "at least" qualification two sentences back needs explaining. The full semantics of a device is more than just the outputs it makes for given inputs and the timings of those inputs. We need also to know about the patterns of all events (i.e. input and output communications and, later, barrier synchronisations) in which it can engage. For instance, how may the inputs events interleave with output events? In many circumstances, we need this information to avoid deadlock.
When we consider possible interleavings for the numbers.reset implementations of slides 49 and 50, some differences do emerge. In the serial implementation (slide 50), here is the sequence of events when a single reset event occurs:
... out ! x out ! x + 1 out ! x + 2 reset ? y out ! y out ! y + 1 out ! y + 2 ...
where time is flowing downwards and x and y represent generic values. Note that the output of the reset value is the next event following the reset input. No other interleavings of input and output events are possible.
Now, consider the parallel implementation (slide 49). The above sequence is certainly a possibility but so, also, is the following:
... out ! x out ! x + 1 out ! x + 2 reset ? y out ! x + 3 out ! y out ! y + 1 out ! y + 2 ...
It all depends on where the previously cycling number is in the feedback circuit when the reset is taken by replace. If it is in succ or prefix, we will get the first pattern. If it is in delta, we will get the second.
So the parallel and serial implementations of number.reset are different. The serial form is more constrained in the way it syncrhonises with its environment (i.e. the other processes in the network in which it is embedded). Everything it does can also be done by the parallel version, but the parallel version may choose to do things differently.
Note: when considering the semantics of a process, it is only its impact on its environment that is relevant. That is why, when thinking about the patterns of events in which a process can engage, it is only those that interact with its environment (e.g. external input and output channels) that are important. Hence, in the above sequence (and the ones that follow), we only include events involving the channels from the parameter list – not the internal ones.
Now, let's get back to the integrate process, first comparing the serial and parallel versions of the original process – the one without any reset channel. Consider the serial version (slide 57). Its synchronisation pattern is tightly constrained: a strictly alternating sequence of inputs and outputs:
... out ! r -- running total, so far in ? x out ! r + x -- running total, so far in ? y out ! r + x + y -- running total, so far in ? z out ! r + x + y + z -- running total, so far ...
This serial version "buffers" one item of the flow of numbers from its input channel to its output (i.e. in any state, the number of inputs it has taken is either the same as its number of outputs or one more).
As noted in "Basics" slide 94, the parallel version "buffers" two items of the flow of numbers from its input to output (i.e. in any state, the number of inputs it has taken is either the same as its number of outputs or one more or two more). This allows it greater flexibility in the way it synchronises. The above pattern can certainly happen, but so can:
... out ! r -- #in? = #out! in ? x -- #in? = #out! + 1 in ? y -- #in? = #out! + 2 out ! r + x -- #in? = #out! + 1 in ? z -- #in? = #out! + 2 out ! r + x + y -- #in? = #out! + 1 out ! r + x + y + z -- #in? = #out! ...
where "#in?" means the number of inputs so far and "#out!" means the number of outputs so far. Other patterns may occur, so long as:
0 <= (#in? - #out!) <= 2
Note that, viewed separately, the output sequence for any given input sequence is the same for both the serial and parallel versions. However, the difference in buffering capacities may be significant for deadlock analysis. The more constrained pattern of synchronisation forced by the serial version increases the potential for deadlock in a poorly designed application that uses it.
Now consider the serial and parallel versions of integrate.reset ("Choice" slides 51 and 52). The serial version still buffers only one running total (either the most recently computed value or one that's just been reset). Its synchronisation pattern is also tightly constrained: a strictly alternating sequence of either an input or reset event, followed by an output event. For example:
... out ! r -- running total, so far in ? x out ! r + x -- running total, so far in ? y out ! r + x + y -- running total, so far reset ? a out ! a -- the reset running total in ? z out ! a + z -- running total, so far ...
The parallel version (slide 52) can buffer up to three running totals: one in plus (the most recent), one in replace (either the second most recent or a reset value) and one in delta (the oldest). This gives much greater flexibility to the patterns of synchronisation possible. Again, the above pattern is possible. But also:
... out ! r -- running total, so far in ? x -- 'r+x' moves through 'replace' to 'delta' in ? y -- 'y' only gets into 'plus' (which needs its other input) reset ? a -- 'a' gets into 'replace' out ! r + x -- running total, so far -- 'r+x' fed back through 'prefix' to 'plus' -- 'r+x+y' computed, moves to 'replace' and is discarded -- 'a' moves into 'delta' out ! a -- the reset running total in ? z out ! a + z -- running total, so far ...
and many others. Notice that in the above sequence, one of the running sums of input values (r+x+y) never emerged. Whether missing this value is significant depends on the application.
Now, consider what happens if the replace gadget in the parallel implementation (slide 52) were positioned elsewhere. For one thing, the buffering capacity between the in and out channels drops back to two. If replace were spliced into the channel between prefix and plus, the reset value would never emerge as itself – it would always first have been added to the next input value. For example:
... out ! r -- running total, so far in ? x -- 'r+x' moves to 'delta' in ? y -- 'y' only gets into 'plus' (which needs its other input) reset ? a -- 'a' gets into 'replace' and moves on to 'plus' -- 'a+y' computed in 'plus', cannot move on yet out ! r + x -- running total, so far -- 'r+x' fed back through 'prefix' to 'replace', which discards it. -- 'a+y' moves to 'delta' out ! a + y -- the reset running total (with added 'y') in ? z out ! a + y + z -- running total, so far ...
In the previous example, the contribution of 'y' was never seen in the running sum outputs. This time it is, but added to the reset value (which is not seen directly).
If replace were spliced into the channel between delta and prefix, the reset value would never emerge as itself – it would always first have been added to the next input value (as for the previous version). The difference is at start-up – there is no way a reset could happen fast enough to prevent the first output from always being the first input added to the initial 0 from prefix (i.e. the first output is always the first input).
A sequence of events (channel communications and, later, barrier synchronisations) in which a process can engage is called a trace.
The last 7 sequences above show extracts from traces of the processes being considered. For clarity, we've listed them in two columns: one for input and one for output. For traces, consider them listed in one column, keeping the ordering.
CSP (Communicating Sequential Processes), the formal algebra that underlies occam-pi, defines three semantic models with increasing capabilities: traces, failures and divergences. The simplest is the traces model, which enables verification of safety properties (e.g. that a process will not do something bad). The other two concern liveness properties (e.g. that a process will actually do something): failures enable deadlock analysis and divergences address livelock.
In the traces model, the semantics of a process is just defined by: the set of all its possible traces. Two processes are equivalent if their traces are the same set. A process, P, is a refinement of a process, Q, if the traces of P are a subset of the traces of Q. This is where safety analysis comes in: if a process Q is known to have safe behaviour and we implement a process P and prove that it refines Q, then we know that P also must be safe (because every trace that P can do, Q can do and Q only does safe things). In such a scenario, Q is usually described as a specification for P.
The position of the replace component in the parallel circuits of numbers.reset (slide 49) and integrate.reset (slide 52) does impact on their formal semantics.
The serial numbers.reset (slide 50) is a traces refinement of the parallel implementation in slide 49. The serial integrate.reset (slide 51) is a traces refinement of the parallel implementation in slide 52.
If, however, the replace component is repositioned somewhere else in the circuits, there is no formal relationship between the serial and those parallel versions. Whether the differences (see earlier) matter depends on the applications to which they are put.
For the inertial navigation component (slides 53-56), they don't matter. All the versions of integrate.reset (serial or any of the three parallel implementations considered above) deliver running sums and allow resets at any time. The precise interleaving of inputs, resets and outputs doesn't matter – the important matter is the accuracy of the input sample values and the accuracy of their sampling times (which must be evenly spaced). If some running sum is discarded when a reset happens, it doesn't matter: that value was suspect anyway, which is why integrate.reset was being reset. If the reset value does not get output itself, it doesn't matter: the value that comes out is the reset value plus the latest input, which is more up-to-date than the reset value alone. Finally, if we can't reset before the first number appears after integrate.reset is switched on, who cares?
Keywords: q4 , csp , formal-semantics , reset
Submission reference: IN2166
I have had a little bit of trouble implementing the flip behavior to pairs expressed in Q4. I understand what it is meant to do but struggling at finding a way of implementing it that isn't long and overly complicated. I wanted to avoid a modified plus process inside pairs2 and wanted to introduce the new component to do the job as this makes the most logical sense in terms of the rest of the program. It also suggests that a suitable process has been described and from looking through those available I felt that the closest match would be the (Ed: rest of sentence deleted as it gives too much away).
I simplified my (Ed: name deleted) process slightly and with my code currently looking like this I get no output. Confused at what's going on! I've tried running through process diagrams on paper and still stuck ...
PROC pairs2 (CHAN INT in?, flip?, out!) CHAN INT a, b, c, d, flip.decision: INT any: ... (Ed: variable declaration hidden, used in flip response below) WHILE TRUE SEQ PRI ALT flip ? any ... (Ed: response to flip guard hidden) PAR delta(in?, a!, c!) tail(a?, b!) ... (Ed: process instance hidden) plus(b?, d?, out!) :
Your pairs2 has two errors.
The biggest one is that you start a PAR network of processes – all of which run forever – in the body of a WHILE loop. The first time that loop is entered, once it reaches that PAR all the components of that PAR start up and never finish. So the loop never loops, only executing the PRI ALT (at the start of its body) just the once. That's probably not what you meant to happen.
The second error is that your PRI ALT only has one guard. That means just wait until that guard is ready. The code may as well have been written:
PROC pairs2 (CHAN INT in?, flip?, out!) CHAN INT a, b, c, d, flip.decision: INT any: ... (Ed: variable declaration hidden, used in flip response below) WHILE TRUE SEQ flip ? any ... (Ed: response to flip guard hidden) PAR delta(in?, a!, c!) tail(a?, b!) ... (Ed: process instance hidden) plus(b?, d?, out!) :
Again, that may not be what you wanted.
These two misunderstandings need correcting. Hopefully, what needs to be done then becomes much clearer. Your modified (Ed: name deleted) process looks good.
Keywords: q4
Referrers: Question 25 (2012)
Submission reference: IN2165
In question 4, we have to deal with an array of channels. I was wondering what the syntax is for doing so in regards to the parameter that goes in the call to print.streams?
See "Basics" slide 101. That instance of print.streams takes the input-ends of an array of 4 channels. In Q4, print.streams needs the input-ends of an array of 3 channels. The syntax for this is the same – the number of channels in the array doesn't matter.
Keywords: q4
Submission reference: IN2164
I'm currently working on Q4 and while my freeze/error-inducing process in Q3 works exactly as specified/intended, I can't seem to get the control working in Q4 for reasons I don't understand.
Here is the code for my monitor process, which is only trying to enable my numbers2 process to be reset:
PROC monitor (CHAN BYTE in?, CHAN INT numbers!) ... (editor) code omitted :
It should do, as far as I can see, run round the loop doing nothing until an 'n' is pressed – when it should output a 0 to the numbers! channel. The problem is that when I try and insert it in to the network it causes all output to stop from the numbers2 process, defined as such:
PROC numbers2 (CHAN INT out!, reset?) ... (editor) code omitted :
The process will also not respond to any keyboard input.
If I remove my monitor process from the network, the numbers2 process functions fine ... so it certainly feels like it should be my monitor process that's causing the issues. Am I missing something very obvious?
Your monitor is not running "round the loop doing nothing until an 'n' is pressed". It is busy polling the keyboard channel! It uses a PRI ALT governing that channel against a SKIP guard. If no key press has been made, the keyboard input guard is not ready and the PRI ALT takes the SKIP guard. The latter was defending only a SKIP (i.e. do nothing) process, so execution loops around back to the PRI ALT.
Your monitor process is continually active, racing round this polling loop over 100,000 times per second on the Transterpreter (or more than 100,000,000 times per second with the KRoC runtime), consuming every processor cycle available. The other processes can make little headway against this torrent of (useless) activity – the system is effectively livelocked. Take a look at the processor loading (e.g. on the Windows Task Manager) when this is running – one of the cores will be almost at 100%, with the others mostly idle (the Transterpreter does not multicore schedule). If you're using KRoC (which does multicore schedule), the system will work ... but one of the cores will be at 100% loading and getting rather hot. All that work is quite unnecessary and unacceptable for a real-time system (with hard deadlines to meet) or an embedded system (with limited battery life).
This is a classic mistake – see the warning at the bottom of "Choice" slide 30.
Solution: save the planet and don't poll for keyboard input! Just wait for one to arrive (i.e. all you need is the input line). Waiting for a channel input costs nothing in processor loading and the waiting process jumps to life when something arrives.
Keywords: q4
Submission reference: IN2162
Question 4 for the assessment states: "New processes, numbers2 and integrate2, must be made that accept the new reset signals and respond appropriately. Maintain the same style of implementation as before. Don't modify any internal processes – but insert an extra one somewhere to do the job."
It also states earlier that numbers, integrate and delta are accessible from the course.module included. If we have to redefine numbers2 and integrate2 based on the ones included, is there anywhere on raptor etc. where we can look them up and copy the code from course.module into our q4.occ file and then make changes to them?
Sorry, I thought the source files for course.module were in the Transterpreter release, which most have downloaded. They certainly are in the Kroc release, which is worth getting if you have Linux or a Mac (look for modules/course/libsrc).
Of course, you must have these source files and I have copied them to raptor (and swallow) at:
\courses\co538\course-module\ (read the README.txt)
You don't really need these files to copy numbers, integrate etc. to your q4.occ starter file and then edit into the extended versions needed for the exercise. They are only 7 lines of code each and, anyway, can be copy-pasted from "Choice" slide 88.
You need these files for curiosity browsing and studying. Many of the processes have implementations that are really complex and scary (e.g. course.REAL32TOSTRING in float_io.occ, which converts a 32-bit floating-point real into ASCII text – a task that just is complex and scary). Ignore those! But there are a lot that will reward reading. Be curious. We are always here to answer your questions.
Keywords: q4
2011 |
Submission reference: IN2060
its cutting it a bit fine i know, but how do i ipmlement the speed control section for the last part of the assigemtn, ive been sticuk on thisfor ages, ive fiigured out that i need to use a timer, im just not sure how best to utilize it.
I'm afraid you have to ask questions a little more specific than: "how do I do this part of the assignment?".
However, we will say this ...
The model answer has two versions for speed.control. Version 0 uses only the pause(delay) procedure to control output line speed: it has to respond to speed control signals and, of course, the data flow it's controlling. It is very simple but has some not good properties (such as not being able to respond promptly to speed-up signals when executing a long pause). Nevertheless, it would get good marks, :).
The other version uses TIMERs directly and responds quickly to speed-control signals at all times – but it's a bit more complex.
Keywords: q4
Submission reference: IN2059
Hi, I'm really struggling with the speed.control section. I have a process that takes 1s and 0s given to it by my monitor, and then sends then either halves them, or doubles them depending on what is received. This is then sent to another process which takes a value from the speed.control process, and outputs a line of digits. After doing this, it checks with a timer to see if the time figure is greater than speed. If it is, it waits until the timer has again passed the speed value. The problem is, when I key plus or minus, nothing seems to happen? Any thoughts on where I've gone wrong?
I don't understand what you means by "either halves them, or doubles them depending on what is received"? You say your process is receiving 0s and 1s, presumably these are INTs? But if so, halving a 0 or a 1 gets 0, doubling a 0 gets 0 and doubling a 1 gets 2. I don't understand how that helps ...
You also talk about comparing a "time figure" with a "speed" ... which is like comparing chalk with cheese. You should only compare time values against time values (which may have been calculated from a previous time value and a gap interval). For example, the gap interval (in microseconds) for a speed of 256 lines per second would be 1000000/256.
Hope this helps ...
Keywords: q4
Submission reference: IN2056
I am having trouble implementing the "pairs2" process for the 3rd assessment. Below is what I have so far, but it doesn't work:
PROC pairs2 (CHAN INT in?, out!, inject?) INITIAL BOOL flip IS FALSE: WHILE TRUE PRI ALT INT injected: inject ? injected flip := NOT flip SKIP CASE flip FALSE pairs (in?, out!) TRUE differentiate (in?, out!) :
Please never show someone your code and ask why it doesn't work! Instead, explain why you think it does work – i.e. talk through the code, saying what you are expecting it to do and saying why. Nine times out of ten, either yourself or the person to whom you are explaining will then see why what you are saying is wrong: some unfounded assumption you have made or something wrong with the mental model you have about the ideas/constructs you are using.
The problem here is that once either "pairs" or "differentiate" is instantiated in the above code, it never terminates (because its components all have infinite loops). This is the mistake in your mental model of what is happening here. As a result, the loop in your "pairs2" above will never loop! As such, any attempt to communicate on the "inject" channel after either "pairs" or "differentiate" has been started (and that will be within nanoseconds of the start of your system) will not be accepted and your "keyboard.monitor" will be forever blocked. Your system should still be running ... but you have lost control.
The correct way to go about this is to change something inside the existing "pairs" process, rather than trying to replace the whole thing. However, if you can't figure out that particular solution, you can have both "pairs" and "differentiate", but running in parallel, with a switch process at the front (which sends data to one or the other) and a simple multiplexer component at the other side which collects output from both. However, that's a rather heavyweight solution, but at least it works!
Keywords: q4
Submission reference: IN2054
To partially answer my own question (invalid reference to another question!); the deadlock seems occur arbitrarily whenever the output lines per second is > 32. I was running the program directly from vim (!./q4), which I presume buffers and can't output quick enough?
There is no deadlock if I run the program directly from the terminal (urxvt).
That is slightly odd — even if vim doesn't take the output quickly, it should just stall the program, not deadlock it completely. KRoC does behave slightly differently if the standard I/O isn't a terminal, but without investigating I'm not sure how vim implements this (i.e. whether it just uses pipes or whether it opens a VT pair for communication).
PHW adds: I just tried running the model answer in the way described (from vim) ... and it works just the same (i.e. correctly) as when run directly.
Keywords: q4
Submission reference: IN2053
I am at the point where I have an implementation of speed.control. However, pressing any of the monitored keys in rapid succession causes a deadlock. Is this to be expected?
Probably not — it hints at problem in the design of your solution. Without seeing the code, my immediate thought is to wonder if you have some components polling their control channels, e.g.:
WHILE TRUE PRI ALT BOOL any: control ? any ... do something useful SKIP SEQ in ? any ... other stuff
Although it takes more than just this, you could end up in a situation where the code above is stuck waiting for data from "in" or a subsequent output, but some other component in the network is stuck trying to send data down the "control" channel, and as a result, is stopping the input (or output) in the above code from happening.
Check for cycles of connected processes in your solution and look for deadlock possibilities in there.
Keywords: q4
Submission reference: IN2051
Same problem as in Question 18 (2011):
pause(1000000)
results in waiting about 30 seconds. I am using the Transterpreter on Windows 7 64-bits.
Same waiting time with:
TIMER tim: INT timeout: SEQ tim ? timeout timeout := timeout PLUS 1000000 WHILE TRUE SEQ tim ? AFTER timeout
In order to have about a delay of 1 second, I need pause(33333). But ... pause(1000000) in print.streams does give 1 second.
I suspect your code ... please send to Fred <frmb@kent.ac.uk>. We won't tell you what's wrong ... but will point to any areas of obvious concern!
Keywords: q4
Submission reference: IN2049
When I output BELL to error! in q4 it does not BELL error message the console. However, it just exits the program with error code 1.
Is this meant to happen or is there something wrong with my code?
That should not happen! Please send Fred <frmb@kent.ac.uk> your code.
Keywords: q4
Submission reference: IN2050
Hi, I am very confused with how to go about implementing the freeze part of q4. Unfortunately, I was not able to do this in q3 either! Help!
Sorry – can't just tell you the answer ... it's too simple ...
Think this way: a data stream through a channel only flows if the processes through which it is routed are programmed to execute appropriate input and output instructions. If those instructions are not being executed (e.g. the code is doing something else ... like waiting for some signal to resume the flow), the stream cannot flow. The default action is no action. Data flows only if it is programmed to flow. What you see (in your code) is what you get.
Hope this helps!
Submission reference: IN2047
When I 1 000 000 of delay for the pause method (which should be 1 second when I run it it seems to be delaying for about 70 seconds is this purely down to the TVM or is it something else if so what am I missing?
The grammar in your question does not parse. So, it's a little difficult to understand.
However, the code:
pause (1000000)
will pause the executing process one second (= 1,000,000 microseconds) on either the KRoC compiled system (for Linux and Macs) or the Transterpreter (so long as you have not switched it to the runtime for the Lego Mindstorms ... in which case, the pause would be 1,000 seconds (= 1,000,000 milliseconds)). Of course, you must not have changed the implementation of the pause process in your starter file.
There is no way it will result in a delay of around 70 seconds. If still a problem, please mail Fred, <frmb@kent.ac.uk>, your code and ask nicely, :).
Keywords: q4
Referrers: Question 21 (2011)
Submission reference: IN2048
Hi, I'm just doing the speed control part, and it has come to my attention that there are two different versions of more-exercises.pdf floating around. I personally used the one on raptor, but I have found out from a friend the moodle one says the upper limit should be 256 lines/second, where as the raptor one says it is 1024 lines/second.
Which is it, and can the old versions of files be removed to avoid confusion please?
I've just checked. There are two ways to find more-exercises.pdf from the Co538 Moodle page: from the Assessment 3 box and from the "Exercise sheets ..." link in the Teaching Resources box. These link to different, but identical, files. The same-named file on raptor (in courses\co538\exercises\) is also identical (and says limit the rate of output to 256 lines/second). Your q4.occ starter file (unless we have made a mistake there) also says 256. The q4.occ on raptor (in courses\co538\exercises\) says 256.
There used to be a version where the limit was 1024. We lowered it because your terminal emulator probably can't go that fast and, if it could, you wouldn't be able to read it! We must have an old version somewhere you can access ... please mail Peter, <phw@kent.ac.uk>, where - thanks!
PS: nobody would lose any marks for setting a limit of 1024 instead of 256.
Keywords: q4
Submission reference: IN2046
In q4, I'm building the first network diagram where you have to connect all the deltas into the printstream, but it says there are too many actual parameters. Is there any way to resolve this please?
There is no printstream process. There is a print.stream, but that takes only one input stream and is only used for the first part of this exercise. For the first modification (with the deltas), there are three streams that need printing and the data-flow diagram shows print.streams (plural) to be used.
Note also that print.streams (in your q4.occ starter code) takes four parameters – the third being an array of channels (the three streams, in this case, for printing). See Basics slide 100 for an outline of its use: outline because the example in that slide prints from four channels and, to avoid distraction, does not have the first two parameters (column width and delay) that are defined for the print.streams given in the starter code.
Keywords: q4
Submission reference: IN2045
This is a follow-up to Question 12 (2011) ...
PROC freeze.control (...)
Editor: rest of question omitted.
Thank you for giving more information on the area of your problem. However, without seeing your code, I can't help. The description you give is still not enough to diagnose your error.
If you send me (<phw@kent.ac.uk>) your code, I will point out any misunderstanding of system behaviour that's apparent (but, of course, I cannot correct your code).
Keywords: q4
Submission reference: IN2044
For assessment 3 (q4), it is required for pairs to be flipped to differentiate on the push of a button and reverse if pushed again. How would I implement this e.g: what is the best structure to use: IF or CASE?
If there is a 2-valued decision to make, then a boolean expression managed by an IF is appropriate. If there is an n-way decision and (n > 2) and the decision is to choose between a known set of options (represented by constant integer or character values), then a CASE is appropriate.
We have not yet presented the CASE structure in the lectures, but there is a forward reference to it at the end of the the question (Exercise 4) on the more-exercises sheet. The note there recommends its use for processing character input from the keyboard channel (i.e. in your monitor process).
Keywords: q4
Submission reference: IN2043
In exercise 4, I have a freeze.control proc that takes the output of print.streams. The behaviour is controlled by monitor.
If I do not forward the input to screen AND do not read the input, the program seems to lock (no deadlock error).
However, if I just read the input without fowarding it, I can freeze than restart to output to screen without problems.
I can't figure out why.
Sorry – cannot understand your question. In paragraphs 2 and 3, to which process does the "I" refer and to which channel does "input" refer? In para 3, to what channel is the input being "forwarded"? Thanks.
Keywords: q4
Referrers: Question 15 (2011)
Submission reference: IN2042
This question relates to the pairs2 implementation of assessment 3 (q4.occ).
In order to implement this process, I must have a component that will 'flip' the addition to a subtraction. Quoting from the text: "A neater way is to leave the existing sub-components alone, but introduce an extra component into the circuit to achieve the required effect. [A process suitable for this new component has been described in the course.]"
What process is this? I have not seen such a process?
Answering your questions in reverse order: yes you have ... and you have to find (or re-invent) it yourself! ;)
Keywords: q4
2010 |
Submission reference: IN1916
Will we lose marks by not including ASCII data-flow diagrams after adding freeze and speed.control components?
Nope! We should have asked you to include network diagrams in some form (ASCII art, hand drawn on paper, electronic media) ... but we didn't, :(.
I'm sure you did draw some diagrams anyway – it's very difficult to know what you are doing if you don't!
Keywords: q4
Submission reference: IN1915
I have a couple of questions regarding the speed.control modification in Assessment 3.
If you halve the initial speed of the system right down to 1 line/second, the system won't let you go any slower than 1 line/second, as specified. But if the speed is doubled at any point by pressing '+' before slowing it right down like this, the slowest the system can output becomes 1 line every 2 seconds. Could you possibly give me any indication why this might be?
Early on in the assessment pdf, when it talks about generalising input to the reset processes, it mentions that monitor should only output zeros. But I use different integer values on a single channel to discriminate between plus and minus signals in my speed.control implementation. Is this acceptable or should I use a plus channel and separate minus channel?
Thanks! :)
This is not entirely unexpected behaviour in some cases. Not having seen your code, I'm guessing that at some point you cap the integer at the top/bottom to impose the limit. However, the maximum value is probably not a power-of-2 multiple of the initial value, which is why you get this slightly odd behaviour — one sequence of integers as you speed up, which is capped when it reaches the maximum speed, and a different sequence of integers as you slow down (and vice-versa). Hence you get this behaviour. It would be better if you could fix it though — the fact you get the behaviour you describe suggests something is slightly wrong somewhere. Try building a test-rig for your speed.control process to see what it's doing.
What you have is fine — the zeros are only for resetting the number-processing components. The point is that you should be able to reset numbers or integrate to any value, i.e. the reset component used in them is general.
Keywords: q4
Submission reference: IN1913
Hey, When I add my speed.control before the print.streams method, all of the lines get outputted at once for some reason.
Say I am at 2 lines per second, rather than 1 line being outputted at 0.5 seconds and then the next being outputted 0.5 seconds later, 2 lines are outputted each second.. :( Is this what's supposed to happen? :<
Also, not sure if outputted is a word, but if it isn't it should be >.> Thnx!
Sorry – that's not supposed to happen! I'm afraid there's something wrong in your speed.control logic (probably).
Sorry – outputted is not a word. The word you are looking for is: output!
Keywords: q4
Submission reference: IN1911
Hi, I'm currently working on step 3 of Assignment 4 – changing pairs to subtract rather than add. Without wanting to go into too much detail I've got both a modified pairs process and another new process which uses a boolean flag to toggle. The last time I used a flag in such a way it was pointed out to me that it was unnecessary and I'd missed an alternate way of doing things.
Am I going down the wrong road again with regards to this? Thanks.
Your solution sounds good.
For many cases, remembering state in global variables leads to more complex code than just letting process logic flow through the states (where the state of the process is represented by where the logic has reached, rather than data in a variable).
However, for the toggle process you describe, using a boolean flag (declared global to the loop) is probably simplest.
There are no complete rules for things like this that cover all circumstances we encounter – only guidelines. The guideline two paragraphs above often works simply and elegantly (and is often missed by too much thinking along OO lines) – just not here. Always look for the simplest solution.
Keywords: q4
Submission reference: IN1912
Hello, my bell isn't working ...
If ALL my code does is output a BELL on the error channel, it works fine! But when I add my processes in, to run AFTER outputting the BELL (SEQ), nothing happens :/
I don't understand! :((
Sorry – see the answer to Question 15 (2010). You probably have the same trouble and the same fix should work.
Submission reference: IN1910
In the speed.control process when it comes to outputting BELL nothing seems to happen. I have also changed my code so that whenever I press the '-' key it outputs BELL without doing anything else but this still has no effect (no inverting of colours/screen flash etc). I'm using a Windows machine so in reference to the Question 11 answer this may be different to a Macbook.
Sorry – this seems to be a bug in the Windows version of the Transterpreter. I finally found a Windows machine and tried the model answer. As you and others have observed, no reaction to BELL, :(. The problem is that characters sent to the error channel are not automatically flushed as per spec (and as we have told you, for example at the end of our answer to Question 11 (2010))!
This is only a problem with the Transterpreter on Windows. On the Mac – and, probably, Linux (I've not tried that yet) – the error channel correctly flushes every character. The kroc run-time also manages the error channel correctly.
We will get this fixed. Meanwhile, wherever you send BELL to the error channel in your solution to q4, follow this with a FLUSH – e.g.
error ! FLUSH
Apologies.
Referrers: Question 16 (2010)
Submission reference: IN1908
In Q4, while testing I noticed that when pressing 'n' there is a delay between my reset in the increment:
0 0 1 1 1 4 <-- 'n' key pressed 2 3 9 3 6 16 4 10 20 0 10 21 <-- finally! 1 11 24
This isn't allowed, is it?
Yes, it is! See Question 7 (2010).
How quick the reaction to your reset is depends on how much is already
in the pipeline to the screen ahead of where the reset is processed.
The 'n' keypress is processed inside inside numbers2,
whose numbers generated in future start again from 0.
Ahead of that are numbers already generated in a delta,
integrate2, another delta, pairs2 and
print.streams.
Your reset clearly can have no effect on those numbers and you have to watch
them come out of the system before you see the reset
If your screen output is set very slow (e.g. one line per second), there will be numbers backed up in all stages of the pipeline and the response from the system to the reset will be delayed (as you observed). If your screen output is very fast (and it would need to take around a million lines per second - unfortunately, your terminal window cannot manage that), the pipeline will be empty and the response from the system to the reset will be immediate. occam-pi is good for real-time control.
Keywords: q4
Referrers: Question 22 (2012)
Submission reference: IN1907
Hi, For the freeze control in Q4, can I change the whole network diagram from the previous modification or should I stick to the old diagram, but with new processes included??
Well, you may design a different network diagram if you have a better way of arranging things. However, the question asks for features to be added incrementally – e.g. when adding freeze control, the previous reset controls must be retained.
Process orientation enables safe incremental design and implementation. Because the internal logic and data structure of each process is isolated (strictly private to the process), processes only impact on each other when they communicate (or, we will see later, barrier synchronise) and that can only happen with the explicit agreement of the processes involved. So, nothing can happen to a process behind its back! This means that as we add processes to a network, only those parts of the network to which they are explicitly connected (by channels or, later, barriers) are affected – the rest of the network behaves as before.
There is one caveat to the above. Whilst plugging in new processes cannot alter the behaviour of existing ones (and the sub-networks they form), we do have to ensure that the network overall remains alive. Any modification to a network may introduce a possibility for deadlock and we must take care not to do this! We will be teaching design rules that guarantee freedom from deadlock ... but these are not complete (i.e. they don't cover all the designs we need to make). For the others (e.g. the dining philosophers' college), we need to make individual analyses to remain safe. It is a challenge to make such formal analysis routine ... and, if time, we shall have a go in this course! :)
So in answer to your question here, we recommend incrementally modifying the old diagram (as has been done in the exercise sheet in the four developments of the q4 process network) by connecting in new processes with the necessary behaviour. It's the simplest way to go – for both the freeze and the speed controls.
Keywords: q4
Submission reference: IN1906
To implement the freeze control, are we allowed to add a new process in Q4? This process would communicate with the monitor process.
Yes. In general, it's a good idea to implement new functionality with a new process!
The new process for freeze control can be identical to the control process from Q3 (just implementing the freeze part – not the other stuff provoking deadlock etc.).
Keywords: q4
Submission reference: IN1905
Using the Transterpreter, if you send a BELL down the error channel, is it meant to actually do something, because for me it does nothing or is that just the Transterpreter?
The BELL character is ASCII code 7 (known as "bell"). On old teletypes, when this was received it actually rang a real bell. On later video terminals, it caused a beep sound. In terminal windows (on modern desktop screens), what happens depends on how your terminal emulator is programmed (sometimes this is user configurable). Many effects are possible:
The terminal window in the Transterpreter JEdit occPlug does the third action above (screen flash) – at least, that's what it does on my Macbook.
Here's a short program (test-bell.occ) that you can cut-and-paste and compile-and-run:
-------------------------------------------------------------------------------- --** Test BELL on screen and error channels. #INCLUDE "course.module" --* the main process -- -- @param keyboard The standard input channel (stdin, in Unix-speak) -- @param screen The standard output channel (stdout, in Unix-speak) -- @param error The standard error channel (stderr, in Unix-speak) -- PROC test.bell (CHAN BYTE keyboard?, screen!, error!) BYTE ch: SEQ -- test BELL on screen channel ... out.string ("screen: this line will end with a BELL (press a key) ...", 0, screen!) screen ! FLUSH keyboard ? ch screen ! BELL screen ! FLUSH -- the effect of the BELL, if any, happens now! out.string ("*c*n", 0, screen!) keyboard ? ch -- wait for keypress. This is to let the terminal -- emulator complete its reaction to the BELL on -- the screen channel. Otherwise the terminal -- emulator mixes that up with the following text -- sent to the error channel. By default, screen -- and error channels are crudely multiplexed to -- the same output device. From Unix, they can -- be separated. -- test BELL on error channel ... out.string ("error: this line will end with a BELL (press a key) ...", 0, error!) keyboard ? ch error ! BELL -- the effect of the BELL, if any, happens now! out.string ("*c*n", 0, error!) : --------------------------------------------------------------------------------
Note: the screen channel needs a FLUSH in order to force out text that doesn't form a completer line (no line-feed character). The error channel, however, flushes every character sent automatically.
Referrers: Question 15 (2010)
Submission reference: IN1904
Will the model answer for Q3 be available to look at before the Q4 submission deadline?
Sorry, no! Q3 is a warm up exercise for Q4. The freeze control it asks for can be reused intact in Q4.
Submission reference: IN1903
In relation to Question 8 (2010): I get that output if I remove speed.control. The only other instance I've got it to work correctly is putting speed.control before/after my freeze process. The problem is that delay() acts strangely (very slow compared to invoking it from print.streams).
I'll have another good crack at it tonight and if I fail I'll email you :)
If you put the speed.control process after the output from print.streams, it'll be controlling the delay between each character sent to the terminal. As terminals are line-buffered (unless you explicitly FLUSH each character), you will have to wait some time before each line appears (the delay per character multiplied by the number of characters in the line).
If the delay is called from within print.streams, then you'll be getting the delay for each line of output, rather than each individual character, so it will generate screen output faster.
Rather than clutter up print.streams with additional speed control logic to adjust delay times, keep that logic separate in your new speed.control process but get it to control the speed of (any) one of the channels going into print.streams.
Note: using the delay process to force delays in the speed control logic has the following problem. Whilst the delay is on-going, the logic cannot respond to further instructions – such as to speed up. For instance, if the speed has been wound down to one line per second and we key in a '+' to make it go faster, the keystroke cannot be responded to until the end of the current delay period and – with one second intervals – that will feel very unresponsive. Consider how to solve this!
[Hint: your speed,control must already be ALTing between the input channel (whose speed it is controlling) and a control line (for adjusting speed). Rather than use a delay somewhere, get it to ALT between the input channel, control channel and a timeout guard. With suitable logic, it can now be programmed to respond immediately to any control signal, regardless of how long it is till the next timeout.]
Keywords: q4
Submission reference: IN1902
For Q4, why does flipping to minus within pairs2 result in a number being generated that is 1-bit from the correct answer? Now that I've implemented speed.control the number being generated by pairs2 is 1 from the correct answer if it's doing addition and 2 from the correct answer if it's doing minus. I've tried putting speed.control in different places but either delay() functions strangely or I deadlock (trying not to give too much away). I'd like to learn more about this strange behaviour so I can fix it with my current set-up. Any hints? :)
Check the model solution output given in the answer to Question 7 (2010).
It sounds like you are doing something wrong. Does the above allow the "1 from the correct answer" you mention? Which bit in the number is "1-bit from the correct answer"? "2 from the correct answer" sounds definitely wrong.
But it also looks like you are doing something right! Try mailing your code to one of us. We won't correct it but will give you a pointer if we can.
Keywords: q4
Referrers: Question 9 (2010)
Submission reference: IN1901
For Q4, the pairs2 process is it okay to write a new toggle process that upon a 0, say, being put down its reset channel, it outputs the opposite of values that arrive (instead of the same). For example, if 2 was input, the opposite (i.e. -2) would be output?
Also is there somewhere we can find an example of the output we should get upon the flip being activated?
That toggle process sounds a really good idea!
Here's output from the model answer:
77 3003 6084 78 3081 6241 79 3160 6400 80 3240 6561 81 3321 6724 <-- 'p' keyed in round about here 82 3403 6889 83 3486 84 84 3570 85 85 3655 86 86 3741 87 87 3828 88
Keywords: q4
Referrers: Question 8 (2010) , Question 14 (2010)
Submission reference: IN1898
When it comes to flipping the adder within the pairs process to a subtractor, it states in the q4.occ starter file that after we do this: "...we see the natural numbers sequence".
In Exercise 4 in the "more-exercises" sheet, it states: "in its flipped mode, the modified pairs2 process becomes a differentiator so that the stream of numbers produced are the same (bar a bit of slosh) as those coming from numbers2".
This means positive numbers must be produced. However, back in the q4.occ file it also states: "The first 'p' zaps the adder process within pairs so that it becomes a subtractor, taking the numbers arriving from the tail process from those arriving directly from the delta".
This means that negative numbers are produced.
Unless I am doing something wrong, which is entirely likely, do these two statements not mean different numbers will be produced? Which is the right one if this is so? Does the aforementioned "slosh" mean the minus sign?
You are not doing anything wrong!
This is our mistake, for which we apologise. The quote you gave from the q4.occ starter file tells you to do the subtraction the wrong way around. Stupidly, this was a known error – see Question 18 (2006). It was corrected in the starter file but, sadly, an old version has crept back in!
The q4.occ starter file has been corrected again – hopefully, we have better version control in place now! The corrected file can be found on raptor at:
\courses\co538\exercises\q4.occ
Note: when marking this assessment, no marks will be lost for programming these subtractions the wrong way round (i.e. for doing what the q4.occ starter file specified) – even though that leads to (a decreasing sequence of) negative numbers. Apologies.
Keywords: q4
Submission reference: IN1899
I'm currently working on Q3 and have managed to get the output to the screen to freeze when 'f' is received. When the next key is pressed, numbers are again put to the screen but the process has kept on running and therefore some numbers are not printed. Is this correct or do I have to stop the numbers from incrementing (any pointers on how to do this would be appreciated)?
It's not correct!
The question (Exercise 4) in the "more-exercises" sheet does say: "from wherever it left off". Keying 'f' should freeze screen output, which should resume from where it froze when the next character is entered.
It's actually simpler to program the above behaviour than to leave the demo process running without printing its output. Remember that a channel cannot lose any messages: if the receiver does not input, the sender just blocks (until such time as the receiver does input from the channel ... at which time, the message comes across). So to lose message from demo, we would need to program control explicitly to continue to take in messages but not forward them! To block messages from demo, just don't listen to it – simple!!
2009 |
Submission reference: IN1825
I'm working on the speed control on q4 and I'm getting some very strange behaviour, whenever I use the pause process, regardless of what value I pass it to delay by, it always seems to delay by approx 1 second, whether I set the delay value to 1, 10, 100, 1000, 10000 or any other number in between. And when my speed control changes the delay value, I can't see the result since it just insists on printing at that constant rate of about one line per second.
If I remove the pause completely, it outputs several thousand a second (since print.streams is initialised to -1).
Any idea why this might be happening? I'm in panic mode right now!
Sorry – you submitted this with just over an hour to the deadline ... which was a bit late for us to respond! In any case, without seeing your code, there's not enough info to suggest what's wrong ... and we wouldn't let you post full implementations of things like speed control and ask why it doesn't work (see paragraphs at the top of each anon Q&A page).
Make sure you get good feedback from whoever marks your submission! Complain if you don't ...
Keywords: q4
Submission reference: IN1819
"A neater way is to leave the existing subcomponents alone, but introduce an extra component into the circuit to achieve the required effect. [A process suitable for this new component has been described in the course.]"
Is there any chance of a hint on where to find this?
Well, you'll need a component that's PRI ALTing to react to the reset message to your pairs2. So, look in the choice slides for examples ...
Keywords: q4
Submission reference: IN1818
Hi, I have got a problem with the freeze functionality in q4. I have managed to implement it and it freezes an output when requested and resumes it after receiving next character, but the print streams then prints one extra column of ones. (I assume this is because I had connected the freeze.control with monitor and print.streams processes in order to avoid deadlock) Is there any way to get rid of this extra column being printed?
Sorry, I've no idea how you can get an extra column of numbers (ones) after freezing and un-freezing!
I don't understand what you mean by connecting: "the freeze.control with monitor and print.streams processes"? Do you mean connecting the freeze.control between and print.streams? That sounds like you are introducing an extra channel into print.streams, which would account for the extra column – but that extra column would always have been there?!!
No. You should be introducing a freeze.control process into an already existing channel, between an already existing somewhere and print.streams (to which it was previously directly connected).
Keywords: q4
Submission reference: IN1816
Hello,
I am currently attempting q4. My question is this. Can the implementation of pairs2 be made in sequence? I find the idea of switching the circuit in PAR components perplexing. Should I be able to do this? Will a sequential implementation be looked upon with disregard by the mark scheme?
Many thanks.
A sequential implementation for pairs2 will only gain a few marks I'm afraid. The exercise is to develop your skills at designing and modifying parallel networks.
Read this part of the question carefully again – especially the paragraph starting: "One way is to bring the new reset channel into ...". The solution does not require dynamically changing the circuit (which we can do in occam-pi, but is not part of this taught module). One solution involves modifying the behaviour of the adder process (so that it flips betwwen an adder and a subtractor when reset). A neater solution, hinted in the paragraph just referenced, just needs another process in the network somewhere and no modifications to the behaviours of any of them – it's just a circuit design problem, using existing components.
Keywords: q4
Submission reference: IN1811
Any ideas on how can you send an INT (e.g. 1) to a process that accepts CHAN INT only?
The short answer is communicate with it in parallel. Presumably you have a PROC definition which takes a CHAN INT parameter, in which case you need to wire in a channel and output on the other end. A simple example (and not useful for any assessment probably!) would be:
CHAN INT c: PAR my.proc (in?, out!, c?) c ! 42
This runs "my.proc" in parallel with a simple process that just outputs on "c". It would be expected that "my.proc" accepts this value, and the continues doing whatever it previously did with the "in" and "out" channels.
If you're still not clear on this, please discuss with your seminar leader :-).
Keywords: q4
Submission reference: IN1812
I am having a difficulty to understand how to activate a resettable process. The replace process would always use the reset channel. How does it actually get activated? I have tried to send the zero value in the reset channel but it still won't work. Am I missing something here?
It sounds like your implementation is on the right lines. Such a process would normally have the implementation:
PROC replace (CHAN INT in?, out!, reset?) WHILE TRUE PRI ALT INT v: reset ? v PAR INT tmp: in ? tmp out ! v INT x: in ? x out ! x :
Thus, if something comes in on the "reset" channel, this component will respond by swallowing up the next value received on "in", and outputting the reset value on "out". Ordinarily, in the absence of any communications on "reset", this process will just copy data from "in" to "out" (the second guard in the PRI ALT).
Regarding 'activation', the process once instantiated is always active — though it may spend most of its time waiting at the PRI ALT for one of the input channels to become ready. Of course, this means you'd have to wire it up inside the relevant process network, which involves modifying that original network (in the case of "numbers", "integrate", etc.). The code for these can be found in the lecture slides, or on raptor in "/courses/co538/libsrc/demo_nets.occ".
2008 |
Submission reference: IN1552
Hi, I was wondering if you could tell me whether for modifying the pairs process in q4, do you expect us to being using one of either the substitute or the greater processes from the Legoland catalogue? Cheers.
Sorry – that's for you to work out! Using one (not necessarilly either of the ones you mention) of the processes already given in the slides is only one (possibly the best) approach. The question suggests another: plug the reset line into a modified plus process (that would then be better called something like plus.minus).
Keywords: q4
Submission reference: IN1549
I've moved onto Q4 finally, but I am completely confused by this:
-- The squares pipeline from the `legoland demonstration' (see "demo_nets.occ" -- in the "libsrc" directory, which contains the "course.module" sources) is: -- ... -- Unpack and rebuild this squares pipeline and pipeline it into print.stream -- to make a system that outputs perfect squares - one per line: -- ...
It sounds like we have to change squares in the course files, which I can't even find. Surely I'm misreading this.
The last portion of text in the comment you quote (and also the first line of Exercise 4) gives the answer – the key word is "rebuild":
-- Note: we don't need to redefine any of the processes defined in these files. -- They have already been defined and pre-compiled. The #INCLUDE directive, -- at the start of this file, gives access to them.
So, no, you are not expected to change these. However, you will need to write new versions of some of these (simple) processes to incorporate the reset channels as required.
But you are not expected to modify the course files to do that :-). The simplest way is to re-type the code from the Legoland catalog (slides 88 and 95 from the basics slides) and rename appropriately (e.g. "numbers.reset" for your modified "numbers") when you add in and deal with the reset channels.
For the first part of Exercise 4, the text explicitly points you to that slide 95 as a model for the required code – you just have to add one more process to the pipeline.
Alternatively (and only if you are a very slow typer!), you could copy the relevant sources from the "course.module" library. For those working with the kroc system, these sources are in your downloaded release: modules/course/libsrc/demo_nets.occ. Otherwise, they are on raptor: /courses/co631/libsrc/demo_nets.occ (from Windows, this looks like: S:\courses\co631\libsrc\demo_nets.occ, assuming your S: drive is mapped to '\\raptor\files').
Keywords: q4
Submission reference: IN1546
Hi, I'm struggling to avoid deadlock in Q4, specifically the "freeze control" bit.
I understand the problem I'm seeing (I think): if you hook up "print.streams" to feed data into monitor, then it creates a "circle of wires" and it is feasible that monitor could be trying to send a reset signal to numbers, but numbers would be trying to send to print.streams which is trying to send to monitor.
The problem is to think of a way around this. Is it acceptable to simply modify print.streams to accept a "freeze" signal the same way numbers2 and its friends do? That seems the most logical and consistent thing to do, but it also seems bad to fiddle with existing processes.
If that idea is "bad", can you offer any sort of hint as to the "proper" answer? Thanks. :)
Your analysis of the deadlock sounds quite plausible, but keeping the existing "print.streams" process as it is would be sensible, unless there is no other sensible solution. If the deadlock is in that loop of processes, then all you need to do is (somehow) break that cycle. It sounds like you have your "print.streams" feeding data back into the "monitor", which is then doing two jobs: handling keyboard input, and handling output from the program. Which is where things start to get a bit complicated.
So ... don't do that! Just keep the "monitor" process handling keyboard input (and sending other signals appropriately). Separately, add some sort of "freeze.control" process, similar to the one in Exercise 3, whose single job it is to freeze the output of "print.streams" going to the screen. That way, you add one extra process to the top-level network, which doesn't increase the complexity of any individual component :-).
There may still be opportunities for deadlock (e.g. if trying to reset numbers (and others) when the output is frozen), about which there is a note about in the q4.occ file. However, that will be impossible if your follow the specification (of the required reaction to an 'f') in the question (bottom of page 5 in more-exercises).
Keywords: q4
Submission reference: IN1545
Duplicate of my question originally posed on the forum (I later realised that the forum was not being used).
In assessment 3, the last task:
‘+’ : double the rate of output of lines of text (up to a maximum of 1024 lines/second)
‘-’ : halve the rate of output of lines of text (down to a minimum of 1 line/second)
Do we determine max and min speed just by observation, or do we have to actually count the number of lines per second?
Ah!! I see your problem now – sorry, an earlier answer did not.
To double or halve the speed, we need to know the current speed! The question does not say what initial speed to use – this is about to be fixed, :). Please set the initial speed to some value of your choice, within the min and max ranges given in the question (e.g. 32).
Your process should compute the delays necessary to control the speed. You may assume that the system can produce lines faster than the maximum (1024 per second) specified and your task is to constrain it. Actually, the transterpreter will have difficulty delivering more than 256 lines per second ... no matter. Your delays should still be computed so that, if you run your program on a faster platform, the controlled speed will increase to either 1024 lines per second or whatever the maximum happens to be.
Note: with the transterpreter, a delay of 0 microseconds will actually give a delay averaging 5 milliseconds. With the kroc compiled native code, the delay will average 0.5 microseconds. For both, a delay set to -1 yields no delay at all. Sorry, this is a subtlety of the runtime support. So, when the question says: "instance it with a delay of zero", change that to: "instance it with a delay of -1". I'll fix that as well.
By the way, if you wind the speed right down to one line per second, when you reset the numbers generator (or the integrator or pairs), the system outputs around 3 or 4 more lines (i.e. takes 3 or 4 seconds) before the changes resulting from the reset happens. This effect is less marked for the integrator and pairs resets. This is not an error on your part, nor is it due to an inefficiency in the occam platform – it is a property of the (exercise 4) system itself. Can you see why?
Keywords: q4
Submission reference: IN1535
In q4, with pairs set to differentiate, if integrate is reset then pairs will give a negative number.
This is of course accurate, however the question states: the modified pairs becomes a `differentiator', undoing the `integration' effect of the process immediately upstream so that we see the natural numbers sequence. Should we employ some method to enable this to return the natural numbers sequence immediately, or is the negative number acceptable?
Regarding the pairs process, Exercise 4 says: "Note: in its flipped mode, the modified pairs2 process becomes a differentiator so that the stream of numbers produced are the same (bar a bit of slosh) as those coming from numbers2." So yes, the odd negative number just after the reset you describe is acceptable, :).
Keywords: q4
2007 |
Submission reference: IN1329
print.streams
waits 1 second until it outputs the next line.
While it waits, do the other processes (number
,
pairs
and integrate
) wait also?
In occam-pi, can we force the channels to input to a process, while that
process waits for some time to pass, in order to accept at a later stage?
Yes to your first question. They are all blocked while
print.streams
is sleeping since that has
to take the output streams they are trying to generate.
No to your second question. Nobody can force input into a process! If a process is not inputting anything, then no input can occur – what-you-see-is-what-you-get. Any process trying to output something down a channel to a process owning the other end, but not currently inputting from it, simply has to wait. No data is lost. When-and-only-when the target process gets around to do some input, the message will flow from the source to target &ndash nothing is missed.
[Note the contrast with Object Orientation. Any object can be forced to take input (delivered by method invocation) at any time, whether it's ready for it or not. There's nothing an object can do to prevent this. Sorting out the resulting mess when that happens is one of the reasons why OO – even single-threaded OO – can be a real headache ... ]
Keywords: q4
Submission reference: IN1331
I am a bit confused. I am on the speed section of q4
.
I understand that time increments every microsecond.
I have declared a TIMER
and got the time
and I have a variable which I PLUS
to the time
to set up my speed delay.
I have set the initial value to be 1,000,000 (1 second) but
the output comes out a lot slower than 1 line per second.
Any ideas why this might be? Thanks.
Check that you are not making the same mistake as that suggested in the answer to Question 22 (2007).
Keywords: q4
Referrers: Question 25 (2007)
Submission reference: IN1328
With relation to Question 15 (2007). I have exactly the same problem and I don't really understand the explanation.
The pause
function in print.streams
goes much faster than the one in my
speed
process (I do comment the one in print.streams
out before trying
the one in my speed
process). I have noticed that some of the output done in
print.streams
is PAR
but even if I copy and paste the in/out in my speed
process a few times (to delay the delay
process from happening) it will not
reach anywhere near the same speed is if it were done in print.streams
.
Why will the pause
in speed
not go as fast as the one
in print.streams
?
Thanks.
Without seeing your program, I've no idea ... but can hazard a guess.
The delay
process imposes the same delay on any process
invoking it – it will be just the same in print.streams
as in your speed
control process.
In print.streams
, the pause
is executed once
per cycle – i.e. once for each line of output.
Now, where is your speed
process and what stream is it
controlling?
If it is in the stream of BYTE
s coming out from print.streams
,
you had better not be invoking pause
in every cycle – otherwise,
you will be getting that pause for every character generated, not for every line!
Your will be controlling characters per second, not lines per second.
If this is you problem, a simple fix is to invoke pause
only
if the BYTE
flowing through is '*n' (newline).
There is, though, a better and more efficient solution ...
By the way, there is no PAR
output in print.streams
– only PAR
input.
Keywords: q4
Referrers: Question 23 (2007) , Question 25 (2007) , Question 25 (2007) , Question 25 (2007) , Question 28 (2007)
Submission reference: IN1330
The diagrams that we need to submit for q4 ...
do we need to submit a diagram for all the new processes we have made
(numbers2
, integrate2
, pairs2
)
or is it just a layout of our processes for q4
?
Thanks.
Please submit a diagram for any process network you have changed (from any diagram given in the question sheet or starter file). Diagrams could be ASCII text art (as in the starter file) or any standard electronic document (also deposited in your submission directory) or a neat hand drawing (handed in to the CAS office with a cover sheet for this assessment number and module ... or scanned in and copied into your submission directory).
So yes ... we do want diagrams for your modified numbers2
,
integrate2
, pairs2
and q4
process networks. Only process networks need diagrams –
not serial logic.
Keywords: q4
Submission reference: IN1325
For the '+' and '-',of the q4.occ: each time the user types '-' on the keyboard, I divide by 2 the 1000*milliseconds of the delay that is passed to the print.stream. But this works only until (1000*milliseconds)/64 and then the (1000*milliseconds)/128 is the same as the (1000*milliseconds)/64. Do I do miss anything important here?
You should not be doing anything to the delay value passed to
print.streams
!
As the q4.occ starter file suggests, set that delay to -1 so
that print.streams
imposes no delays at all.
Leave print.streams
alone.
Implement speed control in a brand new process – as
the question (and starter file) suggest.
I guess you're modifying print.streams
to take
a speed control channel and starting at minimum speed
(1 line/sec => a period of 1000*milliseconds per cycle).
When a '-' is keyed in, the line rate should slow down
– i.e. the period should be doubled, not halved.
When a '+' is keyed in, the line rate should speed up
– i.e. the period should be halved.
Assuming that's what you meant ... why is (1000*milliseconds)/128
is the same as (1000*milliseconds)/64?
I'm assuming that milliseconds has the value 1000, since time
is measured in microsecond units.
Then, (1000*milliseconds)/128 is 7812, which is rather different
from (1000*milliseconds)/64 which is 15625.
[Note: the question (in the PDF file) says set the print.streams
delay to zero, but the starter file says minus one.
Setting a delay of zero asks for a delay of one time unit
(microsecond on most current platforms) – see the answer to Question 15 (2007).
This is because the AFTER
operator really means after!
Setting a delay of minus one asks for no delay at all –
because time is always AFTER
one time unit in the past.]
Keywords: q4
Submission reference: IN1326
In the assessment it says: "BYTEs output on the error channel do not need flushing - they are delivered to the user's terminal (window) without delay." Is this true with the transterpreter also? As I found that the error channel needed flushing after a bell signal.
On Unix systems, the standard error channel does not need flushing
and that's how occam-pi's error!
channel behaves there
(and is supposed to behave).
Under the Transterpreter, it should behave the same ... but, as you found,
it does not.
This will be fixed in the next revision – thanks.
Meanwhile, please send a FLUSH
to the error!
channel if you want previous output to be forced out!
Keywords: q4
Submission reference: IN1324
A question on freezing:
When we freeze obviously the timer keeps on going (for the speed control). Now, when we resume, the timer might have gone through many cycles therefore letting a whole load of result pour out all at once before resuming the normal speed.
Do we want that to happen or not? Thanks.
It's time, rather than the timer, that keeps on going. The timer ain't doing nothing!
But yes, depending how you do it, your scenario will happen.
It is quite easy to avoid (e.g. if you implement speed
control with a pause
procedure – though this has
its own problem, see the first paragraph of the asnwer to Question 15 (2007)).
There will only be a small loss of marks for suffering
this effect when a freeze is unfrozen.
Keywords: q4
Submission reference: IN1323
For the '+', '-', which are the maximum number and minimum rates? Because in the q4.occ doc you are saying 1-128, but in the pdf file you are saying 1-1024 lines/second.
Sorry – either maximum rate is OK. For most terminal emulators though, 128 lines per second is about as fast as they can go!
Keywords: q4
Referrers: Question 28 (2007)
Submission reference: IN1322
Hello,
I have some issues with deadlocking when I type with some fury at 'n' and 'i' when I implement them. My relevant code looks like:
... code deleted
Everything that I think could be done in parallel is done in parallel and I don't understand why if I start pressing the two buttons rapidly I would get in a dead lock situation. Thanks.
Sorry – see the third paragraph of the preamble at the top of this page. We can't answer such questions here.
Keying in 'n' and 'i' fast should absolutely not provoke in deadlock, so something
is wrong.
Your resettable integrate is not the parallel version required – you're supposed
to be working from the parallel integrate
process ... but this isn't why
your system is deadlocking.
[From a quick scan of your code, I can't see any obvious reason - sorry. You'll have to keep thinking about it ...]
Keywords: q4
Submission reference: IN1321
I'm working on q4, and was wondering about the last part (the speed control).
I assume I should use the pause
given to us in q4 for this, but when the
timeout given to pause is '0' it returns extremely fast (as expected),
however when the timeout given is 1 or more, it seems to be a lot slower.
(I am expecting to wait 1ms where it seems to be more like 1 second.
Well – you can use pause
somewhere within whatever process
you write for the speed control.
It's OK ... but when the delay is long, like a second, it will wait that whole second
before processing anything else ... which could be a signal to speed up!
There is a way to do this so that speed response to '+' and '-' is always fast,
no matter what the current delay period.
When you set zero as a delay period - e.g.
TIMER tim: INT t: SEQ tim ? t tim ? AFTER t PLUS 0
we are saying wait until the time on the timer is AFTER
what was just read
– i.e. that the timer has advanced at least one microsecond.
With the Transterpreter, that will probably be true, so there will be no delay imposed
... and the output is fast.
But if we set:
TIMER tim: INT t: SEQ tim ? t tim ? AFTER t PLUS 1
we mean wait until at least two microseconds have passed. The Transterpreter is fast enough that that probably won't have happened, so a delay is imposed. Because no other processes can progress (they are blocked by the above delaying speed control process), the occam run-time goes to sleep ... first asking the operating system to wake it up in a microsecond or two. Unfortunately, most operating system have a granularity at around 10 milliseconds in operating its timers ... so your system has to wait that long to get reinstated. [Note: that won't be the case when the operating system is written in occam-pi – check out RMoX.]
Consequently, there won't be much difference between a delay(1)
and
delay(10000)
(10 milliseconds) ... but you will notice delay(100000)
(100 millseconds, or 1/10 second) is a lot slower!
So, that should explain the effects of giving small delay values to the pause
period.
If we pass 1, we hope for 1 (2 actually) microseconds, but get around 10000 – same for
all delays up to 10000. [You should not have been expecting 1ms and should be getting
1 second delay!]
Keywords: q4
Referrers: Question 18 (2007) , Question 20 (2007) , Question 22 (2007) , Question 28 (2007)
Submission reference: IN1320
Are we required to submit q3.occ
as part of the latest assessment, or do we
just submit q4.occ
as this covers the stuff in q3
?
Just submit your q4.occ
source file. Thanks.
Keywords: q4
Submission reference: IN1318
I'm trying to do the increment/decrement of the print.stream's delay part of question 4 and can't seem to see why the following is happening, it seems fairly basic:
PRI ALT rate ? r print.streams (10, r!, chans?, screen!) SKIP print.streams (10, r!, chans?, screen!)
I can't ever get passed the first guard even though I know that I have read input from rate. Removing the skip guard and adding a stop below the first guard shows me that I can actually trigger this guard. Shown in the following:
PRI ALT rate ? r STOP
However it seems that when the skip guard is added the first guard is never correctly evaluated and the second one evaluates to true. Whats going wrong?
Guards are either ready or not ready – they don't evaluate to anything.
There are two problems with your first code fragment.
The first is that you input something from rate
into a variable r
possibly an integer?
But then you pass r!
to print.streams
where r!
is the writing
end of some channel!
Now, while occam-pi does enable channel-ends to be sent through channels,
I don't think that's what you are trying to do here – sending
channels through channels is how occam-pi can set up networks at run-time
(and is part of next year's Advanced Concurreny and Practice
module).
So, what is your r
– it can't be both an integer and a channel?
Your main problem, though, is not understanding the nature of
the print.streams
process.
This process runs forever – its main loop is WHILE
TRUE
.
So, when your code fragment runs, the rate
guard probably won't be
ready ... but the SKIP
guard will and so your second print.streams
(which is the same as the first!) starts executing ... and never
terminates.
So your code fragment never terminates!
If it is embedded inside a loop, that loop will never loop and your
code fragment will never be executed again.
Hope that helps!
Keywords: q4
2006 |
Submission reference: IN987
In the older answers, you mention model answers. Are these still available to look at?
OK - I've put model answers to completing q1.occ
,
q2.occ
, q3.occ
and q4.occ
in the raptor folder:
\courses\co631\answers\
Submission reference: IN861
Hi I need some help! I spent ages trying to get this to work, but it doesnt seem to want to. I'm still stuck on the reset numbers to zero, so I have some questions!! [Stuff omitted.]
[Editor: the above question was posted at 14:00:02 on the day of the submission deadline ... the following was at 14:25:44.]
Hi, I know this is cutting it a bit fine but I've been stuck for days with question 3. When I run the program, the 'i' and 'n' keys work as expected however, when I press 'p', the program output doesnt change and the keyboard is unresponsive. [Stuff omitted.]
Sorry - that was cutting it too fine! We were attending a Board of Studies meeting from 2:00-4:30pm that afternoon ... and 4:30 was after the deadline. We try to turn around answers as quickly as possible - but cannot promise to do so within the day.
The story has a happy ending for at least one of the questioners ... who followed up an hour later with:
"Forget the last question, i figured it out!! Finally!"
:)
Keywords: q4
Submission reference: IN854
Why does my code just print:
0 1 2 3
then deadlocks?
If I change the printstream
call to connect to the f
channel (rather than c
), then it just prints:
0
then deadlocks?
If I change it to connect g
, then it just deadlocks before printing!
Here's my code:
PROC starty (CHAN BYTE keyboard?, screen!, error!) CHAN INT a, b, c, d, e, f, g: CHAN INT x: INT xx: [3]CHAN INT q: WHILE TRUE PAR numbers (a!) delta (a?, b!, c!) integrate (b?, d!) delta (d?, e!, f!) pairs (e?, g!) print.stream (100000, c?, screen!) :
You never use your channel array q
, nor your channel x
nor your variable xx
.
The WHILE TRUE
betrays a bad misunderstanding! Its loop body is
a parallel network of processes - none of which ever finish. So, that network
never finishes ... so the loop body never finishes ... and your loop never loops!!
Just get rid of it.
In your code, numbers
outputs its first zero ... delta
forwards it to integrate
and print.stream
...
print.stream
prints it (first output line) ... integrate
adds it to zero and sends zero to the second delta
... which
forwards it to pairs
and channel f
.
Channel f
has no receiving process, so that's the end of the
second delta
which can't continue until it completes the output
on f
.
Meanwhile, pairs
takes in the zero and waits for its second input.
This is on its way ... as numbers
can now output its second number
(1) ... the first delta
forwards that to integrate
and print.stream
(which prints it - the second output line).
Meanwhile, integrate
adds it to its running sum and outputs that to
the second delta
... which, sadly, is blocked still trying to output
... which means that integrate
is now blocked.
Meanwhile, numbers
can now output its third number (3) ... etc.
Eventually, the first delta
gets jammed trying to output
to integrate
... so numbers
gets jammed trying to output to the first
delta
. Because, integrate
and pairs
have
internal concurrency, they can actually take in at least one more input than
outlined above (because they have parallel input and output processes).
This is why you get a couple more lines of output before complete deadlock
is establised, :(.
If you connect print.stream
to the g
channel,
the earlier delta
processes jam straight away as there is
no process taking their second output channels. Everything jams very
quickly ... though the first zero should get through to be printed?
Probably, the Transterpreter bails out with its deadlock message before
Windows gets around to showing the zero in the terminal window.
Your mistake is using print.stream
, which has only a single input
channel. You should be using print.streams
, whose code is given
in your starter file and which takes an array of input channels (one
from each delta
and one from the final pairs
).
Keywords: q4
Submission reference: IN852
Is there anyway to use the numbers
, integrate
and
pairs
processes in a SEQ
?
For SEQ
, I can't figure out how to make them work, but they are fine for a PAR
.
But I can't figure out how to stop them in a PAR
, I would use an IF
statement if it was a SEQ
; but I'm really stuck and I spent all day trying
to make it work ...
No, there is now way to use the numbers
, integrate
and
pairs
processes in a SEQ
. The code:
SEQ numbers (a!) integrate (a?, b!) pairs (b?, c!) ... etc.
first runs the numbers
process and waits for that to finish ... which
it never does ... so the integrate
never runs ... which means
there is no process taking the output from numbers
... which means
that numbers
never even manages to output its first number!
So, trying to run these processes in sequence ... that is a pretty fundamental error.
By "stopping them", I assume you mean blocking them so that the output stream is frozen. To do this, no change at all to those processes is required! You just have to put something in their output stream - an obstacle ("pause") process that you can switch between allowing traffic through or blocking it. To block traffic, simply don't input anything and, therefore, don't forward anything.
If by "stopping" you mean the last modification (response to a 'q' keypress), just terminate the obstacle process. Now, there's an "air-gap" in the wiring and no data can flow and pressing further keys cannot repair that! To see deadlock immediately, you should also terminate the keyboard monitor process - otherwise, that's still alive waiting for keyboard input.
Keywords: q4
Submission reference: IN842
Is is ok if my 's' keypress doesn't use blackholes? It doesn't seem to cause any problems not using it, but I just wanted to make sure it was ok as you mentioned it during the class
Yes. If I mentioned it in class, it wasn't to do with this assignment. Sorry - I can't remember doing that. There is no need for "black holes" in this assessment.
Keywords: q4
Submission reference: IN839
My suspend process works but is giving some very strange output. The code is as follows:
... code deleted
It stops the program just fine but will not allow me to resume. To try and
test it a little bit i changed the last line from "SKIP
" to
"out ! x
", just to see what was pending on the output channel.
This allows the program to resume on the next keypress.
However: in every case (despite how long I wait before resuming),
the next number output is 43 and the other output from the
program is not what I'm expeciting. For example:
1 1 4 2 3 49 <-- pause here 43 46 135 43 89 181 <-- resume key 3 92 188
Do you have any idea why this may be happening? Or more to the point, is my suspend process along the right lines?
Sorry - your code fragment is deleted for the same reason as in the previous question.
However, your suspend process polls its control channel and, once it suspends operations, that's all it does. It spins forever, never releasing the processor and, so, your keyboard monitor process never gets back in to allow you to stop it! [Actually, that looks like a bug in the Transterpreter, which should re-schedule after a failed poll attempt. We will look into that.]
But that doesn't let you off the hook. That poll here is not needed ... and, if you have to poll, you shouldn't just spin ... without engaging (communicating) with some other process ... or having a (small) timeout ... in the polling loop. Then, everything gets scheduled again!
Putting a communication in your polling loop is what you do in the "test it a little bit" you describe. However, you output an unitialised variable and that accounts for the mysterious "43" you see. Uninitialised variables have no default value - the compiler warns you if it sees you using them. [I suspect our Transterpreter people decided it would be amusing to set them to 42, :), which they are absoultely entitled to do ...]
Keywords: q4
Submission reference: IN833
Hi,
I'm having some trouble with my zap adder control. I created a new PROC
called operation that takes an additional parameter to decide what function
is to be carried out. Does this seem like a sensible way to solve the
problem?
... code deleted
Also, to suspend output would a reasonable way be to simple halt numbers
from outputting anything thus causing everything else to wait for input?
Cheers.
Sorry, we can't answer specific questions about a piece of code large enough to give too much of a solution away. A general guideline is given in the third paragraph of the general text at the top of this page.
Having said that, the deleted code does look sensible (albeit with some redundant
SEQ
s). Your second question has "yes" as its answer, provided by
"halt numbers
" you really mean "suspend numbers
".
Keywords: q4
Submission reference: IN843
Do I get extra marks for spotting the specification problem in Question 17 (2006) and Question 18 (2006)? :)
We don't know who you are ... these are anonymous questions! :)
Keywords: q4
Submission reference: IN841
In question 17 I meant which number do I take off which? Its strikes me as important and I don't want to get it wrong :)
Ah - I understand what you mean now! :)
The specification says it in words:
'p' ==> .............................................................. .................... taking the numbers arriving from the tail process from those arriving directly from the delta.
Natural language, sadly, is a difficult medium with which to be precise - but we try. In your notation from question 17, this means:
delta - tail
However, that looks wrong! And will lead to a decreasing sequence of negative numbers ... instead of an increasing sequence of positives!! Humm ... that specification has been running for many years and nobody spotted anything wrong. It should be:
'p' ==> .............................................................. .................... taking the numbers arriving directly from the delta process from those arriving from the tail.
So, in your notation from question 17, this means:
tail - delta
Even now, I find it hard to interpret that natural language correctly. Specifications should be written in mathematics - only then can we have precision. Meanwhile, we will accept as a correct solution to this part of the assignment one that does the subtraction either way around. Apologies.
Keywords: q4
Referrers: Question 5 (2010) , Question 19 (2006)
Submission reference: IN840
You said in the class that pressing 'p
' should mean the third column is
natural numbers, but when I do what you say I have delta - tail
in pairs I
get this but the numbers are decreasing. So which one is correct,
delta - tail
or tail - delta
?
Thanks.
Sorry, I've no idea what you mean by: "delta - tail
in pairs"?
Same for "delta - tail
or tail - delta
"?
The pairs
process, slide 98 of basics.ppt
, has three
sub-processes: delta
, tail
and plus
,
arranged in the network topology shown. Your task is to make that plus
process behave like a minus
when a 'p
' keystroke is
made (and vice-versa for the next 'p
') ... etc.
Please see the answer to Q16 for further help.
Keywords: q4
Referrers: Question 19 (2006)
Submission reference: IN837
Hi, I totally get stuck on the fourth modification, how can I change the
pairs
process to undo the integration? Thanks
I think you mean the third modification: dealing with a 'p
'
keystroke ... which has to change the behaviour of pairs
.
Read the specification of this change:
'p' ==> the first 'p' zaps the adder process within pairs so that it becomes a subtractor, taking the numbers arriving from the tail process from those arriving directly from the delta. In this state, the modified pairs becomes a `differentiator', undoing the `integration' effect of the process immediately upstream so that we see the natural numbers sequence. A second 'p' toggles the process back to its original state. Subsequent 'p's toggle between the two states.
This assumes you are modifying the pairs
process whose
implementation is given by the network shown in slide 98 of
basics.ppt
. Just do what it says in the first sentence!
The second sentence will then just be true (as your experience in doing
the second assessment exercise should inform you). Don't forget to deal
with the third and fourth sentences in the specification above.
Keywords: q4
Submission reference: IN827
In the current assessment, does pressing 'q
'
basically kill it?
I.e. are we trying to make the whole thing crash and die?
Thanks
The question says: "Just cause the system to freeze (i.e. deadlock)
in response to this 'q
'".
By this , we mean something stronger than
the freeze in response to an 's
', from which we could
recover the system with a further keypress.
By "freeze (i.e. deadlock)", we do mean force the system into deadlock
- something we would not normally require!
But this is trivial to do: terminate the keyboard monitoring process
and one of the processes in the data stream(s) to the screen channel.
A (much) better solution would be to arrange for all processes to terminate "gracefully" - but that's a *lot* of work and definitely not required.
Keywords: q4
Submission reference: IN826
With assessment 3, question 4 has this:
's' ==> suspends output to the screen. Output is resumed by the next keypress (which is NOT processed according to the above rules -- it is merely the signal to resume output).
How should it be processed differently?
I assume that we press 's
' once, and nothing is output
but everything is still running.
Then, I assume if 's
' is pressed again then output it resumed,
but at the state the machine reached even when it wasn't outputting.
Am I wrong here though?
Is there something special we need to do?
Thanks.
If you type an 's
', the output must be frozen.
The next key pressed (i.e. any key, not just an 's
')
lets output resume from the point at which it was frozen.
That's still what must happen if, for example, that next character
was an 'i
' - i.e. that 'i
' is not processed
according to the rules (which would mean resetting the integrator).
Keywords: q4
Submission reference: IN825
I have to following for Q4:
[snip code]
And i keep getting the errors:
Error-occ21-q4.occ(325)- incompatible channel direction specifier on `d' Error-occ21-q4.occ(336)- incompatible channel direction specifier on `b'
I've tried changing around the channels and rewriting the PROC's but the same erros keep popping up. From what i can tell the channel directions are correct. For numbers replace outputs on d and delta takes an input on that channel.
Double-check that you're wiring things up correctly. Because you don't specify which lines the errors are being reported for it's pretty hard to give any more advice! The compiler will generate this error when you try and specify an incompatible channel-direction. Your code had a mixture of some parameters with direction-specifiers and some without -- put them all in as you think they should be and try compiling again. If things still go wonky, email me your code (frmb@kent.ac.uk) and I'll see if there's something else going wrong (like a compiler bug!).
From phw@kent.ac.uk: yes, double-check! You have simply used the codes given in slides 46 and 49 (from choice.ppt), which are correct for the replace process defined on slide 34. Now, look at the replace process defined in your q4.occ starter file ... it's different! The difference is trivial - one parameter name and the order of its parameters. To fix things, either change the replace in your file *or* invoke it correctly.
Keywords: q4
2004 |
This may sound silly but there are no questions about using "CASE", could you please tell me a bit more about it and when it's used please. Thanks.
The "CASE" construct is much like C and Java's "switch". In occam, "CASE" can be used in three places: as a "switch" on some variable/expression; in tagged protocol definitions; and in tagged protocol input. There are plenty of examples of "CASE" usage -- see the past questions, course notes, the model answer to Q4 (its "keys" process) and this occam tutorial. It would also be neater to use a "CASE" for examining the result of a "compare.string" function, rather than an "IF", in Q6.
Keywords: tagged-protocol , case , q4 , q6
When will the q4 model answer become available?
Done! Also for q5. See:
answers/a4_slow.occ answers/a4.occ answers/a5.occ
in the usual place.
Keywords: q4
Are differentiate and minus predefined or do we have to define them?
You have to define them -- they are not in the course library.
You will have been told this in your seminar groups. You could also find out for yourself by browsing through the course library:
/usr/local/courses/co516/libsrc/README.txt
Note: you don't have to write a differentiate process for Q4! Nor do you have to write a minus process ... read the fifth modification (in your starter file) carefully. Resetting the pairs process causes its adder sub-process to change behaviour so that it subtracts the numbers arriving on its two input streams from each other (careful to do this the right way around) rather than adding them. This has the effect of turning this reset pairs into a differentiator (which is merely a comment, describing the result of this change). One way to do this might be to wire a minus process into the circuit, but that is some way from the simplest solution.
Keywords: q4
Where do we use numbers.reset? After the second modification you ask us to declare numbers.reset and integrate.reset, but the diagram has numbers as its component?
There wasn't space in the ASCII-art diagrams to write a revised name for the resettable processes. Clearly, the processes labelled numbers, integrate and pairs -- that have reset lines coming into them -- are the resettable processes you have to produce. What you call them (e.g. numbers.reset etc.) is up to you! Just don't continue to call them by their original names, since those names are already in the course library and the linker will complain.
Keywords: q4
Talking about the resettable running-sum integrator, you said in the lecture that there was an argument for putting replace between plus and delta or between delta and prefix. Does this mean that the former of the two actually resets to 0 or output 0 instead of the latter that will output 0 plus the last number that came on plus?
Slide 6-21 in your printed notes (currently slide 22 of chapter 6 in the Powerpoint set) places replace between the delta and prefix. This means that, when a reset (e.g. a zero) comes in, it goes through the plus (and gets something added to it) before going through the delta and being output. Therefore, resetting with a zero does not cause zero to be output -- you will get zero plus the next input. However, the running total was zapped to zero, which is all we were wanting to do.
If we placed replace instead between the plus and the delta, a reset of zero also zaps the running sum to zero and we will see that zero emerge -- which lets us see more directly that the reset has happened.
Placing replace between the prefix and the plus has the same behaviour as the first option above.
So, the replace can be added anywhere in the original circuit and it will have the required behaviour (of zapping the current running sum).
Note that with any of these positions for replace, the next number output by the device -- following a reset -- may be the old running sum (before it is removed when it next passes through the replace). This just depends on where that old value is in the circuit when the reset happens. If that were a real concern, we could not use a replace. Instead, we would have to modify the delta process to take the reset channel itself (and PRI ALT between that reset and its normal input). That's easy -- it's a folding together of the logics for replace and delta into a single process:
PROC delta.replace (CHAN OF INT in, reset, out.0, out.1) WHILE TRUE PRI ALT INT x: reset ? x PAR INT any: -- remove old value in ? any out.0 ! x -- copy through new value out.1 ! x -- copy through new value INT x: in ? x PAR out.0 ! x -- copy through value out.1 ! x -- copy through value :But I prefer not to disturb existing components unless I really have to!
Keywords: q4
This question regards the `pairs.reset', which we are supposed to program for Q4. Is it okay to say we can program two methods, `pairs.plus' and `pairs.minus', and the `monitor' method choses which one of these to implement depending on the key-press; would this work?
And also, with the `monitor' PROC, is it alright to say that if I type `n' into the keyboard it sends the number 0 to the `numbers' method as an imput? If this is the case am I to asume that if monitor dosen't send a number (i.e. 0) to it, it would carry on as the normal `numbers' and not reset the numbers PROC ?
Also the timer, which we had to implement in q3:
TIMER tim: INT t: SEQ tim ? t tim ? AFTER t PLUS delay
where can we put this ? In the `monitor' method, or is it more sensible to implement it somewhere in `layout.max.chans', because it's connected to the screen ? A student told me somewhere in `numbers', `integrate' or `pairs' would be suitable.
Programming two separate `pairs' methods is possible, but quite a long way round. You can't `switch' between them, however -- you have do run both (in parallel) and then work out how to feed them inputs and collect outputs. It's easier (and arguably better) to just modify the internals of `pairs'.
As for the resetting of `numbers', yes, that's the way it'd generally be done -- in fact, there isn't any other way in occam. You can't interact with a process unless you have explicit wiring for it (e.g. one process cannot directly change the value of a variable in another process -- the processes have to communicate over a channel to achieve this). And yes, the `numbers' process should carry on generating numbers as normal, until it is reset. What happens inside another process (e.g. `monitor') can have no effect on `numbers' (or, indeed, any other process) unless communication takes place between them! This is what makes occam systems so robust as new components are added or existing ones changed -- unlike systems currently running the Social Services disability section, the Child Support Agency, ...
The timer code can be put anywhere where it will limit the speed of program output. The program is basically a pipeline of processes, so slowing down any one component in that pipeline will slow down the whole pipeline (the pipeline in this case is: "numbers -> integrate -> pairs -> layout.max.chans". `monitor' would not normally be part of this pipeline (although it could be). However, there's no need to complicate the code in `monitor' with timeouts (and making it part of the pipeline) -- the timeout code can go somewhere else. For clarity and simplicity, it's often better to engineer these sorts of things into stand-alone components, then wire them into the process network. Pencil and paper come in handy for this.
Keywords: q4
Hello, I'm having trouble with the `monitor' procedure, my code is below:
PROC monitor (CHAN OF BYTE k, CHAN OF INT num, int, prs) PAR IF k = 'n' num ! k IF k = 'i' int ! k IF k = 'p' prs ! k :
I get indentation errors, and I'm not sure how to fix this, I was told by a colleague that we are supposed to implement an infinite loop in the `monitor' process -- why is this ? and what use could this be ?
Also, in the specification for the assignment, when we press `s' to suspend the output to the screen I'm assuming that this supposed to be implemented by the `monitor' method -- am I right?
Yes, this code has incorrect indentation. The "occam-2 checklist" in the course notes (and linked from the course web-page) provide a good deal of information on the layout of occam code. The correct layout for an occam `IF' (conditional process) is:
IF condition.0 process.0 condition.1 process.1 ...
The operation is: the various conditions are checked in the order written; the first one that evaluates to `TRUE' is selected and the process under it run. The rest of the conditions are then ignored. If you look at this occam tutorial, you'll see that the equivalent Java is something like:
if (condition.0) { process.0 } else if (condition.1) { process.1 } else if ... ...
In occam, however, one of the processes must be selected -- if the `IF' "falls-off" the end, it behaves as `STOP', generating a run-time error.
What you have in your code is some way to being a nested `IF'. The correct layout for that would be:
IF condition.0 process.0 IF condition.1 process.1 IF ... ...
But this is exactly equivalent to the version above, with all the conditions aligned.
The process needs to be an infinite loop otherwise it will run once then terminate, deadlocking anything else that tries to communicate with it (since it isn't there anymore). Parallelism does not imply repetition -- if you want the network to run forever, make each component run forever. And visa-versa -- if you want the network (or a sub-network) to run once (or n-times), make each component run once/n-times. Infinite loops are just `WHILE' loops that never terminate (because their condition never becomes `FALSE'). For example:
WHILE TRUE out ! 42
Will just output 42 on the channel `out' forever (or until it deadlocks).
The suspend signal needs to be handled in `monitor' in the sense that's where the key-presses arrive and are processed. Again, it's a design decision (up to you) as to whether the `monitor' process actually does the suspending of screen output, or whether it simply signals another component in the network, that suspends there. Suspend processes (e.g. for Q3) have been covered in the seminars, so it might make sense to re-use that.
Keywords: q4 , incorrect-indentation
Concerning q4: `PROC pairs' uses `delta', `tail' and `plus' components linked together. For the assignment we need a toggle on `pairs' in order to add numbers or take them away from each other. If we created another procedure which changed between `plus' and `minus' depending on key presses, and used that procedure in place of `plus'. Is this along the right lines or should there be something internal to `pairs' which decides if there should be a toggle ?
That is largely up to you! Both ways are essentially acceptable, assuming a nicely coded solution. The difference is usually the breakdown between parallel and sequential code. A single component will generally be sequential code only, whereas a network of processes requires parallelism (but the individual sequential processes are simpler).
One way to find out, of course, is attempt to program this both ways, and see which gets you to the finish-line first..
Keywords: q4
Is there any way the output can be slowed down its very hard to see if my code is working. If not is there any way we can output our results to a text file and look at them in there ?
The easiest way to slow down the output is using some suitable `delay' component, either inside the network somewhere, or just before the network connects to the `screen' channel (but this latter delay process is slightly more complicated, as you only want to delay when a newline character goes through). As has been mentioned in the seminars, look at the following files on raptor for an idea of how to do this:
/usr/local/courses/co516/answers/a1_slow.occ /usr/local/courses/co516/answers/a2_slow.occ /usr/local/courses/co516/answers/a3_slow.occ
The last of these implements a fixed slow rate (10 lines/second) and has the simplest code ...
Keywords: q4
In the code given in q4 there is a replace procedure. I don't understand what it does. Could you explain how it works please.
This question was discussed in the seminars, attendance at which is compulsary. If you miss one, it is your responsibility to find out what you missed!
Having said that, look at slides 6-21/22/23 ... and ...
This procedure is probably best explained in terms of its occam code -- occam is actually very structured, although getting used to the syntax/indentation can take a little time. The code for `replace' (with the channels dressed up with direction specifiers) is:
PROC replace (CHAN INT in?, control?, out!) WHILE TRUE PRI ALT INT x: control ? x PAR INT any: in ? any out ! x INT x: in ? x out ! x :
The main body of this process is a `WHILE TRUE' loop, so it's going to do something forever. The process inside the `while' is a `PRI ALT' with two guards. The first guard will accept an input from the `control' channel, that has priority over the second guard, an input from `in?'.
As with most ALTs, if neither channel is ready the process will stop running and wait until one of them is. If the `in' channel is ready, and selected, a value will be read and simply output on `out' -- so values can just "flow" through the component unhindered.
However, if the `control' channel is ready (and this will be selected if both channels are ready) a value is read from it and placed in `x'. The code then, and in parallel, performs an input from `in' (throwing the value away) and output the value sent down the `control' channel to `out'. The effect of this is that a communication on the `control' channel causes the next value on `in' to be replaced. In this version, the communications are done in parallel -- so the replaced output may appear before the value that it was replacing. This is not a problem however, and those communications could be done sequentially if desired.
The `replace' component should have been covered in the seminars already, however..
I'm struggling with the `monitor' method: checking previous anonymous Q+A's I found a student starting the method this way:
PROC monitor ([]CHAN OF INT out, CHAN OF BYTE keyboard, intr) --{{{ forever WHILE TRUE ... wait for `intr' and process accordingly --}}} :
while I have done it this way:
PROC monitor (CHAN OF INT keybrd, num , int , prs) PAR id(keybrd, num) id(keybrd, int) id(keybrd, prs) :
I'm totally sure my own version is wrong, what I don't understand is what I'm meant to do exactly for this method; and also I would have thought the input for keyboard would have been a string for "s" "n" etc.. so you can compare which one to reset. I have done the methods for `numbers.reset', `integrate' and `pairs' and they're working. I'm not sure where to proceed from here though.
PLEASE HELP!!!! :'(
Going from your last paragraph, keyboard input is characters -- that are represented by BYTEs in occam. occam doesn't have a native `string' type like Java, so that rules that out. Strings in occam are done using arrays of BYTEs.
What you suggest is largely sensible (and correct): wait for some input from the keyboard, then compare to decide which component to reset. The first code fragment above is on the way to doing this. The second code fragment isn't; this will fail to compile due to the parallel inputs on "keybrd" -- also it's unclear what such code should do: relay the values on "keybrd" to each of the three reset-able processes ? Better to do the input first, then decide what to do with it.
Just as a point to convention: occam PROCs should be called "processes" or "procedures", not "methods" (a term from OO programming, which occam isn't). occam also has FUNCTIONs (that return values) and these are very different from PROCs (non-value parameters can be used to "return" data from PROCs, however).
Keywords: q4
I am trying to set up a reset for pairs. Where do you best suggest I have replace? Before the input or after? Or can I have more than one replace in a process?
Yes, you can have as many replace processes as you like in any process network (such as the one needed for pairs.reset). Actually, you should add no replace processes there -- they offer no help in implementing the required change in behaviour of pairs.reset when a reset signal arrives.
Keywords: q4
I've completed q4 - but just testing it I've found that my implementation for pairs resetting is a bit odd.
If left on its own the program runs fine and loops round every 20 secs or so. If i press `p' I start to see the list of natural numbers - but the program then crashes at 65535. Is this ok?
Yes, that's not too serious -- but the crashing is a pain and easily fixed.
The `pairs' process, when subtracting, behaves like `differentiate' (except that it loses the first value communicated -- because of the `tail'). Thus you'd expect to see natural numbers -- or at least the input to the (`integrate' -> `differentiate') part of the pipeline.
Your program crashes when your resttable `pairs' process is reset, because your code uses (I strongly suspect) either a `+' symbol (instead of a `PLUS', which wraps round on overflow without crashing) or a `-' symbol (instead of a `MINUS', which also wraps round on overflow without crashing). The course library `plus' process uses a `PLUS', precisely so that it can be used on number streams that get too large or too small.
Your program `crashing' is expected behaviour, if you have used the algebraic operator symbols. The sum of 1..65535 is just less than 231 -- when 65536 is added, it'll overflow. "Crash" is perhaps a slightly strong term in this case -- the (overflow) error was correctly detected and appropriate action taken. But use the `PLUS' (or `MINUS') operators and the overflow will be ignored -- that's what Java does anyway!
Keywords: q4
When the system is paused, do we need to guard against the user typing in other valid command letters such as `n', `p' etc. ? In my system, when it is paused through a `s' pressing any other valid commands creates a deadlock!
From the `q4.occ' file:
--> 's' ==> suspends output to the screen. Output is resumed by the next --> keypress (which is NOT processed according to the above rules --> -- it is merely the signal to resume output).
So pressing any key whilst paused (including valid command keys) should just resume the output.
Keywords: q4
I was reading the bit about graceful termination in the course notes and understand about sending poison down the line to shut each process down properly. My question is does this mean that we have to change every single component that we use, i.e. `delta', `succ', etc. ?
Yes, to get processes like `delta' to shut down nicely, modification will be required. However, you're not expected to implement graceful termination for Q4 -- you can do if you like, but it's quite a lot of hard work. Essentially anything that has a `WHILE TRUE' loop needs adjusting in some way -- such loops cannot terminate..
Keywords: q4 , graceful-termination
I'm now somewhat through Q4 and have noticed that I'm using polling `PRI ALT's. It says in the coures notes that they should be used only as a last result -- I'm wondering if this is acceptable in Q4?
I'm not sure of another way of interupting a process based on a signal that may or may not arrive. I've created PRI ALTs in the new control PROCs that have been added to `numbers', `integrate' & `pairs'. I'm now planning on using it to react to the byte `s'
As the course notes say, polling should only be used as a last resort. I wonder, however, if you're actually polling.. Polling code is specifically this:
PRI ALT c ? x ... do something with `x' TRUE & SKIP -- skip guard SKIP -- do nothing
When executed, if data is available on the `c' channel (i.e. the corresponding outputting process is blocked in the output), then that data will be accepted immediately (placed in `x') and the guarded process runs. If data is not available on the `c' channel, the `SKIP' guard is selected and does nothing -- so the `PRI ALT' finishes immediately.
That code is polling, and it can create problems.. For example:
WHILE TRUE PRI ALT c ? x ... do something with `x' TRUE & SKIP SKIP
This code will consume as much CPU as it can until some data arrives on the channel `c'. Of course, the correct code in this case (since the process does not interact with anything else in the loop) would be:
WHILE TRUE SEQ c ? x ... do something with `x'
This code, on the other hand, will wait for something to arrive on `c' then do something with the data received. And waiting (either blocked on channel communication or waiting for a timeout with `AFTER') does not consume the CPU. (although busy-wait versions of these could be created easily, it would be daft..).
It's the `SKIP' guard in the `PRI ALT' (and subsequent do-nothing process or do-very-little process) that constitutes polling.
The following code, for example, is not strictly polling (but it is not nice code):
WHILE TRUE PRI ALT c ? x ... do something with `x' TRUE & SKIP SEQ d ? y ... do something with `y'
If you've written stuff like that, you probably wanted instead to write:
WHILE TRUE PRI ALT c ? x ... do something with `x' d ? y ... do something with `y'
These two code fragments do not behave in the same way, however. The first will commit to input on `d' if `c' is not ready -- refusing then to service `c' until something has arrived on `d'. The second will happily wait for both, and service the first channel that becomes ready (or `c' in preferance to `d' if both are ready).
You can read some more on ALTs and polling in this occam tutorial.
Referrers: Question 23 (2010)
In the diagrams that you have put into Q4, you have connected the `monitor' only to `numbers' `integrate' and `pairs'. Surely this also needs to be connected to the `layout.max.chans' as to allow output to the screen or not? That is the way I managed to do it in Q3 and it seemed to work ok.
The keyboard characters input by the `monitor' process do not have to be echoed to the screen channel.
I assume you are talking about the suspend mechanism, in reaction to an `s' keyboard input -- the fourth modification. From `q3.occ':
--{{{ data-flow diagram -- --Sorry ... you're on your own here. -- --}}}
So yes, some extra connectivity is required beyond that shown on the diagram for the third set of modifications.
However, altering `layout.max.chans' (to take that extra connectivity) is not the simplest approach -- the re-programming is untidy; since it takes its original inputs in PARallel, you will need to poll the extra one separately.
A simpler approach, as discussed in the seminars for Q3, is to create a separate `suspend' component that can be added to the existing process network (with some minor extra wiring) -- and leave `layout.max.chans' unchanged.
It's usually better engineering to add new functionality by adding a new (parallel) process specifically to implement it, rather than by modifying an existing component to add to its responsibilities. For performance reasons, we may sometimes need to fold parallel processes together into one single (but more complex) serial process -- but that can be done later (and fairly mechanically). In this exercise, there is no such performance constraint. In fact, the model answer adds code to slow the system down to produce output at only 10 lines/second, so that it's easier to see the effect of the controlling keystrokes. You might like to do the same -- though this is voluntary!
Keywords: q4
2003 |
I have done the rest of the assignment but Im have trouble with pairs.mod, I have defined new PROC's:
[snip code]
Below is my code for `pairs.mod':
[snip code] PAR replace.bool (l.2,control,l.1) [snip code] SEQ prefix.bool(TRUE, l.2, l.1) delta.bool(l.1, l.2, l.3)
The trouble I have is that it says I have parallel inputs on channel `l.1', but this is similar to the way I implemented the other mods and they all work...
This can't be right -- both these processes run for ever, so it doesn't make sense to execute them sequentially. Once `prefix.bool' starts, control can never return, so `delta.bool' never runs.
There appear to be two parallel OUTputs on channel `l.1', in replace.bool and prefix.bool
Keywords: q4
Additional to Q40, I havn't actually started using `layout.max.chans' yet, because none of my deltas will work. Currently I've got numbers outputting into the delta I gave which outputs one channel into an output module which just outputs whatever ints it gets onto the screen straight away and the other output going to nowhere. If I remove the delta i get the output i expected, but with the delta in between I get no output. The only thing that can possibly be wrong is the delta. Any more ideas?
If you leave the second output of the delta unconnected, the delta will get blocked when it tries to output. If you want to discard the data, connect it to an INT style black-hole:
PROC int.black.hole (CHAN OF INT in) WHILE TRUE INT v: in ? v :
Will I be penalised if I use STOP to create a deadlock for Question 4?
No, but it's not a very nice way of inducing deadlock, and it's not always correct. In the default `error-mode', processes that STOP cause a run-time error and the whole program finishes. In `stop' error-mode (which isn't the default), processes that STOP just die quietly, leaving the rest of the program running. Thus, if you use STOP, you should do it in such a way that the program would deadlock `nicely'.
A quick way of causing local deadlock is to communicate on an unconnected channel, simply:
CHAN OF INT dummy: dummy ! 42 -- deadlocks here, because there's nothing connected to the other side
Which diagrams do I need to submit with this assignment? (Q4)
You should submit diagrams for all processes you create or modify. I.e., the modified process networks for `numbers', `integrate' and `pairs', and the overall top-level `q4' network. Also include `icons' for processes you create, if these aren't immediately obvious in the other network diagrams.
Referring to Assignment on Q4:
Yes, you may well need to implement a `minus' process, but it depends on how you go about solving that bit. For monitor outputs, a channel-array or separate channels are equally valid. On your third point, technically `INT' is a protocol. The structured PROTOCOL types should only be used if you need them -- you don't need them for this assignment.
Keywords: q4
delta (g, h, c[0])
this is in my main q4 proc. `g' is the input coming from numbers, `c[0]' is an output which will go to layout.max.chans and `h' is an output which will go into integrate. I know numbers gives an output as I've tested it with an output module, but as soon as I attatch the output from number to the input of this delta neither `h' or `c[0]' give any outputs when tested with the same output module.
I can't for the life of me see what I've done wrong! I've checked that all channels are connected correctly over and over so its not that either. Any ideas?
Two numbers must be output by the `numbers' process before any proper output appears. Since all the output is done via `layout.max.chans', that must input from each of its channels before anything will be displayed on the screen. Thus, if any of those input channels are unconnected, nothing will happen -- the `layout.max.chans' process will wait for input forever -- the `max.chans' constant defines how many channels should be `layed-out'. Similarly, if your pairs process doesn't output after two inputs, things will deadlock -- `layout.max.chans' will be waiting for that final input and the remainer of the network will probably be blocked on output.
Keywords: q4
I've done the third mod and it works fine. However, someone has just mentioned that you didn't want us to modify the `plus' process. Is this true ?
The question says:
'p' ==> the first 'p' zaps the adder process within pairs so that it becomes a subtractor, taking the numbers arriving directly from the delta process away from those arriving from the tail. In this state, the modified pairs becomes a `differentiator', undoing the `integration' effect of the process immediately upstream so that we see the natural numbers sequence. A second 'p' toggles the process back to its original state. Subsequent 'p's toggle between the two states.
There is not a single `right' way to do this. The first line seems to imply that you should modify the adder process, though there is a neat solution that doesn't.
Keywords: q4
Do we have to use the replace function provided for q4 ?
I have a working q4 but it does not use the replace function. That ok?
In theory, yes. However, if your solution would have been more efficient using `replace' you may lose marks based on that. However, if your solution is succinct and correct, no marks will be lost.
Keywords: q4
To suspend screen output, would directing the `out.int' and `out.string' to a `black.hole' be appropriate ? I have tried this but it doesn't seem to work, am I going in the right direction or completely off.
Re-directing the output to a `black.hole' won't suspend it -- it'll gobble it up, like a black-hole. To suspend the output you need to stop the flow of data, which is often simpler than re-directing it. See the model answer for question 3 (on raptor) for an idea of how to do this.
[snip code]
I'm probably missing something really obvious, but why is this not giving any output? There is nothing coming in through the input channel, but yet when I attatch it to a tested output module nothing comes out.
Look carefully at the PROC heading for `replace':
PROC replace (CHAN OF INT in, control, out)
and note the ordering of the `in' and `control' channel parameters.
Keywords: q4
I'm a bit confused about the `out.int' and `out.string' PROCs in `layout.max.chans' in Q4. Are they already defined somewhere, because I can't seem to find them. Or are we meant to define these two PROCs ?
They are defined elsewhere -- in `course.lib' to be precise, so you must not define them yourself -- doing so will result in linker errors when it finds two copies of each (one from the course library and one from your code).
These two PROCs just write INTs or BYTE-arrays to a BYTE channel, aligning in the given `field' (2nd parameter). Writing `out.string' is easy, `out.int' less so. You can find the code for these on raptor in:
/usr/local/courses/co516/libsrc/utils.occ
Keywords: out.int , out.string , q4
I'm having trouble with getting the `pairs' process to toggle adding and subtracting. The following code compiles but doesn't do much, the only effect being that an input on the control line stops any other keypresses getting through. Ive tried declaring `subtract' in various places to no avail. Thanks.
[snip code]
See the answer to Question 27 (2003) for a brief description of the problem. Your code contains the process networks for both versions of pairs, but once running, these will never terminate -- they contain `WHILE TRUE' loops. You need to modify the process network itself -- not `wrap' the networks up in other code, as that won't work.
Keywords: q4
I'm having some problems with the new pairs process. This is what I've done:
[snip code]
It doesn't seem to be doing anything. Any suggestion ?
This appears to be a common mistake -- you're instancing the `plus' and `minus' PROCs from inside another component, that results in your component behaving like either `plus' or `minus' respectively. However, once called, these PROCs never return, as they have WHILE TRUE loops.
If you want a single component to take care of the addition/subtraction, you have to engineer (program) it that way -- i.e. a single self-contained PROC, not one that instances other PROCs. If you do want to re-use the existing `plus' and `minus' PROCs, they have to be engineered into a suitable parallel network -- i.e. instanced directly under a PAR, not from sequential code.
Keywords: q4 , process-networks
Referrers: Question 29 (2003)
I have now got a completed version of q4. However, in this monitor process...
[snip code]
.... it will only reset `I' or `P' if I press the key twice and it pauses it inbetween each key press. How come it is doing this as it is only the `S' case that asks for a second input? Also, typing in N twice causes the program to deadlock, yet I can't think of why. Any suggestions?
You have an ALT guard of the form:
in ? y BYTE x: SEQ in ? x ... do something based on `x'
Before getting to the `do something based on `x'' bit, two inputs will happen on "in". Remember that in an ALT, input guards do perform the input before the guarded process runs. The correct guard/process would be something like:
in ? y ... do something based on `y'
Keywords: q4 , alternation
Are we allowed to create a process called `my.prefix', and replace the standard `PROC prefix (...)' within `my.numbers' / `my.integrate' with the new `PROC my.prefix (...)' ?
Yes, in theory there's no problem with doing that. However, for this assessment, there shouldn't be a need to do this, but that depends on how you go about modifying the various process networks.
Keywords: q4
I am having trouble with step 3 of the assessment. I am trying to have a variable that is set to either 1 or -1, and then the one of the numbers within pairs is multiplied by this number before the addition takes place (having the effect of subtraction).
My trouble comes in where to create and initialise the variable (call it `b'). At the moment I have it in my monitor process...
[snip code]
but when I compile, it whinges on the line marked that `b' is not declared. Doesn't the declaration at the top of the PROC last throughout the process ?? If not, how can I introduce the `b' variable without it being reset to one each time the process is run??
The rule with variable declarations in occam is that they are visible in the process following the declaration, and only that process.
For a good description of this, which relates directly to the error in your code, see Question 3 (2000). You should have gotten an error about incorrect indentation in that code too..
Keywords: q4
My part 2 of the assessment will not work. I have tried everything and, despite being able to get it to compile, nothing I can do can get the keyboard input to have the desired effect. I have proved that the keyboard input is being read, but I don't know why it's not running the rest of the program as it should
[snip code]
... am I right in thinking that once it has outputted 0 down either the `n' or `i' channel, it should then come out of the process and go back to my `q4' process (where it was called from), and thus go on to execute the whole number sequence thing but with the values of 0 waiting to be inputted on either the `numbers.reset' or `integrate.reset' processes.
I ask because no matter how I seem to plug these processes together (each one making its own sense), they don't seem to work!!
Removing some of your code, and assuming you fed it `i' on the keyboard, you are left with a process that behaves something like:
CHAN OF INT i: SEQ i ! 0
This immediately deadlocks. The reason is that the channel you are trying to output on is unconnected -- there is no parallel process performing the corresponding input (remember that channel communication in occam is a synchronous action, as well as a communication -- i.e., both the inputting and outputting processes must wait for each other before the communication can take place).
The `q4.occ' file shows (in ASCII art), the process network that ought to be constructed:
| v keyboard ____________________________|___________________________________ | | | | _____|_____ | | __________| | | | / 'n' | monitor | | | / |___________| | | v | 'i' | | / v | | ____/____ /| _____|_____ /| _______ | | | | / | | | / | | | | | | numbers |->- |->-| integrate |->- |->-| pairs |\ | | |_________| \ | |___________| \ | |_______| \ | | \|\ \|\ \ | error | \________ \ \ ------>-- | v v v | | __\_____________\_____________\__ | | | | | screen | | layout.max.chans |------>-- | q4 |_________________________________| | |________________________________________________________________|
Thus, taking code straight from the diagram, the PROC header for this particular `monitor' process should be of the form:
PROC monitor (CHAN OF BYTE keyboard, CHAN OF INT to.numbers, to.integrate)
... and the monitor process resets the numbers and integrate processes by communicating on the channels given to it as parameters. The actual channels used are part of the `q4' process (i.e. should be declared there) -- as can be seen in the diagram.
Keywords: q4 , parallelism
Is there something special that we need to do to get what we press on our keyboards to register in occam as my program isn't picking up any keyboard inputs, yet by my reckoning it should be. It works for the `a3.occ' file tho ?
Help!
If you have a correctly programmed monitor process, there should be no problem with the keyboard. When you type keys into occam programs, they are not echo'd back to the screen unless you explicitly program this -- so it appears you are typing blind. Might this be the problem ?
If things ought to be happening, but aren't, double-check the `monitor' programming. Also check that it is wired up correctly -- i.e. with the keyboard channel.
Keywords: keyboard-input , q4
[snip code]
I have plugged the `i' and `n' channels into `integrate.reset' and `numbers.reset' respectively and yet, though the program compiles, it only seems to be running the `step1' process and not taking any keyboard input or taking it but not acting on it. Any clues as to what is wrong ??
Yes, although I can only give a fairly restricted answer here. If you want a more detailed response, mail your seminar leader -- they'll be happy to help. If you're in Peter's group, he's not around just at the moment, so you may mail me (frmb) instead.
The main problem with your solution, so far, is that it is not parallel. Your main process either runs the `monitor' code, or the `step1' code. For the network to work correctly, you need to have these as two distinct and separate parallel processes, with channels connecting them.
Keywords: q4
In order to change the behaviour of the pairs process each time `p' is pressed, can we re-implement pairs without including the plus and minus processes, and carry out the calculations using the PLUS and MINUS operators directly ? Or is it best to keep the plus and minus processes involved ?
In many ways, that's entirely up to you -- for example, try both, see how they turn out. What you must not do is trash the default `pairs' process and replace it with a purely sequential `pairs' process. After any/all modifications, the `pairs' process must still be a network of sub-processes. Depending on how you decide to approach this part, you might need to write new processes of your own (as opposed to simply modifying old ones).
Note, however, that the `plus' process and `PLUS' operator are utterly unrelated -- one is a process, the other is used for building expressions. One cannot be substituted for the other, without a significant amount of work. The choice (between operators) of whether to use `+' or `PLUS' is up to you. The former is often better, since the program will Stop before generating incorrect data. The latter simply ignores integer overflow -- which will usually result in incorrect answers being generated.
Keywords: q4
For Q4 what is the command to make the terminal bleep when any other character is entered apart from those specified?
Output an ASCII "bell" character:
out ! BELL
The `BELL' constant is defined in `consts.inc', that is included by q4.occ.
The constant definition is simply:
VAL BYTE BELL IS 7:
It may not work on some terminals -- i.e., those that cannot beep, or those that are configured not to beep.
Referrers: Question 32 (2003)
do we hand in Q4 through reception or online?
At Reception -- cover sheet, printout of code, and process diagrams. The deadline for Q4 is now Thursday 20th November.
Keywords: q4 , submission
Hi, i'm trying to implement the second part of q4, where the inputs `n' and `i' have an effect on the operation of the program.
I have defined a `monitor' process which outputs 1 to a chan, depending on what the keystroke is:
PROC monitor ([]CHAN OF INT out, CHAN OF BYTE keyboard, intr) --{{{ forever WHILE TRUE ... wait for `intr' and process accordingly --}}} :
When trying to implement my version of `numbers', I wanted to continue using the numbers as normal, but if the INT 1 came in through a `control' chan, to set the value of the input to the prefix as 0 (hence starting it from the beginning again)
PROC my.numbers (CHAN OF INT out, control) CHAN OF INT a, b, c: WHILE TRUE PRI ALT INT x: control ? x IF x = 1 c := 0 TRUE PAR delta(a, out, b) succ(b, c) prefix(0, c, a) :
However, it doesn't work. Any help ? :)
As regards numbers, you can't do what you're trying to do with the above code. The compiler will reject it at the ``c := 0'' line, since you can't assign to a channel. We'll assume you meant to output instead, `c ! 0'.
The compiler won't reject that code (if fixed), but it won't work either. Initially `my.numbers' will wait for a signal on the `control' channel -- and won't output anything.
You'll notice this immediately, and maybe press the `n' key to prod `my.numbers'. Given this, the ALT will wake up and run the IF process. Given that `x' will be 1, `my.numbers' will attempt to output on the `c' channel, and deadlock -- there isn't anything connected to the other side of that channel. If, for some reason, `x' was not 1, the original `numbers' process network is run (by the PAR). That'll happily output numbers forever and ignore the `control' channel, such that an attempt by `monitor' to communicate will cause deadlock (in `monitor' as it attempts to output).
You actually need to modify the original process network for this one, as will be explained in the seminars this week (if it hasn't already). To do this, you need to understand what happens when the `numbers' network is switched-on; essentially a number `flows' round in the loop, being incremented by `succ' each time, with `delta' producing the copy that is output. Thus, to reset the numbers back to zero, you need to interfere with that `flow'.
In occam, you can't interfere with a process externally -- the compiler just won't let you (unless you forcefully turn the checking off, but this is rarely a good thing). Attempts to communicate `externally' on the `c' channel (and in parallel), will be banned by the compiler. The modification needs to be `deeper'.
Note: Eerke has mentioned that the deadline for Q4 has been moved back one week, into project week. From the ukc.cs.cs2 newsgroup:
This also reduces the deadline bunching in week 8: the minor pieces of coursework are still there, the major one for CO516 is now the single deadline in week 9.
.. so you've got a bit more time on this.
Keywords: q4 , process-networks
2002 |
I'm trying to edit question 4 for the assignment but when I open it using 'gvim q4.occ' it opens but is just black and white text and it beeps at me!
Check the answer to Question 16 (2002). Note: starting work for an assignment the morning that assignment is due is probably not a good strategy ...
For the second modification task, I have created my own processors numbers.reset and integrate.reset which respond to the inputs 'n' and 'i' respectively, however when I assign the replace processor to be used within each of these processors, it displays an invalid process error:-
: reset ? ch : IF : (ch = 'n') : PAR 318: replace (a, 0, b) : delta (b, out, c) : succ (c, d) : prefix (0, d, a) : TRUE Error-oc-q4.occ(304)- Invalid process type tree not caught by case (switch) is CHAN
Why does this occur?
Well ... replace takes 3 channel parameters and you supply an INT (0) as one of them! The Solaris kroc compiler does give a poor error message, but nobody at INMOS ever thought someone would write code like that! The Linux kroc handles this better.
Your code is very wrong though. You are misunderstanding something fundamental. See your seminar leader. [If you get an 'n' in the above, you start up a PAR construct that never ends ...?]
For part two of q4, where it states "clearly numbers and integrate will have to be reimplemented", do we declare a new process (such as numbersOne) within q4 and modify this or can we edit the version in demo.nets?
You need to declare a new process (such as numbersOne) before q4 in your file q4.occ. Cut and paste the numbers code from demo.nets and modify that. You can't, of course, edit the file demo.nets - you don't have write permission ...
Keywords: q4
Is it me or for the second modification do you have to change not only numbers to accommodate a reset command but prefix as well? The same goes for changes that have to be made to integrate and its internal code. Is there an easier way to do this or not?
I'm afraid it's you. You have to change the numbers process because it's functionality has changed - it's got a reset line! To make this change, however, you don't have to change any of its old sub-components - i.e. prefix, delta and successor - but you do have to insert one extra sub-component into its circuit. The same observations apply for the needed change to integrate.
Keywords: q4
I have just completed the 'p' operation. It un-does the last operation but the numbers are one out each time:
43902 963714753 43903 43903 963758656 43904 43904 963802560 43905 43905 963846465 43906
Is this still correct or should I be getting the same in the last colunm as in the first colunm?
No - that's fine! The model answer (answers/a4) does the same thing.
Keywords: q4
In q4 you say 'q' should be dealt with by putting the system into deadlock. Can't we use the command STOP instead?
Well ... you can, but it's not very nice. Any process executing a STOP - in the current versions of KRoC - causes the whole system to stop in a rather ungraceful way. On the Solaris version, it even causes a core dump! Later versions of KRoC will offer an option so that only the process executing a STOP will stop (i.e. freeze, which is subtly different from terminate) - leaving the rest of the system running. This is what is supposed to heppen.
So, getting your process to respond to 'q' with a STOP is allowed - you will not lose marks for this solution. For a better solution see Question 12 (2002).
This is the error i keep getting and I don't understand why, max.chans is still set at 3, can you help, I can't seem to get passed this to get on with the rest!?
raptor$ kroc q4.occ : delta(a,b,e) : integrate(b,c) : delta(c,d,f) : pairs(d,g) 315: layout.max.chans(e,f,g,screen) : :: : : Error-oc-q4.occ(315)- Too many actual parameters in call of layout.max.chans
You have too many parameters! layout.max.chans takes just two parameters - an array of input channels and an output channel. You are supplying four parameters, :-(.
Your channels e, f and g should be elements of an array - e.g. c[0], c[1] and c[2]. Then, your instantiation would be:
layout.max.chans (c, screen)
An alternative solution is to keep your channels, e, f and g, as they were and construct the array required by layout.max.chans on-the-fly:
layout.max.chans ([e, f, g], screen)
For the final modification to q4, when my program is running, I press q and the screen outut stops, and then if I press any key a deadlock message comes up and the terminal shows the raptor prompt again.
Presumably, you react to the q by sending a suitable signal to the same process implementing the suspend mechanism? What we were suggesting was for that process to terminate (i.e. exit its loop and finish) when it gets that quit signal. That leaves no route for the streams of numbers to get to the screen and most of your q4 system is deadlocked.
However, your keyboard monitoring process is still alive, waiting for more keystrokes. If you type anything but the ones it wants (e.g. anything bar 'n', 'i', 'p', 's', 'q'), it swallows it and loops around and stays alive. If you type an 'n' (for example), it tries to output a reset signal to a deadlocked component. That doesn't succeed and the keyboard process is stuck trying to output. There are now no processes left to run - and, now, the run-time system can announce deadlock and terminate. This solution is fine, but the model answer does something slightly different ...
Referrers: Question 14 (2002)
2001 |
Can you give me a hint on how to implement the `PAUSE' method for part 4? I know how to do the quit function but need to be able to put this deadlock within the pause function.
Implement a `PAUSE' in the same way as you did for question 3 (as discussed in your seminar groups). To cause deadlock as the response to a QUIT, the simplest way is to arrange for the process that manages the PAUSE effect to terminate - that leaves its upstream processes blocked all trying to output. Your keyboard monitor is still active - so your system is not yet deadlocked. But as soon as you type one of the characters to which it responds by outputting to the rest of your (now blocked) system, that output won't be taken and your keyboard monitor will block. Everything is now stuck and the run-time system will detect deadlock and quit.
Keywords: pause-process , q4
I have created the `pause' process to respond to `s' as step 4 of Q4 asks. But where does it go? Does it take input direct from the keyboard and then outputs to the monitor or does the monitor output to the pause process??
It can't take input direct from the keyboard (as happened for question 3), since the keyboard is already connected to the monitor process. Channels may only connect to one process (at each end). So, I guess that monitor must output to the pause process!
Oh - I see what you were wondering: connect keyboard to the pause process along with the input/output channels whose traffic it's going to freeze ... and pass on keyboard input other than `s' to the monitor. Well, you could try that but I would advise against. There is a nasty deadlock lurking if you do this ... can you see it?
Keywords: pause-process , q4
From Question 31 (2000), it says:
Getting the monitor to trigger a deadlock (in response to a `q') is easy and will earn full marks (for this part).
Would we get full marks if we implement a livelock ... or do we have to trigger a deadlock?
Forcing a livelock is a bad idea - your program keeps on running! Forcing a deadlock will terminate your program.
In Question 4, for the monitor process we are asked to implement the following: `any other character is an error and is processed by bleeping the screen'. I've looked at last years Q+A's on the web but I can't find help on this. Could you give some kind of clue as to how we can produce a bleep from the PC squeaker in occam?
You missed it! See the answer to Question 18 (2000).
2000 |
I get an error message when trying to compile the folowing:-
PROC plus.modified (CHAN OF INT in1, in2, control, out) WHILE TRUE PRI ALT control signal ... actions when control signal is received plus (in1, in2, out) -- <<< ERROR MESSAGE HERE :
I get an error message saying expected end-of-line found when a ? was needed. What's the problem?
You are creating an instance of the plus process in a position where the compiler expects another guard for your PRI ALT. There is nowhere legal you can put that line without adding an extra SEQ (or, possibly, PAR). Bear in mind that once plus starts, it never terminates - so don't ever expect to go around the loop again if you invoke it somewhere in the loop body ...
The first guard of your PRI ALT is syntactically illegal. There should be a ? in the middle of it - and where is your signal variable defined?
Finally, if your PRI ALT is really meant to have a single guard, it's a bit pointless - better simply to use a SEQ.
Keywords: q4
I am having some trouble with part 3 of the assessment. Here's my code:
... censored
What I'm trying to do is pass through a channel of INTs, multiplying them by a factor, whilst in parallel checking another channel to see if the monitor has passed a zero and, if so, changing the factor.
The problem is that KRoC won't complile the code because it won't let me read and write to a variable in parallel - which is fair enough 'cause I could see some problem arising if they both want access to it at the same time.
Is there a way to get round this, or do I need to rethink my ideas?
I haven't shown the code because it's wrong in too many ways, I'm afraid, and posting it would not help anyone.
It's not KRoC that won't compile it so much as the language doesn't allow it (and, therefore, KRoC rejects it). We are simply not allowed to look at a variable in parallel with another process that's changing it. So, you do need to rethink your ideas. Check out Question 44 (2000) and its answer.
Keywords: q4 , process-networks
I am currently doing the pairs toggling bit of Q4. I am trying to say
IF there is a toggle input THEN switched := NOT switched ELSE carry on excuting the rest of the code.
where toggle is an input channel and switched is a boolean variable.
You are describing a poll on the toggle channel. See slide 5-37 in the notes. You may consider the use of polling absolutely essential (see the comment on slide 5-37) for your solution to this part of the question - even though it's not!
Referrers: Question 47 (2000)
Should we be using PLUS/MINUS or +/- for Q4?
My class supervisor told me that we should be using +/-. But when I do that, my q4 process crashes very quickly due to not being able to wrap round into negative numbers. Is this OK or should I use PLUS/MINUS and allow the program to wrap round?
Please use PLUS/MINUS rather than +/-. That's what the plus process (from the course library) uses and that was chosen specifically to allow these demo programs to run forever. The Fibonacci sequence gets big very quickly - so the demo example program would crash very quickly otherwise. Of course, the numbers in the supposed-Fibonacci column are no longer from the Fibonacci sequence ... but never mind.
However, whether you use PLUS/MINUS or +/-, you will not lose marks. I've squared things with your supervisor!
In the specification for the p bit in q4.occ, it says: "take the output arriving from the tail from that arriving directly from the delta". I'm certain, well confident, well satisfied, ... ERM.. at least I think I've implemented it as specified, but my output gives:
-1 -2 -3 -4 ...
I am very tempted just to switch the channels going into plus so that it gives:
1 2 3 4 ...
when its in subtractor mode. Or are the negative numbers actually what's required ... i.e. the assignment means do as I say not do what you think I mean ... ?
You've got me here! In question 4 on the exercise sheet, it doesn't attempt to specify which way around the minusing should operate (in response to a p from the keyboard). So, doing it either way round would be OK.
In the q4.occ file, I tried to make this precise but - given the complexities of natural language - managed to say it the wrong way around :-( ... Apologies for this. So, doing it either way round - what I said or what I meant - is OK.
Keywords: q4 , negative-numbers
In question 4, when you press the i key to reset the integrate thingy, should it output 0, or the next value that comes in?
The question did not specify - so either version will be accepted.
Keywords: q4
I'm in the process of doing q4 and I've implemented everything except pairs. It all compiles but, when I run it, it immediately gives me an error:
Range error / STOP executed (signal 4) Fatal error code 1, core dumped Abort (core dumped)
First thoughts were that I had used STOP wrong. However, I took it out and still got the same error. I can't work out where I could be going out of range, so I just wondered if you could explain the error message to me so I could work out what part of my code it is refering to.
The run-time error messages are a bit terse, I'm afraid. The above error message can be caused by at least 4 things:
It's probably the last one that's your problem ...
Keywords: q4 , range-error , stop
Do you just want the code for q4.occ or do you want any new diagrams we have done drawn out as well?
You should submit hard-copy of your program listing attached to a cover sheet to the CAS office (by close of business on Thursday, 30th. November, 2000). You should also include network diagrams of any networks you have designed. In this case, that will be for your modified versions of numbers, integrate and pairs, together with the overall network for the q4 process. On these diagrams, channel names should be labelled with the names used in your code and the direction of data-flow should be arrowed. Neat hand-drawn diagrams on you program listings are fine.
For the assessment, are we allowed to code the modified versions of int and pairs sequentially, as is lecture slide 5-11? Or do we have to stick to creating them from the given components in "course.lib"?
No - when you modify those processes to introduce the reset/toggle channels, keep the same level of concurrency. But this can't be done just by inserting extra components from "course.lib" - you have to use some others. A big hint is supplied by the inclusion of the replace process in your starter file (exercises/q4.occ) - you just have to work out how to use it. The model answer reuses the existing sub-components (of numbers, integrate and pairs) unchanged - their behaviour is modified simply by inserting an extra process into their respective circuits.
Modified versions of slide 5-11 type implementations will be accepted, but will not attract full marks.
Keywords: q4
I am having trouble with the layout.max.chans process. I am calling it within another PROC as follows:
PROC q4 (...) ... ... [max.chans] CHAN OF INT c: PAR ... ... ... ... ... layout.max.chans ([c], screen) :
Am I calling it correctly?
No. Your c variable is already an array holding max.chans elements (that happen to be channels). The expression [c] creates an array with one element (that happens to be an array of three channels) - this is not what layout.max.chans is expecting! Your call should be:
layout.max.chans (c, screen)
Keywords: q4
When implementing the response to an `s' being pressed should it either:
The former - see the answer to Question 26 (2000).
Can we use the keyword STOP in response to a `q' being pressed in Assignment 2?
Yes - but KRoC is currently set up to regard STOP as an error, so your program will crash. That's OK but not very nice!
We might change KRoC to handle a STOP differently - occam allows more than one semantics. The default one is the current one - treat it as an error. The (arguably proper) one is that the process executing the STOP just stops, but other processes running in parallel continue.
If we made this change, then simply getting your monitor process to execute a STOP would stop that monitor - but the rest of your network might carry on producing output (depending on how you set it up). That would be wrong.
So, your monitor process needs to do something to block everything else as well (e.g. cause a deadlock). The model answer blocks all of the network, but leaves the monitor running (all it does is go into a state where it black holes all keyboard input). The system is not deadlocked because the monitor is still alive and accepting further input. Nothing more is being produced, though, and keyboard input is consumed but ignored - we have livelock.
Bringing a network to a graceful halt (by causing all its component processes to reach their natural end without triggering deadlock) is hard. The paper in the course book ("Graceful Termination - Graceful Resetting") shows how to do it - it's fairly mechanical but tedious. For this exercise, you would have to make new versions of all the basic cycle processes used from the course library - these new versions would be ready to terminate (i.e. no WHILE TRUEs).
But graceful termination is not required. Just getting the monitor to execute STOP is also not good. Getting the monitor to trigger a deadlock (in response to a `q') is easy and will earn full marks (for this part).
Referrers: Question 13 (2001)
I am currently working on modification 3 of q4. I have modified the code so that it switches between being a plus and minus process - but when switching to the minus process all the numbers printed are 1 greater than the number entered. Is this OK or should a further modification be made to compensate for this error?
It's OK! Turning the plus into a minus changes pairs into a differentiate, except that the first number that ought to be output is missing. All the question asks is that you make this change (dynamically, in response to a `p' from the keyboard). What it does doesn't matter. So the fact that it turns that last process into something that (almost) cancels out the second, leaving you with traffic that equals the input to the second - except that one number gets lost - is fine.
Keywords: q4
Help! I am trying to do part three of question 4 (the second assignment) and I can't get the following to compile. The error message is that state is not declared on the line marked:
WHILE TRUE SEQ BOOL state: state := TRUE -- start with normal pairs process WHILE state -- <<<< COMPILER COMPLAINS HERE ... loop body
Surely though, it is - just above the line which causes the compiler to fail!
No it's not!! It's declared two lines before the line complained of by the compiler. Declarations have scope for subsequent declarations and the first executable that follows (which must all be at the same level of indentation). In the above, the first executable following the declaration is the assignment - so state is in scope there, but not for the following executable (the while-loop).
To make the declaration have scope for more than one executable, those executables must be wrapped up in a SEQ (or PAR or WHILE or IF etc.) - that turns them into a single executable. This question has been asked before - see the answer to Question 3 (2000).
Keywords: q4 , variable-scope
Referrers: Question 54 (2004)
When implementing the part where the plus process is changed to a subtractor when `p' is pressed, am I right in saying we don't really have to change pairs apart from the reset. The rest is done by changing the component plus?
Yes - that is one way to do it. There is another way that does not require changing that plus process - merely inserts another component into the (modified) pairs network.
Keywords: q4
In Q4, when you say `suspends output to the screen', do you mean the processes should keep going and not output anything to the screen, or pause and wait until they are allowed to continue?
The latter - the processes should become blocked until output is allowed back through to the screen. Don't modify those processes in any way to get this functionalty. Do it the same way you did it for question 3 from the Execrcise Sheet (which was considered in your seminar groups).
Referrers: Question 32 (2000)
I am working on q4.occ. Inside one of my PROC headers, I have delcared a BYTE variable:
BYTE c:
I then read in a BYTE and store it into this variable. Then, I wish to do checks on this variable to see what character it is holding. For example:
IF c = 'n' ... do something
This obviously isn't how it's done? Looking back at bugs.occ quotations marks give the ASCII value of the char.
Please let me know how this is done as I can find nothing about this in the notes.
There is nothing wrong with the code fragments above. A character within single quotation marks is a BYTE literal, whose value is the ASCII code of the quoted character. Mail me (or your seminar leader) your complete code and say precisely what goes wrong.
Keywords: q4
On q4, when I convert plus to minus in pairs ... should the output from pairs be one greater than the output from numbers along the same row of data? For example, if the current numbers value is 7, then the value in the pairs column on the same line is 8 ...
Yes. (I'll say a bit more when the q2 submission deadline is over ...)
Keywords: q4
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License. |