So, good morning, ladies and gentlemen.
I am Pavel Pisa from Czech Technical University.
I teach computer architectures for something like 20 years.
From year 2000, we follow the famous Professor Hennessy
Patterson book about the computer architectures.
And we have used the original MIPSIT simulator, which
has been distributed with the book, but it has got dated.
So we decided that we need to do something for our students
to have a better experience.
And we started first with MIPSIT simulator,
and then we switched to RISC-5.
And this was work, it has this work of the Jakub Lupak,
our student.
So I hope that everything is working,
and I pass him a mic and the stuff.
OK?
So, good morning.
Over the past decades, computer engineers
have been creating faster and faster computers.
Meanwhile, many software engineers
kept writing slower and slower software.
And in many areas, this is fine, but in other ones,
we need to process pretty much insane amount of data
often in real time.
And to do that, we need really efficient software that
can exploit the capabilities of the hardware.
And only software engineers who understand
the principles of the hardware can do that.
So to ensure we will have such software engineers,
we need to teach our undergraduate students
at least the basics of computer architectures.
And because nobody wants to learn with pen and pencil
anymore, we started using graphical simulator.
So, and it is more.
Yes.
So we started with a MIPSID simulator, as was mentioned,
which was shipped with the Hennessy Patterson books.
However, it had pre-limited features,
and it only worked on Windows.
So in 2019, Carl Kochi was sitting over there,
created Qt MIPS, graphical simulator of the MIPSMaker
architecture.
And it was continued with a lot of work of Dr. Pisa here.
And in 2032, myself, with my colleague Max Holman,
and again, a lot of work from Dr. Pisa,
we have switched the simulator to RISC-5
so that we could switch all the undergraduate computer
architecture teaching to RISC-5.
So we are there.
The simulator is licensed under GPL-3,
and it's native simulator running under Qt-5 and 6.
It's developed and available on GitHub.
And to better collaborate on the materials,
we have joined forces with our sister faculty.
We are from the faculty of electrical engineering,
and they are the faculty of information technology,
and we have created what we call computer architectures
education projects.
And you can find all the materials
that we have recorded in lectures, slides.
You can find it there.
And furthermore, to collaborate with as many people
as possible, the university has joined the RISC-5 foundation
lately.
So the simulator is called Qt RISC-5,
and it is currently used by our university,
the Technical University in Graz, University of Colorado
at Colorado Springs, and University of Porto.
The previous MIPS version is still
used by the Charles University in Prague,
and National Coupled History and University of Athens.
And this talk will focus on the teaching and user perspective
if you are interested about how it works inside,
at least a little bit of it.
You can look up the talk that we gave
at the RISC-5 International Academy and Eurotraining
Special Interest Group.
So before I dive in, as Dr. Pichai mentioned,
you can just open this link and follow the presentation
with the simulator running in your browser.
It is in chat.
Great.
So let's dive in.
When we get students who have never heard anything
about computers before, we need to start really simple.
So what we do is that we start with a very simple, single cycle
micro-architecture, and we show them
how basic instructions are processed there.
So this is the simulator.
This is how it looks when you open it.
So we will hit No Pipeline and No Cache to get started,
and hit Start Empty because we will use one of the examples
provided, so file examples, and simple load and store work.
As you can see, the program is really simple.
It just loads from one part of memory,
stores into another, and then goes into loop using branch
instruction.
So this is the basic view that we start with.
And on the right side, you can see
detail of the program memory with address of each instruction,
hexadecimal code of the instruction,
and the disassembled instruction itself,
where the last two columns can be edited directly
in this view by double-clicking and writing
the instruction or pasting the code.
And furthermore, the left mode column
is a place where you can set breakpoints,
so you can use it like a TV debugger,
or at least the simplest part of that.
And now we can move to the heart of the simulator,
and that is the visualization of the pipeline.
So if you look closer, on the left,
we start with the program counter, program memory,
and circuits to update the program counter.
We load the instruction, and here you
can see the hexadecimal value of the instruction shown
on the bus, and it gets to the control unit,
where we send all the control signals that we need.
So we are showing globeboard instruction,
so we need to send the data from memory to registers.
We need to read the memory, and we
will need immediate value for the arithmetical and logical
unit.
Right here, we can see mechanisms for resolving branches,
but this is globeboard instructions.
I think there's a thing there.
And here is our arithmetical and logical unit,
which has two possible inputs, either from registers or from PC.
And the other one has either value from registers
or from immediate decode.
Here we get the requested operation of the ALU,
and here we get the signal whether the result was
zero for branching.
And finally, here we have the data memory,
if it address, and the data to be written.
So we start executing, and we see
that the instruction load board was highlighted,
and in the register view that appeared up there,
we see that value 1 through 8 was written
into the register bank, which is highlighted by the red color.
If we continue, we move to the starboard instruction,
and now the value needed to be read.
So it's blue now.
And if we go back to detail of the view,
we see that we read that value from register,
and we are sending it by this wire to the data memory
to be start.
We also read the address from the immediate decode,
and we are sending that to the arithmetical and logical unit
to be added to register, which is in fact zero.
So we are just sending the value to the memory,
and now the memory can write.
So let's see what happened in the memory.
Here we can see the address 4 or 4 with the value written.
So it corresponds to the address we have here,
and to value we have here.
And right above it, we can see the place
where we read the value from.
So speaking of the memory view, right now
we are working with words, but we can work with other sizes.
So you can switch the view for the unit
to be either word, half word, or byte,
which will work with respect to both Littler and Big
Indiana's.
And once we add cache, which will be in the moment,
we can switch the memory view between direct view of the memory
and view where we are looking through the cache.
So we will see also the cache data.
Now we move to last instruction of the long program.
That is the branch equal instruction.
And we will see that we take the destination from immediate.
It's negative, so we're jumping back.
We add it to the program counter,
and here we send it back to the program counter.
In the control unit now, the signal for branching,
for the most generic one, is active.
And we see that the branch resolving mechanism
determined that the branch should be taken.
So we go to the program counter, and instead
of taking the program counter plus four,
we are now instructed to switch this multiplexer
and take the value computed by the arithmetical and logical
unit.
So here we have detail of the program counter
and the register itself in the pipeline.
And as you can see, we continue to the load bar instruction
so that we can keep running in a loop in this example.
So this is a very basic example just for this presentation,
but it gives you an idea how we start with the simple processor.
And when students have idea of what the virus are doing
and what it all means, we can start
speaking about how to make the CPU faster.
And well, what we find out that the memory is slow,
so we want to cache it.
However, that's not that simple.
There are many ways to cache it.
We can cache data.
We can cache instructions.
We can choose different sizes of the caches.
And if you do it wrong, it will be worse than doing nothing.
So we really need to think about that.
So we switch to the second option in the configuration
and add in time empty.
But this time, we will hit the button up there
which will open integrated editor with syntax
highlight and integrated assembler.
The other options are to open file, to save file, close file.
This is the important one.
This is to run the assembler and upload it to memory.
And if you have some more complex project,
you can even invoke external make file.
Except for WebAssembly where there is no make.
So we insert a simple selection sort.
You will use, for example, I put it in free column
so that we can see the program.
But just a simple selection sort was important here.
That we have data that will be put into the L file
and later start into memory.
And that will be the data that we want to sort.
So we save the file so that we don't lose it
and we move to the memory view.
Right here, you can see the data that we have inputted.
And on the right side, new windows opens.
And it's the detail of the data cache.
It has two parts, statistics of the cache performance.
And it has very detailed view of the internal structure
of the cache and the data that are there right now.
So if we start running, the cache was empty.
So of course, we need to edit and we will miss.
And we will continue adding the value.
And right now, the cache is full.
So first decision that the students need to understand
is, what shall we edit?
So right now, there is random choice.
So it evokes the first one and we continue running.
And right now, the selection sort will start placing values
where they should be.
So it moves the value number one to the first one.
And you see the yellow highlight shows us
that the value is now written in the cache
and the cache is dirty.
So right now, the cache is using writeback policy
just to show you the highlight.
And we can continue.
And now, we switch one with five.
And it was a simple example, so the array is now sorted.
But we still need to go over it because the CPU doesn't see
that, needs to check it.
And because we use the writeback policy,
we also need to run fence instruction
to make sure that everything is stored back to the memory.
So you see there is no highlight anymore
and the cache is empty.
And this is a time where we should look at the performance
data and we will see that we have quite an improvement.
Of course, it depends on how fast memory we have
and fast cache we have.
So in the configuration, you can set the penalties
for hits and misses so that this data will look
according to what you need.
So this is the configuration of the data cache.
You can see that we can select different shape of the cache,
which means number of sets, block size,
degree of associativity.
And then we have two policies.
Replacement policy, which is out of random,
last recently used, or least frequently used.
And writeback policy, which can be,
you can see writeback right through the options there.
So here is how the detail of the shape of the cache
looks for two different configurations, which in fact
have the same amount of data there.
But they will probably have quite different performance.
And also, the right one, it's way more complicated.
So the students can examine what this
will do to their particle programs and data loads
that they will have.
Of course, we have also program cache.
And I have added this very stupid design
where we have just one cell.
And well, in program, you never go to the same address twice.
So you can see that we always missed.
And it's actually worse than doing nothing.
So just an example of that.
And I mentioned that the windows can just appear.
So if we prepare some example code for students,
we can insert special pragmas to make the windows appear
so that the students who have not seen the simulator before
can just start with all the tools they need.
So we can show any part.
We can focus address in memory, and so on.
So now we have improved the speed of the memory.
And we look at the CPU again.
And we find out that most of the silicon
is just lying there doing nothing most of the time.
So we want to utilize it better.
So we see that most of the parts are somewhat independent.
So we split it into five parts.
So let's go to third option.
We will choose pipeline without cache.
And you can see that the image got somewhat more complicated.
However, if you remember the previous, it's all the same.
So students already invested some effort
into understanding what the image was supposed to mean.
So we don't want to move things around.
We are just adding the minimum amount of things
that we need so that we can continue
with the more complex stuff.
So you can see we display all the instructions
in each stage of the pipeline.
We are adding the interstage registers.
And the colors are not the random.
We are also using that to show which instructions correspond
to each stage of the pipeline in the program view.
So you can see all the stalls and branches nicely
as they progress through the pipeline.
And of course, we needed to add animated windows
to each stage of the pipeline for each wire,
for both control and data that we have.
And now we find out that this is not all we need to do.
Because up until now, we assumed that, OK,
we process one instruction.
Instruction is done.
We continue.
But right now, we start processing instruction.
But it will take, what, former cycles before we get the results.
So we have something that's called data hazards.
And that means that if we do nothing,
we will get all the data.
Because the data from the instruction
that we depend on is not ready yet.
So we can have hazard spending two cycles in the next instruction
and hazard spending one cycle in the instruction after.
Technically, there is also hazard in the instruction
that is after that.
But this is something that we can solve inside the register file
without breaking the abstraction of the pipeline.
So we will ignore the last case.
And so what can we do about that?
Well, we need to detect those problems.
And we need to counteract them in some way.
So we are adding hazard unit to the CPU.
And it has two options.
First option is, OK, we will wait for the data.
But we said we want to build a fast CPU.
And waiting is, well, not fast.
So we also have option to forward the data as we need it.
So yeah, it's in the core tab.
And this is the option.
So this is the CPU with edit forwarding paths.
So what we have here is we are adding path
from the writeback stage to get it directly
into the execute stage.
The multiplexers got bigger.
And we are adding second path to forward the data
from the memory stage.
So here is the difference.
There is some extra wiring.
The CPU looks, well, simpler.
But it will wait.
And that's what we want.
But it will cost us more to build it
because it needs more components.
So let's see some actual examples.
We are again learning the selection sort I showed you
before.
So we start running the instructions.
And right now, we have our PC instruction
that is producing its value to register 10.
And the hazard unit started screaming.
It doesn't like it.
So it tells us it's not very, very visible.
But the text in the red is forward.
So this is the hazard that we have here.
And what happens is that this multiplexer
gets value to use the forwarding wire from the memory stage.
And instead of using the actual value for registers,
we are taking the value for the red path.
And we get here for the arithmetic analogic unique value
hexa 200, which is what we want.
Well, you don't know that yet.
But to remember that value, it will be important later.
OK, we don't want to add the extra hardware.
So we will stall instead.
So this hazard unit is screaming again.
But this time, it cannot forward.
So it's screaming to stall.
But you can see that the instructions
are right next to each other.
So that was the first case.
And we need to actually stall two cycles.
So we will run next cycle.
Another knob is inserted.
And again, the hazard unit is screaming.
So right now, we have any two knobs.
But what we have now is that the instructions
are far apart enough.
And we can continue.
So we get value, thank you, 200 hexa again.
And we are happy.
Well, and then the simulator, of course, supports
the most simple option, we do nothing.
And what happens here?
We have the hazard.
And we get value 0 because the registers were initially empty.
What is the purpose of this setting
is that we will task the students to play the hazard unit
and play the compiler.
So they will have to rearrange the instructions
and insert as less knobs as they need
to make sure that the result will be correct.
This will typically be some kind of homework.
So we don't want to control that manually.
So we have a command line interface,
which can look something like that
and will give you output like that.
So the capabilities that we have here
is to assemble file, to set the configuration,
to trace instruction in each stage of the pipeline,
trace changes to memory and registers,
also at the end to dump the memory and registers, which
is the most useful part because we
want to make sure that the result is the same as it should
be, for example, when the hazard unit is not available.
And finally, when we want to plug in some data,
for example, when the students are supposed to sort,
they should not know the data, so we
have special option to load data into the memory.
And right now, we have CPU that, for undergraduate students,
it's quite fast, but it's quite simple.
So now instead of making it fast,
we will make it more complicated.
And we are adding memory map profiles
and some very simple operating system emulation.
So if we open the templates again,
you can see that there is template for operating system.
And it really does nothing special.
All it does is prepare for calling system call,
which is equal in risk five.
And we will print hellward to file.
The file is connected to a terminal.
So what we actually do is, after running the,
now we get the equal detected, you
can see that there is something correct written
that is detected syscall.
So we will stop fetching new instructions,
so it's more clear for the students.
And once we get to memory, here is
our hellward in the simulated terminal.
And you can see that the pipeline is empty
because we are looking at this from the perspective of user
land.
So the operating system is emulated,
and we don't see the instructions in the pipeline.
We just see that the pipeline was flashed before.
It was written to us.
So this is the system calls that we support.
It's not much, but it's enough to show the basics
to the students.
And this is all the peripherals that we can play with,
mainly using the system calls.
So this is not peripheral, but we
have control and status registers,
some basic supports of them.
We have an LCD display.
The terminal I've already shown you,
and there are some general purpose IOU peripherals,
two LEDs, three knobs with buttons.
And this might seem a little random to you.
It's not.
Because we also have this relevant board that
has exactly the same peripherals.
And the simulator is set up in a way
that you can take the same code, well, not assembly code,
because, unfortunately, the board is ARM.
But you can take the same C code,
and run it both on the simulator and on the real board,
and you can move back and forward.
So I said C code, so we can't use the integrated assembly
anymore, and we did not implement C compiler.
So you can use Clang or GCC to compile
the file into ELF, which, of course,
is to be statically linked.
And what we do now is, instead of hitting the start empty,
we will here insert the ELF executable,
and we will hit Load Machine.
So this is example of some program
that writes to the LCD display.
I will not show you the code here,
because this is one of the tasks that we give our students.
But I can show you this code.
This is available on our GitLab.
We provide a link here.
And it is a test suite, simple for malloc, from the new lip.
So you can link your code to the new lip
and use it in our simulator, or at least some basic parts.
And we have tested that with malloc.
So we can run this, and it's connected to the terminal.
So we can see that some dynamic allocation takes place,
and some checks take place, and the tests
are running successfully.
So now you can use actual dynamic allocation
inside the simulator.
And now some conclusions.
So frequently asked questions.
Is the simulator cycle accurate?
That's a pretty important one.
Yes, kind of.
The thing is, we always assume that the memory has enough time
to finish, and if it doesn't CPU will wait,
we will not insert stores or anything.
The memory will finish, but that's the only exception.
Otherwise, it's inside written in quite similar style
to malloc, system malloc.
So is this compliant with the official RISC-5 tests?
And yes, I can please see this.
Yes, in the previous version, we have added that,
and it's integrating into our CI,
so every new changes are tested against that.
We support the graphical parts, so it
supports the RISC-5 I with multiplication,
and also with control and status registers instructions.
The command line also supports 64 bits.
However, I yet need to find out how to fit the 65 bit values
into the visualization, because it's already quite full.
And we don't have a virtual memory yet,
but somewhere here in other room,
there is a student who already promised
to take care of that in the next year.
So in a year, he might be presenting the change here,
so we'll see.
So what we plan for the future, we
are very close to adding interrupt support.
We would like to add compressed instruction set support,
because that's quite key part of RISC-5.
The only trouble there is it's pretty hard to,
I'm not sure how to fit it into the program view,
because then it needs to be presented sequentially,
and I'm not sure how to show it that the students see
that it's really half of the size.
So that's plan.
Also, the instruction encoding in RISC-5 is somewhat
special, especially around immediate.
So I would like a visualization of each component,
the blocks that the instruction is composed of,
so that that can be seen for each instruction,
and inspect it, and edit it.
We want to be able to run a very minimal RISC-5 Linux
target.
I mentioned 64-bit visualization and the program with that,
also the memory unit.
Another nice thing would be to visualize
the utilization of the pipeline,
the image that is typically in every book,
when you have squares for each instructions,
and you see the spaces where no instructions were executed.
So it would be nice to add.
And also, even when I made these slides,
I would really love to have an option to step back,
because I went one instruction too far.
And it would be really hard to do it with all memory
and everything, but at least for the visualization
of the pipeline, I would really like that.
So if you are a teacher, represent educational institution,
and you want to use the simulator, please do.
If you have some problems, contact us.
We'll be happy to cooperate on that.
If you are a student or developer,
this is open source project, we accept your request.
And usually the way it works is that students
do their final thesis on this project, so far free.
And if you are a distribution maintainer,
you could help me with putting in the official packages.
So you can get the source at GitHub,
and we also provide executables for Windows, Linux, and Mac.
And we have packages using the open-source build system
and launchpad for Ubuntu, SUSE, Fedora, and Debian.
And there are also packages for our Nix packages,
because those are those that I use.
And as we mentioned, we have the online version as well.
So if you would like to read more,
we have some publications, the thesis, and our paper
from the Embedded Word Conference last year.
So those are available.
And we have this subject, and you
can find a lot of the materials at the Comparch.
It's some of the materials videos.
Some are in Czech, many are in English.
And that's all from me, so thank you for attention
and for so many people coming.
Thank you.
Please.
How tightly coupled is the simulation
of the processor and the visualization?
I was thinking, would it be possible to somehow connect
something like ModelSIM with the HDL model?
Or would that be very, very difficult?
These are repeat the questions for the screen.
Sure, so the question was, how tightly coupled
is the visualization and the simulation?
So it's a separated project that is linked together
and is only connected with some data passing and QT signals.
So we already have the visualization and the command
line that are completely separate,
and they are just connecting to the same signals.
So it's quite well separated, but it's not at all stable.
So, any other question?
OK, if you have no other questions,
we do not work only on the simulators,
but we do even the design of peripherals.
So for example, we have open source,
can have these stuff, we work on open source replacement
of MATLAB and simulink.
OK, it is toy, but we work on such stuff.
So if you have interest, we have their links
to our other project.
We have experience with motion control.
I have about 30 years of experience
with embedded system design, including infusion systems
for medical applications.
I have contributed to RTMS project, which
is used in European space agency and so on.
We do VHDL design for the experiments
of its space-grade FPGAs and so on.
So this is the work which we do to help our students.
It is a lot of work, something like eight
many years of work in the simulator,
but it is only for our students, but we
do even the serial stuff for the world.
For example, in Socketken, in mainline Linux kernels,
there are our open stuff, contribution drivers, and so on.
I have a question.
OK.
Sir?
Yeah?
So what do you use for the actual visualization
of the pipeline?
Because I remember there's something like this in,
say, Altair Fortress, which does schematic
after-invisualization.
Well, is this yours?
No, no.
Something you could pull in from some other person?
No.
At point point, which will take three hours.
Yes, the visualization that you see is actually an SVG file
that has special annotations which connected to the core.
Previously, it was done by generated QT objects,
but I was not OK to work with that.
So I switch that to the SVG version
when you can design it all in graphical editor
and then you just connect it to the simulator.
So that's completely ours.