XML

kent logo

CO538 Anonymous Questions and Answers

This page lists the various questions and answers. 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.

We have taken the liberty of making some minor typographical corrections to some of the questions as originally put. Although most of the questions here will have been submitted anonymously, this page also serves to answer some questions of general interest to those on the course.

When asking questions, please do not simply paste in your code and ask what is wrong with it, as these types of question are hard to answer in a public forum (resulting in either no answer, or an answer which will only be of use to the person asking the question). In many cases, a question about code can be formulated in general terms. For example, if you have an `IF' block that results in an `incorrect indentation' error, you might ask, ``what is the correct syntax for an occam `if' statement ?''. Questions of this form are easier to answer, and are meaningful to all.

Questions that are not suitable for these public pages (i.e. those that contain assignment-specific code), should be mailed to your seminar-leader.


Question 41:

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.

Answer 41:

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..

Keywords: replace , q4


Question 42:

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 ?

Answer 42:

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


Question 43:

Hi, what is the general problem if when you go to run an occam program it just crashes ?

Answer 43:

There are a number of probable causes, have a look at the answer to Question 103 (2003) or Question 70 (2000) (and other related questions via the keyword index).

Keywords: stop


Question 44:

Can we draw out diagrams for Q4 by hand on paper next to our code, or do we have to do them neatly in the documentation for the coding like you have done?

Answer 44:

As you say, submissions for your second assessment exercise (Q4) must include process network diagrams for your modifications. Only the diagrams supporting your submission need be submitted (i.e. only those for your final system -- not all the intermediate stages).

Your submission must be on paper (with cover sheet to CAS by 4pm next Monday). Your code will be a listing of your q4.occ file. Neat hand drawn diagrams on this listing are perfectly fine. ASCII art (as in the starter file) are acceptable, as are diagrams produced by any drawing package, but there are no extra marks for this.

The diagrams need are those for the overall system, plus separate diagrams for each modified process that has a sub-network -- in this case, the resettable versions of your numbers generator, integrator and pairs processes.

Keywords: diagrams


Question 45:

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 ?

Answer 45:

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


Question 46:

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?

Answer 46:

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


Question 47:

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.

Answer 47:

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


Question 48:

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?

Answer 48:

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


Question 49:

In the buffer process (slide 13), by using an ALT instead of a PRI ALT, could the request signal potentially get starved untill the buffer is full? I just thought it would have been better to use a PRI ALT with the request channel so if a request does come in it gets serviced straight away.

Answer 49:

Yes. As you say though, once the buffer is full the request channel is the only one in contention for the ALT, so it would definitely be serviced then.

If you use a PRI ALT, giving priority to the request channel, the reverse starvation will happen. Consider an un-full buffer with some process trying to push things into it competing against an aggressive requester, who always takes his output and comes back for more before the buffer has had time to loop and consider servicing the pusher. In this case, the pusher is starved until the buffer is empty -- at which point, it would definitely be serviced.

So, a PRI ALT is not the answer to providing fair service between competing guards whose pattern of readyness is not known in advance (and may sometimes be always ready). A plain ALT provides an arbitrary service mechanism -- no good if fairness is required. A PRI ALT guarantees un-fairness -- again, no good if fairness is required.

There is a simple solution to this and you are invited to work it out. We do use a PRI ALT, but in a subtle way. With a guaranteed unfair mechanism, we can produce a guaranteed fair one. :)

Keywords: alternation


Question 50:

Do you know if it is possible to use PFE to compile and run occam programs ? I know it can be done for Java by associating it with the file-extension ".java" and then telling PFE how to deal with those kind of files. I only ask as it would be helpful if I could edit, compile and run occam programs in a single environment.

Answer 50:

Setting up PFE for editing occam is, as you suggest, pretty simple. Compiling and running occam in windows is a fairly non-trivial matter however. The only windows support so far for KRoC is from cygwin, that provides a Linux/UNIX/POSIX-ish environment in windows. The latest pre-releases of KRoC build ok in cygwin, but it's not entirely different from the same things in Linux -- you still have to use a command-line (i.e. the "bash" shell).

It's definitely within the realms of possibility to make PFE launch stuff in cygwin (i.e. the "kroc" compiler, and assuming success, a shell running the program), but this would probably be non-trivial (involving the writing of DOS batch files or bash shell-scripts).

At some point in the future I hope to have a native windows port, but this is fairly low down on the list of things to do. Personally, I think windows is an absolutely awful environment for any kind of programming. With some time and patience committed to Unix you can learn how to edit, compile and run programs very efficiently. Vim is probably one of the most powerful editors available, but like Unix, it takes time to learn how to use it effectively/efficiently.

Keywords: pfe


Question 51:

I have started Q5 and was wondering if you could give any tips on how to convert a character to upper case. And also what you mean on flushing and how to do this.

Answer 51:

Just as a side-note, Q5 is not for assessment -- but doing it anyway yourself is useful! There are essentially two ways to convert between lower and upper case characters. The first is to do it arithmetically (since `BYTE's can be treated as regular values):

    upper.char := (lower.char - 'a') + 'A'

Of course, you'd better check that `lower.char' really is in the range `a' to `z' first. The second method is more cunning, and relies on the way ASCII characters are assigned:

    upper.char := lower.char /\ #DF

For flushing, see the answer to Question 91 (2000).

Keywords: q5 , flush


Question 52:

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?

Answer 52:

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


Question 53:

Are differentiate and minus predefined or do we have to define them?

Answer 53:

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


Question 54:

How can I make a simple routine that forwards data of `NAME.NUMBER' ? I'm trying:

    SEQ
      INT size:
      in ? size::n; m
      out ! size::n; m

And have also tried:

    SEQ
      INT size:
      in ? string; size::n; m
      out ! string; size::n; m

But I'm getting errors such as "string is not delcared" and "Simple input is not allowed on a channel with a tagged protocol".

I have looked over the chapter 10 pages, but it doesn't cover protocol input for just one type of input. I assume you don't need to use another CASE here.

Answer 54:

The first problem is the scope of `size'. See the answers to Question 19 (2004), Question 29 (2000) and Question 3 (2000).

As for the tagged-protocol input, why do you `assume you don't need to use another CASE here'? Slide 10-21 in the printed notes (chapter 10, slide 25, in the Powerpoint) and section 7.2 of the "occam2 Checklist" show you the syntax for this:

    in ? CASE
      INT size:
      string; size::n; m
	out ! string; size::n; m

If you don't specify the `poison' case, that's fine ... but if a `poison' arrives, your process will STOP (i.e. crash!).

So, the above is what the code fragments in your question should have been, assuming that your variables `n' and `m' have also been defined somewhere (e.g. just before or after your `size' declaration). However, this code fragment only forwards `string' variants of the `NAME.NUMBER' protocol -- not all data variants as the wording in your question implies. In your solution to Q6, you will need to be handling all variants of `NAME.NUMBER'.

However, here's another bit of occam. When inputting a `CASE' protocol, if you are sure that only one variant message will arrive, there is a special syntax ... but you still have the `CASE' keyword and the relevant tag name. For your example, the shortcut code would have been:

    INT size:
    SEQ
      in ? CASE string; size::n; m
      out ! string; size::n; m

though it's not actually any shorter (because of the need for the `SEQ')!

Keywords: q6 , protocol


Question 55:

In an previous anonymous question someone asked how to compare strings. The answer said to pass these BYTE arrays through the "make.string" function and then use "compare.string". However, I get the error:

    make.string is not a function

Is this a provided function or do we have to make it ourselves ?

Answer 55:

"make.string" is provided, but it's not a function -- it's a procedure. It adjusts the BYTE-array given to it as a parameter so that the string can be used with the other string functions -- which are really functions (e.g. "compare.string" and "equal.string"). The the answer to Question 50 (2003) for a code example on how to use it.

Keywords: q6 , string-handling


Question 56:

Would it be possible to give a step by step guide as to how to set up Cygwin on an off campus PC running Windows so that it would be possible for us not to have to be at the uni to do our work ? I've tried to set it up, but there seem to be so many different things to download and extract that I just get lost!

Answer 56:

Possibly; I'll look into it, but no promises. It's essentially the same as setting it up on Linux, except that you need the cygwin versions of the various development packages (gcc, libc headers, binutils, etc.). I'm not a cygwin or windows user, even though I did produce the cygwin port. Only the very latest (pre-releases) of KRoC work with cygwin, so they're probably not entirely stable (but certainly stable enough for CO516 needs). The next major update will be a port of the new KRoC for raptor (the KRoC installed on raptor is quite old -- ~1995). A proper windows port is on the cards, but probably won't happen for another year or two yet (I have no desire to use Windows for anything, especially not software development..). A MacOS port is also on the cards, since that's just another UNIX port.

The first time I setup cygwin I had no knowledge of it, but combining the errors output from KRoC's build script with google searches and package searches on cygwin eventually got me to a working system.

Keywords: windows

Referrers: Question 131 (2004)


Question 57:

As a follow up to my cygwin question, I have off site access to raptor, can I connect to that and run occam files through it?

Answer 57:

Of course! Once you're logged into raptor, just go from the command-line as usual. You'll probably not want to run anything X11 based over your home connection, though. I've got a 512 kbit ADSL line, and gvim is barely usable. However, command-line vim is just as good (slightly less fluffy), still syntax highlighted etc. Latency will be the main issue for doing stuff on raptor remotely.. Of course, you can edit your files at home then just upload to UKC. If you're on the VPN (which is free access I'm told) you can mount your raptor file-store as you normally would from a PPC.

Details on remote access to raptor, etc. can be found from the usual systems group pages.

Keywords: windows


Question 58:

Just finished Q6. It outputs the same table as given in small_result.txt. One problem though - it deadlocks - most probably because the cells are awaiting more input. Is it ok to leave the program deadlocked once it has finished?

Answer 58:

Your solution to Q6 must not deadlock after processing all the data. That's the whole point of sending through the poison message -- so that each process knows when its job is done and can terminate! Look at the given processes read.data and display. Once they have processed the poison, they terminate. For your collate.marks, processing the poison means outputting all the collated names and marks and, then, outputting the poison ... and then it should terminate ... it should not loop back and await more input!

Keywords: q6


Question 59:

Hi, what is the best way to to wait 1 second within a loop ? (Required for q5)

Answer 59:

See the answer to Question 80 (2000).

Keywords: timers


Question 60:

Hi, could you just give an explanation of how the following code works (taken from "sort_pump.occ"):

    PROC sort (CHAN OF BYTE in, out)
      [total - 2]CHAN OF BYTE c:
      PAR
        cell (in, c[0])
        PAR p = 1 FOR total - 3
          cell (c[p - 1], c[p])
        cell (c[total - 3], out)
    :

Thanks.

Answer 60:

This code creates a pipeline of processes (of `total - 1' cells) -- see slides 5-17 and 5-18. The two end cells are catered for specially (since these plug into the external environment -- via `in' and `out'). The cells between these are created using a replicated PAR. If you substitute a constant value for `total' (say 10), then expand and flatten the PAR replicator, it becomes a bit clearer:

    [8]CHAN OF BYTE c:
    PAR
      cell (in, c[0])

      cell (c[0], c[1])        -- PAR p = 1 FOR 7
      cell (c[1], c[2])        --   cell (c[p - 1], c[p])
      cell (c[2], c[3])
      cell (c[3], c[4])
      cell (c[4], c[5])
      cell (c[5], c[6])
      cell (c[6], c[7])

      cell (c[7], out)

Keywords: sort-pump , par , replicator

Valid CSS!

Valid XHTML 1.0!

This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.
Last modified Mon May 20 13:50:23 2013
This document is maintained by Fred Barnes, to whom any comments and corrections should be addressed.