This is the simulator for multi-thread MOS. Aim to be used for
midterm project by embed & realtime class March 2026. It is
modified from iot-rz-u-2
The simulator provides fixed 4-threads with round-robin schedule. It
binds with four user-defined function names: p0() p1() p2() p3(). One
instruction "sync" (implement as "trap...") is used to synchronise four
threads.
MT-MOS hides task-switching from user space, move it into the simulator
implementation. MT means (multi-thread). I will use "multi-task" and
"multi-thread" with the same meaning. The term "multi-thread" is used to
emphasise that it will run user program which is written in many parts
that co-ordinate to complete the task. A user can imagine that there
are many agents working to complete the task. (if this program run
on multi-core processor it will run multi-thread in multi-core hence make
it faster).
The interrupt will be disable in this simulator but devices such as wave
generator still function. You can read ports. However, timers and
interrupt will not work, including "wfi" will do nothing.
This simplifies the implementation.
To achieve task-switching, context of the threads are save/restore.
They are: all registers, PC. Task-switching occurs when time-out
(for example, run 1000 instructions). Sync instruction may cause
task-switch (explain later).
to recap, this is the pseudo code for sim21:
interp
loop (runf)
read command line
run
there are two kinds of run: trace, runoneclock
runf is a global flag. it is used to stop the simulator (with command
'q').
runoneclock
clock++
simdevices
if runflag && cpuflag
run
checkforinterrupt
runflag is used to stop simulator at instruction "stop". (different from
runf)
cpuflag is used by wfi to bypass cpu run (but clock is still advanced)
wfi reset cpuflag (to 0)
when interrupt occurs set cpuflag (to start executing instruction)
runflag initially is 1, it is reset to 0 by 'stop' (no other place change
runflag).
trace
while not break && runflag && clock <
MAXSIM
run
the simulator for MT-MOS has runoneclock modified.
runoneclock
clock++
simdevices
if runflag
run
no cpuflag (wfi does nothing) and no checkforinterrupt
The instruction sync will synchronise four threads. If you use "sync" all threads must have "sync" instructions. When encounter "sync" in each thread it will check that all four threads have reached this point then it will continue otherwise it will stop here. task-switch will occur. Once this thread is re-active it will be at this instruction again (recheck if it can pass).
One global flag "sync_flag" is used to control stop at sync instruction.
Four local flag "sync_lo[.]" signal each thread that reach this
instruction.
local and global flag has this relation:
all local are set, will set global
all local are reset, will reset global
behavior of sync instruction:
two states: "encounter" (sync_flag 1), "pass" (sync_flag 0)
each thread
"encounter"
set local (sync_lo[th_number] = 1)
if all sync_lo are set, set sync_flag
<PC does not move>
task-switch
"pass"
reset local (sync_lo[th_number] = 0)
if all sync_lo are reset, reset sync_flag
<PC++>
sync_lo[.] is local flag, th_number is the thread number.
There is no "race" because when all threads "encounter", each local flag
is set, when all local flags set, sync state becomes "pass".
When all threads "pass", sync_flag is reset, sync state becomes
"encounter", ready for "sync" to be execute in the future.
last update 8 March 2026