1 |
6 |
hellwig |
|
2 |
|
|
Project History
|
3 |
|
|
---------------
|
4 |
|
|
|
5 |
|
|
14-Nov-2002
|
6 |
|
|
Project launched.
|
7 |
|
|
Main makefile written.
|
8 |
|
|
Directory structure created.
|
9 |
|
|
|
10 |
|
|
15-Nov-2002
|
11 |
|
|
Kernel of UNIX 7th Edition copied.
|
12 |
|
|
Download and installation of lcc.
|
13 |
|
|
This included the following steps:
|
14 |
|
|
1) In 'src', copy 'mips.md' to 'eco32.md' without changes,
|
15 |
|
|
except that the interface record is named 'eco32IR'.
|
16 |
|
|
The code output remains for now as it is in 'mips.md'.
|
17 |
|
|
2) Add instructions to makefile for compiling 'eco32.md'.
|
18 |
|
|
3) In 'src', add the interface record definition 'eco32IR'
|
19 |
|
|
to the file 'bind.c'.
|
20 |
|
|
4) Add a directory 'include/eco32/linux' and copy all header
|
21 |
|
|
files from the corresponding directory for the mips processor.
|
22 |
|
|
5) In 'etc', copy 'irix.c' to 'eco32-linux.c' and change the
|
23 |
|
|
contents of this file to properly call the preprocessor,
|
24 |
|
|
the compiler, etc.
|
25 |
|
|
6) Add the option -DLCCDIR=\"$(BUILDDIR)/\" to the instruction
|
26 |
|
|
in the makefile which compiles $(HOSTFILE).
|
27 |
|
|
7) In 'src', substitute 'lex.c' with a newer version, which
|
28 |
|
|
computes the types of hexadecimal constants correctly.
|
29 |
|
|
Disk creator done.
|
30 |
|
|
Program to write the bootstrap sector done.
|
31 |
|
|
|
32 |
|
|
16-Nov-2002
|
33 |
|
|
Preliminary instruction formats defined.
|
34 |
|
|
Preliminary instruction set constructed.
|
35 |
|
|
Some ideas for an address translation unit noted.
|
36 |
|
|
|
37 |
|
|
17-Nov-2002
|
38 |
|
|
Final instruction formats defined.
|
39 |
|
|
Preliminary version of simulator finished.
|
40 |
|
|
|
41 |
|
|
19-Nov-2002
|
42 |
|
|
Instruction set cleanup done.
|
43 |
|
|
Work on assembler started.
|
44 |
|
|
|
45 |
|
|
23-Nov-2002
|
46 |
|
|
Four of the five ROMs translated to ECO32.
|
47 |
|
|
|
48 |
|
|
24-Nov-2002
|
49 |
|
|
Preliminary version of assembler/linker/loader finished.
|
50 |
|
|
|
51 |
|
|
25-Nov-2002
|
52 |
|
|
Bootstrap monitor ROM translated to ECO32.
|
53 |
|
|
Simulator is running.
|
54 |
|
|
Bootstrap sector on disk created.
|
55 |
|
|
Now it is possible to boot from the disk.
|
56 |
|
|
|
57 |
|
|
26-Nov-2002
|
58 |
|
|
Work on an ECO32 back-end for the C compiler started.
|
59 |
|
|
|
60 |
|
|
27-Nov-2002
|
61 |
|
|
Preliminary version of back-end done.
|
62 |
|
|
|
63 |
|
|
28-Nov-2002
|
64 |
|
|
'Load address' instruction invented as macro for a set
|
65 |
|
|
of short sequences of instructions which are difficult
|
66 |
|
|
to generate by the back-end.
|
67 |
|
|
|
68 |
|
|
29-Nov-2002
|
69 |
|
|
Startup code (c0.s, c1.s) revised.
|
70 |
|
|
Writing the bootstrap sector revised.
|
71 |
|
|
System ROMs revised.
|
72 |
|
|
Tests revised.
|
73 |
|
|
|
74 |
|
|
30-Nov-2002
|
75 |
|
|
Started to program the MMU.
|
76 |
|
|
Surprise: we don't need an MMU enable bit! The unit can be
|
77 |
|
|
switched on all the time, but we have to be careful not to
|
78 |
|
|
use the TLB before it is properly initialized.
|
79 |
|
|
|
80 |
|
|
01-Dec-2002
|
81 |
|
|
Interrupt system re-designed.
|
82 |
|
|
Added the last missing case in the 'lda' implementation.
|
83 |
|
|
Timer interrupt is working properly.
|
84 |
|
|
We now have a new instruction: 'nor'. With this it is easy
|
85 |
|
|
to implement the bitwise complement of an integer. Done.
|
86 |
|
|
The compiler option -Wo-kernel compiles a program so that
|
87 |
|
|
it can be run in kernel mode.
|
88 |
|
|
This is a big step forward: hello.c is running (in kernel
|
89 |
|
|
mode of course).
|
90 |
|
|
|
91 |
|
|
02-Dec-2002
|
92 |
|
|
The characteristic feature of kernel mode programs as well as
|
93 |
|
|
of the kernel itself is that they want to handle all sorts of
|
94 |
|
|
special conditions for themselves (e.g., interrupts, exceptions,
|
95 |
|
|
startup code). So if the flag -Wo-kernel is given, the startup
|
96 |
|
|
library code (c0.s and c1.s) is no longer linked in automatically.
|
97 |
|
|
|
98 |
|
|
03-Dec-2002
|
99 |
|
|
The assembler now contains a complete expression parser which can
|
100 |
|
|
handle additive, multiplicative and shift expressions as well as
|
101 |
|
|
unary and parenthesized expressions.
|
102 |
|
|
Error in back-end corrected: mul & div instructions did not
|
103 |
|
|
correctly specify the second source register.
|
104 |
|
|
|
105 |
|
|
04-Dec-2002
|
106 |
|
|
The low-level code generators in the assembler had completely to
|
107 |
|
|
be redone: they could not handle big constants (immediate values
|
108 |
|
|
and addresses) in instructions that allow only 16 bit constants.
|
109 |
|
|
|
110 |
|
|
05-Dec-2002
|
111 |
|
|
I now have a pair of functions which allow to get/set an
|
112 |
|
|
interrupt service routine in the interrupt service routine
|
113 |
|
|
table. The low-level register save/restore is handled in
|
114 |
|
|
assembler, but the interrupt service routine itself can be
|
115 |
|
|
written in C. An application of this principle shows how to
|
116 |
|
|
determine the total amount of physical memory by probing
|
117 |
|
|
the memory until a bus timeout exception occurs. This can
|
118 |
|
|
fully be formulated in C.
|
119 |
|
|
The back-end generates a 'jal' instruction even when the
|
120 |
|
|
argument is a register. Although it would perhaps be more
|
121 |
|
|
appropriate to generate a 'jalr' instruction, I changed the
|
122 |
|
|
assembler to accept an address as well as a register with
|
123 |
|
|
this instruction.
|
124 |
|
|
|
125 |
|
|
06-Dec-2002
|
126 |
|
|
TLB flush is the first instruction dealing with the TLB.
|
127 |
|
|
Implemented.
|
128 |
|
|
|
129 |
|
|
07-Dec-2002
|
130 |
|
|
Until now we only had one special processor register, the
|
131 |
|
|
processor status word. With the MMU present, this will change.
|
132 |
|
|
Renamed 'gpsw' (get processor status word) to 'mvfs' (move
|
133 |
|
|
from special register). Renamed 'ppsw' (put processor status
|
134 |
|
|
word) to 'mvts' (move to special register). These instructions
|
135 |
|
|
have two arguments: a single register and a number specifying
|
136 |
|
|
the special register.
|
137 |
|
|
It is perhaps better to use an established set of instructions
|
138 |
|
|
dealing with the TLB (i.e., the way MIPS is doing this) instead
|
139 |
|
|
of an even more minimalistic one, which is not guaranteed to
|
140 |
|
|
cover all cases. So I will abandon 'TLB flush' in favor of the
|
141 |
|
|
four instructions found in the MIPS instruction set ('tbs',
|
142 |
|
|
'tbwr', 'tbri', and 'tbwi').
|
143 |
|
|
As is documented in the MIPS reference book, the valid bit V is
|
144 |
|
|
not involved in the TLB matching process. Implementation changed.
|
145 |
|
|
Perhaps we don't need the V bit at all? I'll leave it out for now.
|
146 |
|
|
|
147 |
|
|
08-Dec-2002
|
148 |
|
|
Today I came up with the idea to test the MMU implementation by
|
149 |
|
|
running a somewhat more realistic test: a task which is compiled
|
150 |
|
|
for virtual address 0 and has a minimal I/O library which traps
|
151 |
|
|
to the kernel to output a character.
|
152 |
|
|
|
153 |
|
|
09-Dec-2002
|
154 |
|
|
It is not necessary to prepare real page tables for the task, as I
|
155 |
|
|
thought initially. Since we have only one task which uses exactly
|
156 |
|
|
two pages (code and stack), it is possible to preset the TLB with
|
157 |
|
|
two entries for the pages and then leave it alone.
|
158 |
|
|
The test is running.
|
159 |
|
|
|
160 |
|
|
10-Dec-2002
|
161 |
|
|
Now for the next step: two tasks running concurrently, preempted
|
162 |
|
|
by a timer interrupt. This is really a lot more complicated than
|
163 |
|
|
a single task because now the entries in the TLB must be flushed
|
164 |
|
|
and re-programmed when a task switch occurs.
|
165 |
|
|
Another complication is the need for two kernel-mode stacks, one
|
166 |
|
|
for each task, in addition to the task-specific user-mode stacks.
|
167 |
|
|
This is necessary because of two facts:
|
168 |
|
|
- the kernel cannot rely on the integrity of the user-mode stacks
|
169 |
|
|
- the state of the suspended task must be preserved somewhere,
|
170 |
|
|
even if the other task is running and trapping to the kernel
|
171 |
|
|
for a system call.
|
172 |
|
|
|
173 |
|
|
11-Dec-2002
|
174 |
|
|
This was indeed much harder than expected, but now it works.
|
175 |
|
|
|
176 |
|
|
12-Dec-2002
|
177 |
|
|
It is evident that only a very short sequence of instructions is
|
178 |
|
|
able to handle a TLB miss exception efficiently. MIPS is doing
|
179 |
|
|
this by giving the TLB miss exception a separate interrupt vector.
|
180 |
|
|
We don't want to go so far, but of course we cannot tolerate to
|
181 |
|
|
execute all the lengthy actions at the beginning of the standard
|
182 |
|
|
trap handler. So we will sort out the TLB miss exception at the
|
183 |
|
|
very beginning of the standard exception handling.
|
184 |
|
|
|
185 |
|
|
13-Dec-2002
|
186 |
|
|
It is easy to catch the TLB miss - but how should it be handled?
|
187 |
|
|
Some sort of page table has to supply the necessary information
|
188 |
|
|
so that a new entry can be filled into the TLB. How should the
|
189 |
|
|
page tables be organized? In the past I saw cascaded page tables
|
190 |
|
|
as the only solution. But it might be better to have a single
|
191 |
|
|
page table which itself is paged and lies in virtual memory.
|
192 |
|
|
The big advantages of this scheme are fast access (no pointers
|
193 |
|
|
to chase) and (almost) no waste of memory because gaps in the
|
194 |
|
|
table do not need any real memory. But then of course we have
|
195 |
|
|
to handle TLB misses while accessing the page table...
|
196 |
|
|
Very confusing!
|
197 |
|
|
|
198 |
|
|
14-Dec-2002
|
199 |
|
|
What information is needed in which format if a TLB miss (or any
|
200 |
|
|
other TLB exception) occurs? I really have no stringent answer to
|
201 |
|
|
this question, so I will follow again a minimalistic design path:
|
202 |
|
|
Implement a register in the MMU which is set to the offending
|
203 |
|
|
virtual address in case the translation didn't work. Done.
|
204 |
|
|
As I realize now, this hardware equipment can support a variety of
|
205 |
|
|
different organizations of the page tables handled by software.
|
206 |
|
|
Even inverted page tables seem feasible!
|
207 |
|
|
It would be very convenient if the kernel could use another
|
208 |
|
|
register without having to save its contents first. I think
|
209 |
|
|
we could let the kernel have also register 28 at its disposal.
|
210 |
|
|
|
211 |
|
|
17-Dec-2002
|
212 |
|
|
Yesterday I realized that the 'lda' macro instruction is no longer
|
213 |
|
|
needed because 'add' does the very same job. Deleted.
|
214 |
|
|
|
215 |
|
|
18-Dec-2002
|
216 |
|
|
It is very desirable to have an interrupt mask in the PSW.
|
217 |
|
|
If, e.g., the timer interrupts and the timer ISR decides to
|
218 |
|
|
disable interrupts from all devices but the timer itself,
|
219 |
|
|
then this is not easily achievable without a central mask.
|
220 |
|
|
|
221 |
|
|
19-Dec-2002
|
222 |
|
|
One's complement, represented by '~', is another operator
|
223 |
|
|
implemented in the assembler.
|
224 |
|
|
|
225 |
|
|
20-Dec-2002
|
226 |
|
|
As well as bitwise and, bitwise xor, and bitwise or,
|
227 |
|
|
represented by '&', '^', and '|', respectively. These
|
228 |
|
|
operators are left associative and have the same priority
|
229 |
|
|
as they have in C, i.e., & > ^ > |, in order of decreasing
|
230 |
|
|
priority.
|
231 |
|
|
|
232 |
|
|
21-Dec-2002
|
233 |
|
|
Because of the new structure of the PSW all tests must be
|
234 |
|
|
updated and carried out once more. A lot of work...
|
235 |
|
|
|
236 |
|
|
22-Dec-2002
|
237 |
|
|
I spotted a minor bug in the simulator: a breakpoint which
|
238 |
|
|
was set to address C0000004 in order to catch any interrupt
|
239 |
|
|
or exception will not work for exceptions. This is due to
|
240 |
|
|
the handling of exceptions by setjmp/longjmp. Corrected.
|
241 |
|
|
|
242 |
|
|
23-Dec-2002
|
243 |
|
|
ECO32 Version 0.0 released.
|
244 |
|
|
|
245 |
|
|
26-Dec-2002
|
246 |
|
|
Today I started to convert the original sources of
|
247 |
|
|
UNIX 7th Edition to ANSI C.
|
248 |
|
|
|
249 |
|
|
29-Dec-2002
|
250 |
|
|
I found a real programming error in the text.c module:
|
251 |
|
|
if (ip->i_flag&ITEXT==0) return;
|
252 |
|
|
My compiler warned: 'expression with no effect elided'.
|
253 |
|
|
'==' has higher precedence than '&', but ITEXT does not
|
254 |
|
|
equal zero, so the whole test expression becomes zero
|
255 |
|
|
and the return is never executed. The line should read:
|
256 |
|
|
if ((ip->i_flag&ITEXT)==0) return;
|
257 |
|
|
|
258 |
|
|
31-Dec-2002
|
259 |
|
|
The masters made a typoe: in the file kl.c, the function
|
260 |
|
|
named 'ttioccomm' is spelled 'ttioccom'. I think this
|
261 |
|
|
did go undetected because of the very restricted length
|
262 |
|
|
of symbols with external linkage.
|
263 |
|
|
|
264 |
|
|
01-Jan-2003
|
265 |
|
|
Today I began investigating the startup procedure. I will
|
266 |
|
|
place the per-process kernel stack in the top half of the
|
267 |
|
|
u area, which itself is one page in size and is located
|
268 |
|
|
directly underneath the kernel at 0xC0000000 - 0x1000.
|
269 |
|
|
This part of the virtual address space is mapped and so
|
270 |
|
|
the u area of the running process is always accessible.
|
271 |
|
|
|
272 |
|
|
02-Jan-2003
|
273 |
|
|
How do we do the memory management? This is THE central
|
274 |
|
|
question of our porting effort. One possibility which
|
275 |
|
|
offers the chance of only minor changes to the existing
|
276 |
|
|
sources would be to keep the management by the coremap
|
277 |
|
|
array, but with the granularity changed to 4 k, the page
|
278 |
|
|
size. This route of course would not barely touch the
|
279 |
|
|
power of demand paging, which is possible by our hardware.
|
280 |
|
|
Nevertheless, I will follow this path for the time being.
|
281 |
|
|
I changed the coremap/swapmap entries into structs of two
|
282 |
|
|
integers instead of two shorts. Otherwise the range of
|
283 |
|
|
addresses might get too small (although this is unlikely:
|
284 |
|
|
64 k pages of 4 k bytes each equals 256 M bytes - quite a
|
285 |
|
|
lot of memory).
|
286 |
|
|
|
287 |
|
|
04-Jan-2003
|
288 |
|
|
This last change is nonsense - much of the other stored
|
289 |
|
|
information about processes would have to be changed also.
|
290 |
|
|
Reverted.
|
291 |
|
|
Because ECO32 does not have two different stack pointers
|
292 |
|
|
(as the PDP-11 has) we must switch to the kernel stack
|
293 |
|
|
explicitly. But we must not do the switch if the interrupt
|
294 |
|
|
hit while the machine was running in kernel mode already -
|
295 |
|
|
then the sp points deep into a properly setup kernel stack.
|
296 |
|
|
Switching stacks would then destroy the stack completely.
|
297 |
|
|
|
298 |
|
|
11-Jan-2003
|
299 |
|
|
I discovered a mysterious overwriting of some bytes of
|
300 |
|
|
the loaded UNIX kernel. This took place even before any
|
301 |
|
|
of its code was executed! A little bit of searching, and
|
302 |
|
|
the guilty one was found: the bootmon ROM code and its
|
303 |
|
|
stack. Now there is a problem: where should we put the
|
304 |
|
|
stack of the bootmon ROM?
|
305 |
|
|
We have two ways to get some program into the bare machine:
|
306 |
|
|
a) The 'realistic hardware' scenario: a ROM holds an initial
|
307 |
|
|
program which e.g. may boot the operating system from disk.
|
308 |
|
|
b) The 'convenient debugging scenario': the program, e.g. the
|
309 |
|
|
operating system, is somewhat magically loaded into RAM.
|
310 |
|
|
The error described above is caused by the unwanted interaction
|
311 |
|
|
of a) and b) when used together. So I think that the correct
|
312 |
|
|
solution of the problem is to forbid the specification of both
|
313 |
|
|
simulator options -r and -l at the same time.
|
314 |
|
|
|
315 |
|
|
13-Jan-2003
|
316 |
|
|
The simulator uses all CPU power which is available, even
|
317 |
|
|
when only waiting for a command line. This can easily be
|
318 |
|
|
changed by inserting a usleep(100) call into the input
|
319 |
|
|
waiting loop of the curses interface. Done.
|
320 |
|
|
Two new pseudo-ops (.syn and .nosyn) added to the assembler.
|
321 |
|
|
They allow or disallow synthesizing instructions with 'big'
|
322 |
|
|
constants, respectively. This can be used e.g. in the TLB miss
|
323 |
|
|
handler, where much finer control over the usage of register
|
324 |
|
|
$1 is needed.
|
325 |
|
|
|
326 |
|
|
15-Jan-2003
|
327 |
|
|
The constant BSLOP in param.h must be set to 0. Otherwise there
|
328 |
|
|
would exist blocks which don't start at an address which is a
|
329 |
|
|
multiple of 4. This would result in a Bus Address Error if e.g.
|
330 |
|
|
an integer is fetched from the block.
|
331 |
|
|
|
332 |
|
|
16-Jan-2003
|
333 |
|
|
The type mapping from C to machine types is as follows:
|
334 |
|
|
PDP-11 ECO32
|
335 |
|
|
char byte (1 byte) byte (1 byte)
|
336 |
|
|
short word (2 bytes) half (2 bytes)
|
337 |
|
|
int word (2 bytes) word (4 bytes)
|
338 |
|
|
long double word (4 bytes) word (4 bytes)
|
339 |
|
|
T * word (2 bytes) word (4 bytes)
|
340 |
|
|
As can be seen, only ints and pointers are differently mapped.
|
341 |
|
|
This is of not much concern with in-memory data structures but
|
342 |
|
|
can be desastrous with on-disk data structures (super block,
|
343 |
|
|
inodes). Therefore we have to do the following:
|
344 |
|
|
a) define ino_t as unsigned short
|
345 |
|
|
b) rearrange the components in struct filsys (and in principle in
|
346 |
|
|
struct dinode and struct direct too) so that no padding occurs.
|
347 |
|
|
I thought that I could simply write a disk with the PDP-11 simulator
|
348 |
|
|
and then use it with the ECO32 simulator; this is not possible
|
349 |
|
|
due to different endianness.
|
350 |
|
|
|
351 |
|
|
17-Jan-2003
|
352 |
|
|
Here are the changes I actually made:
|
353 |
|
|
1) in param.h:
|
354 |
|
|
a) type 'ino_t' is 'unsigned short' instead of 'unsigned int'
|
355 |
|
|
b) type 'dev_t' is 'short' instead of 'int'
|
356 |
|
|
2) in filsys.h:
|
357 |
|
|
a) delete all components of struct filsys below the comment
|
358 |
|
|
'remainder not maintained by this version of the system'
|
359 |
|
|
b) 's_isize' is of type 'daddr_t', not of type 'unsigned short'
|
360 |
|
|
c) 's_nfree' is of type 'int', not of type 'short'
|
361 |
|
|
d) 's_ninode' is of type 'int', not of type 'short'
|
362 |
|
|
e) exchange components 's_isize' and 's_fsize'
|
363 |
|
|
3) in inode.h:
|
364 |
|
|
a) 'i_flag' is of type 'short', not of type 'char'
|
365 |
|
|
b) 'i_count' is of type 'short', not of type 'char'
|
366 |
|
|
The size of the superblock structure is thus increased by 6 bytes
|
367 |
|
|
to 424 bytes (well below the 512 bytes block boundary), and all
|
368 |
|
|
padding or misalignment is avoided.
|
369 |
|
|
|
370 |
|
|
18-Jan-2003
|
371 |
|
|
I replaced the "Hello, world!" message in the default master boot
|
372 |
|
|
record by a somewhat more appropriate message.
|
373 |
|
|
|
374 |
|
|
19-Jan-2003
|
375 |
|
|
In order to simplify things a bit, I removed the '-n' option from
|
376 |
|
|
the assembler. Now assembler output files always do have headers.
|
377 |
|
|
There are of course situations in which the header must be stripped
|
378 |
|
|
off, e.g. with the boot record, or with the ROM in the simulator.
|
379 |
|
|
We have therefore now a 'loader', a little program which converts
|
380 |
|
|
an assembler output file into a memory image without any header.
|
381 |
|
|
This has the additional benefit that the simulator does no longer
|
382 |
|
|
need to know the executable format, which is especially good if we
|
383 |
|
|
change the format or add new formats.
|
384 |
|
|
|
385 |
|
|
20-Jan-2003
|
386 |
|
|
Started to port the 'mkfs' utility.
|
387 |
|
|
|
388 |
|
|
21-Jan-2003
|
389 |
|
|
Started to program a 'show file system' utility.
|
390 |
|
|
|
391 |
|
|
22-Jan-2003
|
392 |
|
|
Today I decided to spare a small number of TLB entries (4) from
|
393 |
|
|
random replacement. This helps to keep such vital information as
|
394 |
|
|
the current kernel stack permanently mapped.
|
395 |
|
|
|
396 |
|
|
25-Jan-2003
|
397 |
|
|
I changed the disk so that it is now similar to the 'rp' device
|
398 |
|
|
in the PDP-11. This has the advantage that the usr file system
|
399 |
|
|
is located on a different device (specifically: a different minor
|
400 |
|
|
device, i.e., a different partition) so that mounting can be tested.
|
401 |
|
|
The partitions and their intended use is as follows:
|
402 |
|
|
device size in blocks use as
|
403 |
|
|
-------------------------------------------
|
404 |
|
|
rp0 14000 whole disk
|
405 |
|
|
rp1 2000 root
|
406 |
|
|
rp2 4000 swap
|
407 |
|
|
rp3 8000 usr
|
408 |
|
|
|
409 |
|
|
28-Jan-2003
|
410 |
|
|
This was quite a lot of work, but finally 'mkfs' is running.
|
411 |
|
|
The crucial tool to achieve this was 'shfs' - show file system,
|
412 |
|
|
which allows displaying arbitrary blocks of a disk in several
|
413 |
|
|
formats (raw data, super block, inode block, directory block,
|
414 |
|
|
free list block, or indirect block). So everything on the disk
|
415 |
|
|
can be examined in detail.
|
416 |
|
|
By the way, the main hurdles to overcome had been different
|
417 |
|
|
endianness of ECO32 and x86, different padding of structures,
|
418 |
|
|
and alignment restrictions with ECO32, which are not present
|
419 |
|
|
on the x86 architecture.
|
420 |
|
|
|
421 |
|
|
29-Jan-2003
|
422 |
|
|
Here is a short report on byte-ordering on x86, ECO32, and PDP-11.
|
423 |
|
|
The C data type 'long' is stored in 4 bytes on all thre machines,
|
424 |
|
|
as already stated above (16-Jan-2003). The order of the bytes is
|
425 |
|
|
different on all three machines. We number the bytes from MSB
|
426 |
|
|
(most signigicant byte) to LSB (least significant byte): then
|
427 |
|
|
the number (b1 b2 b3 b4) has the value b1*2^24+b2*2^16+b3*2^8+b4.
|
428 |
|
|
If 'A' is the lowest (byte) address where the number is to be stored,
|
429 |
|
|
then the memory layout of the three architectures look like this:
|
430 |
|
|
x86 A+0:b4 A+1:b3 A+2:b2 A+3:b1 (i.e., little endian)
|
431 |
|
|
ECO32 A+0:b1 A+1:b2 A+2:b3 A+3:b4 (i.e., big endian)
|
432 |
|
|
PDP-11 A+0:b2 A+0:b1 A+0:b4 A+0:b3 (i.e., mixed)
|
433 |
|
|
An additional complication results from the fact that disk addresses
|
434 |
|
|
in inodes on a disk are stored in a three byte format, which is
|
435 |
|
|
different on ECO32 and PDP-11 (there is no such format on the x86,
|
436 |
|
|
because we don't want to run a file system on a bare PC, only within
|
437 |
|
|
the ECO32 simulator). In this format only the three least significant
|
438 |
|
|
bytes (b2 b3 b4) are stored; if b1 were non-zero an error would be
|
439 |
|
|
triggered. So then, here are the layouts of this special format:
|
440 |
|
|
ECO32 A+0:b2 A+1:b3 A+2:b4
|
441 |
|
|
PDP-11 A+0:b2 A+1:b4 A+2:b3
|
442 |
|
|
As can be seen, this format is constructed on both architectures by
|
443 |
|
|
omitting b1 (the MSB) from the four byte format.
|
444 |
|
|
I changed the routines that convert the three byte format from and to
|
445 |
|
|
the four byte format (iexpand() and iupdat(), both in module iget.c)
|
446 |
|
|
in order to cope with the changed byte-ordering.
|
447 |
|
|
Reduced the RAM size to 1M; this fits better to the disk swap size.
|
448 |
|
|
Added a counter to the simulator which counts the total number of
|
449 |
|
|
instructions executed since the last reset. This helps a lot if one
|
450 |
|
|
wants to re-visit a specific location in the program, if a lot of
|
451 |
|
|
single-stepping has been done to find the location for the first time.
|
452 |
|
|
|
453 |
|
|
31-Jan-2003
|
454 |
|
|
There has been an inconsistency with the object file format since
|
455 |
|
|
its invention: the header data is stored in little endian format,
|
456 |
|
|
which is convenient for the tools working in the cross development
|
457 |
|
|
setup. The tools running on the target architecture require the
|
458 |
|
|
data to be in ECO32 format of course. This is especially true for
|
459 |
|
|
the kernel exec file loader. Changed.
|
460 |
|
|
|
461 |
|
|
03-Feb-2003
|
462 |
|
|
ECO32 Version 0.1 released.
|
463 |
|
|
|
464 |
|
|
04-Feb-2003
|
465 |
|
|
Added to 'shfs' a command which translates an inode number into the
|
466 |
|
|
block number in which this inode is located, together with an inode
|
467 |
|
|
number relative to that block.
|
468 |
|
|
The simulator's 't' command now displays also the special registers
|
469 |
|
|
of the MMU (Index, EntryHi, EntryLo, BadAddress).
|
470 |
|
|
Memory commands of the simulator completed.
|
471 |
|
|
|
472 |
|
|
05-Feb-2003
|
473 |
|
|
ATTENTION: I changed the output of the disassembler to get it more
|
474 |
|
|
consistent with the rest of the simulator, and especially with its
|
475 |
|
|
inline assembler. There are no more '0x' prefixes in front of numbers,
|
476 |
|
|
and we don't have any decimal output. All numbers are given as hex
|
477 |
|
|
numbers without a prefix (the only exception to this rule are the
|
478 |
|
|
numbers of registers proper, of course, which are given in decimal).
|
479 |
|
|
The instructions which do sign extension show their arguments as
|
480 |
|
|
signed hex numbers. Labels are also no longer prefixed.
|
481 |
|
|
Inline assembler completed.
|
482 |
|
|
|
483 |
|
|
17-Feb-2003
|
484 |
|
|
ECO32 Version 0.2 released.
|
485 |
|
|
|
486 |
|
|
20-Aug-2003
|
487 |
|
|
ECO32 Version 0.3 released.
|
488 |
|
|
|
489 |
|
|
21-Aug-2003
|
490 |
|
|
1) I changed the 'ldhi' opcode from 0x1E to 0x1F.
|
491 |
|
|
Reason: The instruction decoding gets more regular.
|
492 |
|
|
2) The ALU has now an 'xnor' instruction instead of a 'nor':
|
493 |
|
|
(a xnor b) = ~(a ^ b) = (~a ^ b) = (a ^ ~b) = (a == b),
|
494 |
|
|
bitwise parallel for all 32 bits.
|
495 |
|
|
Reason: The ALU is easier to implement, and the instruction
|
496 |
|
|
set becomes more regular.
|
497 |
|
|
3) The PC relative jumps (j, jal, all conditional branches) now
|
498 |
|
|
have PC+4 as their reference location (and no longer PC).
|
499 |
|
|
Reason: PC+4 is computed early in the instruction cycle; all
|
500 |
|
|
other RISC machines do this alike.
|
501 |
|
|
4) The PC relative jumps (j, jal, all conditional branches) now
|
502 |
|
|
encode a word offset, and no longer a byte offset.
|
503 |
|
|
Reason: The target ranges for the jumps are quadrupled without
|
504 |
|
|
any additional effort.
|
505 |
|
|
|
506 |
|
|
07-Oct-2003
|
507 |
|
|
Explored the possibilities to implement a graphics controller for
|
508 |
|
|
ECO32. Easy from the simulator's point of view, not quite so easy
|
509 |
|
|
from the implementer's point of view (due to X complications,
|
510 |
|
|
threads needed) but certainly feasible.
|
511 |
|
|
|
512 |
|
|
13-Oct-2003
|
513 |
|
|
Graphics controller implemented.
|
514 |
|
|
|
515 |
|
|
20-Oct-2003
|
516 |
|
|
Curses feeds certain keypad codes directly into the simulator's
|
517 |
|
|
terminal, e.g. KEY_BACKSPACE. There the MSBs get stripped off and
|
518 |
|
|
a wrong keycode is supplied to the simulated program. Now these
|
519 |
|
|
special codes are mapped to regular control characters, e.g. BS.
|
520 |
|
|
|
521 |
|
|
25-Oct-2003
|
522 |
|
|
The assembler now understands the option '-h' which suppresses the
|
523 |
|
|
output of the executable's header and appends the BSS's size bytes
|
524 |
|
|
of zeroes at the end of the executable. This in turn renders the
|
525 |
|
|
'load' tool redundant, which can be deleted. Done.
|
526 |
|
|
|
527 |
|
|
26-Oct-2003
|
528 |
|
|
A group of students is working on a ROM-based monitor program. They
|
529 |
|
|
need an instruction to implement breakpoints. Because the instruction
|
530 |
|
|
map is already crowded they have to use 'trap'. But they want of
|
531 |
|
|
course a breakpoint trap be easily distinguishable from any other
|
532 |
|
|
kind of trap. So the assembler now allows a constant operand for
|
533 |
|
|
'trap'. This operand is assembled into the otherwise unused bits
|
534 |
|
|
of the instruction. These bits are in turn ignored by the CPU (as
|
535 |
|
|
was the case all the time) but can be inspected by software which
|
536 |
|
|
must read the instruction from memory in order to do this. Now a
|
537 |
|
|
breakpoint trap can get a unique bit pattern distinct from the bit
|
538 |
|
|
patterns of all other traps. Remark: not only the regular assembler
|
539 |
|
|
must understand this but also the simulator's inline assembler as
|
540 |
|
|
well as its disassembler. Done.
|
541 |
|
|
|
542 |
|
|
09-Nov-2003
|
543 |
|
|
The curses library correctly sets the terminal mode to "raw" so that
|
544 |
|
|
neither SIGINT nor SIGQUIT signals can be generated by the keyboard.
|
545 |
|
|
With a graphics controller attached it is however possible that the
|
546 |
|
|
user selects "kill" from the window menu of the monitor window and
|
547 |
|
|
thus shuts down the connection to the X server. This in turn leads
|
548 |
|
|
to an uncontrolled instant termination of the whole simulator which
|
549 |
|
|
cannot be tolerated (e.g. the terminal would stay in raw mode: very
|
550 |
|
|
annoying for an unsuspecting user). Solution: install an I/O error
|
551 |
|
|
handler which gets called from the X system in case the connection
|
552 |
|
|
to the server is lost. Done.
|
553 |
|
|
|
554 |
|
|
16-Nov-2003
|
555 |
|
|
I added a check to the initialization of the memory simulation ensuring
|
556 |
|
|
that neither ROM image files nor program files loaded into main memory
|
557 |
|
|
can overflow the available space (and thus crash the simulator).
|
558 |
|
|
|
559 |
|
|
18-Nov-2003
|
560 |
|
|
The terminal simulation now handles the following control characters:
|
561 |
|
|
(input) 0x0D
|
562 |
|
|
0x08
|
563 |
|
|
0x0E
|
564 |
|
|
0x10
|
565 |
|
|
0x02
|
566 |
|
|
0x06
|
567 |
|
|
(output) 0x07 beep
|
568 |
|
|
0x0D return cursor to begin of current line
|
569 |
|
|
0x0A scroll if cursor is in last line,
|
570 |
|
|
set cursor to next line in same column
|
571 |
|
|
0x02 move cursor left (stop at leftmost column)
|
572 |
|
|
0x06 move cursor right (stop at rightmost column)
|
573 |
|
|
0x10 move cursor up (stop at topmost line)
|
574 |
|
|
0x0E move cursor down (stop at bottom line)
|
575 |
|
|
0x08 delete character to the left of cursor,
|
576 |
|
|
move cursor left
|
577 |
|
|
0x09 output spaces (minimum is one space),
|
578 |
|
|
until column mod 8 = 0
|
579 |
|
|
|
580 |
|
|
19-Nov-2003
|
581 |
|
|
Today I took the first few steps towards a bootable system disk.
|
582 |
|
|
Changes in bootstrap monitor:
|
583 |
|
|
- 'g' command deleted
|
584 |
|
|
- monitor stack sits just below 1M
|
585 |
|
|
- master boot record loaded at physical address 0x00000000
|
586 |
|
|
- master boot record started at virtual address 0xC0000000
|
587 |
|
|
Changes in constructing the default master boot record:
|
588 |
|
|
- relocate code to 0xC0000000
|
589 |
|
|
|
590 |
|
|
20-Nov-2003
|
591 |
|
|
Now here is the big picture of the boot process:
|
592 |
|
|
a) ROM bootstrap
|
593 |
|
|
The ROM loads the first sector of the disk and starts whatever it
|
594 |
|
|
has loaded (provided that the signature is present). Until now this
|
595 |
|
|
was always the default master boot record. In the future this will
|
596 |
|
|
be the first stage bootstrap. This part is already finished.
|
597 |
|
|
b) First stage bootstrap
|
598 |
|
|
The first stage looks for a file named "boot" in the root directory
|
599 |
|
|
of the file system on the boot disk. This part must fit into a single
|
600 |
|
|
sector and thus is restricted in its capabilities:
|
601 |
|
|
- boot must lie in the root directoy
|
602 |
|
|
- it must be one of the first 320 directory entries in the root
|
603 |
|
|
directory (only the 10 direct blocks of the directory file are
|
604 |
|
|
searched for it)
|
605 |
|
|
- it must not be bigger than 5120 Bytes (only the 10 direct blocks
|
606 |
|
|
of the executable file are loaded)
|
607 |
|
|
c) Second stage bootstrap
|
608 |
|
|
This stage loads the kernel, perhaps asking the user for its name.
|
609 |
|
|
|
610 |
|
|
22-Nov-2003
|
611 |
|
|
First stage bootstrap completed.
|
612 |
|
|
|
613 |
|
|
27-Nov-2003
|
614 |
|
|
Second stage bootstrap completed.
|
615 |
|
|
It was indeed possible to ask the user for the path to the kernel he
|
616 |
|
|
wants to get started. The only kernel available for now is one of the
|
617 |
|
|
tests from tst/os.
|
618 |
|
|
|
619 |
|
|
29-Nov-2003
|
620 |
|
|
Makefiles tweaked.
|
621 |
|
|
|
622 |
|
|
06-Dec-2003
|
623 |
|
|
Today I started to develop the tools shfs and mkfs for file systems
|
624 |
|
|
with 4K blocksize. With this blocksize it should be possible to do
|
625 |
|
|
the bootstrap without a named second stage. Conceptually there are
|
626 |
|
|
again two stages (first load a single sector, then the rest), but
|
627 |
|
|
both stages should fit within the boot block.
|
628 |
|
|
|
629 |
|
|
20-Dec-2003
|
630 |
|
|
I discovered a small bug (?) in the simulator: if a write to $0 is
|
631 |
|
|
requested by an instruction, not only the write is suppressed (this
|
632 |
|
|
is expected) but also the source operand does not get computed.
|
633 |
|
|
Thus the instruction ldw $0,$0,1 which is incorrect if no TLB entry
|
634 |
|
|
for page 0 exists (and is so even if it exists because of alignment
|
635 |
|
|
violation) does not lead to an exception (which is quite unexpected).
|
636 |
|
|
Solution: Always compute the source operands, even if $0 is the target.
|
637 |
|
|
|
638 |
|
|
30-Dec-2003
|
639 |
|
|
In order to use swap space on the same disk where the root file system
|
640 |
|
|
is located we need some form of disk partitioning, preferrably NOT
|
641 |
|
|
deeply coded into the disk driver (as the original UNIX has done it).
|
642 |
|
|
In other words, we need a real master boot record, a partition table
|
643 |
|
|
and a tool ("fdisk" or "mkpart") to set up such a table.
|
644 |
|
|
|
645 |
|
|
01-Jan-2004
|
646 |
|
|
"mkpart" finished. It constructs a partition table from a textual
|
647 |
|
|
configuration file and writes it to sector 1. It also copies an MBR
|
648 |
|
|
(which has not been done yet) to sector 0, and a bootstrap manager
|
649 |
|
|
(which also has yet to be done) to sectors 2-7.
|
650 |
|
|
MBR coded.
|
651 |
|
|
|
652 |
|
|
02-Jan-2004
|
653 |
|
|
Bootstrap manager done.
|
654 |
|
|
|
655 |
|
|
03-Jan-2004
|
656 |
|
|
Tool "mkpart" is working.
|
657 |
|
|
New tool "shpart" displays a partition table, read from a disk image.
|
658 |
|
|
|
659 |
|
|
04-Jan-2004
|
660 |
|
|
I made the file systen viewer aware of partitions.
|
661 |
|
|
|
662 |
|
|
05-Jan-2004
|
663 |
|
|
Now "mkfs" also knows something about partitions.
|
664 |
|
|
|
665 |
|
|
08-Jan-2004
|
666 |
|
|
If the operating system is booted from a partition of a disk (in
|
667 |
|
|
contrast to being booted from the start of the whole disk) its disk
|
668 |
|
|
driver must know where logical sector 0 of the partition is located
|
669 |
|
|
on the disk. In other words, the master bootstrap must transfer a
|
670 |
|
|
little bit of information to the boot loader of the OS. This could
|
671 |
|
|
be done as follows: $26 holds the start sector of the partition from
|
672 |
|
|
where the OS is booted and $27 holds its size. In order to use the
|
673 |
|
|
very same bootstrap also in the case that the disk has no partitions
|
674 |
|
|
(and thus the file system occupies the whole disk), this information
|
675 |
|
|
must also be supplied by the ROM bootstrap sequence. Done.
|
676 |
|
|
Surprise: this scheme would allow the sub-partitioning of a partition
|
677 |
|
|
without any modification!
|
678 |
|
|
|
679 |
|
|
10-Jan-2004
|
680 |
|
|
Now the whole bootstrap chain is working. It goes like this:
|
681 |
|
|
a) The ROM loads the first sector of the disk and starts whatever it
|
682 |
|
|
has loaded (provided that the 0x55AA signature is present). This
|
683 |
|
|
may be either the master boot record if the disk is partitioned,
|
684 |
|
|
or an ordinary boot record if it is not (see remark below).
|
685 |
|
|
b) In case the master boot record is executing, it loads sectors 2..7
|
686 |
|
|
into memory (sector 1, the second sector of the disk, is skipped
|
687 |
|
|
because it holds the partition table). These sectors contain a small
|
688 |
|
|
program, the boot manager, in executable format. The boot manager is
|
689 |
|
|
started by the master boot record.
|
690 |
|
|
c) The boot manager loads the partition table from sector 1 of the disk,
|
691 |
|
|
displays the partitions of the disk, and asks the user to enter a
|
692 |
|
|
partition number to boot. An attempt to boot a partition outside the
|
693 |
|
|
range 0..15 is rejected, as well as requesting to boot a partition
|
694 |
|
|
which does not contain a file system of any kind, or does not have
|
695 |
|
|
the "bootable" flag set. If all is well, the boot record of the
|
696 |
|
|
selected partition is loaded. If it has a valid 0x55AA signature,
|
697 |
|
|
it is started.
|
698 |
|
|
Remark: This is the point in the bootstrap chain which is reached
|
699 |
|
|
immediately from the ROM code if the disk is not partitioned.
|
700 |
|
|
d) The boot record code loads partition relative sectors 1..7, i.e.
|
701 |
|
|
the rest of the boot block. These sectors contain a small program,
|
702 |
|
|
the bootstrap loader, in executable format. The bootstrap loader is
|
703 |
|
|
started by the boot record code.
|
704 |
|
|
e) The bootstrap loader asks the user for a path to a file which must
|
705 |
|
|
exist, must be a regular file, and must be executable by its owner.
|
706 |
|
|
This will of course be normally an operating system kernel. The
|
707 |
|
|
default value is /boot/unix. The file is loaded and started.
|
708 |
|
|
Throughout the whole process registers $26 and $27 hold the start sector
|
709 |
|
|
and size of the currently selected range of the disk, respectively.
|
710 |
|
|
|
711 |
|
|
12-Jan-2004
|
712 |
|
|
The register conventions shown above must be changed somewhat because
|
713 |
|
|
with more than one disk present it is also necessary to tell the disk
|
714 |
|
|
driver which disk to use:
|
715 |
|
|
$26 base address of disk controller
|
716 |
|
|
$27 start sector of partition (or disk)
|
717 |
|
|
$28 size of partition (or disk) in sectors
|
718 |
|
|
|
719 |
|
|
28-Jan-2004
|
720 |
|
|
After rewriting parts of the make file system utility (so that double
|
721 |
|
|
indirect blocks can be used, which is necessary for a file system with
|
722 |
|
|
512 byte blocks to hold files of more than 69K) it is now possible to
|
723 |
|
|
boot our port of UNIX 7th Edition from the disk. Alas, it is not yet
|
724 |
|
|
running very stable.
|
725 |
|
|
|
726 |
|
|
10-Mar-2004
|
727 |
|
|
Finally I added the generation of copying loops to the compiler's
|
728 |
|
|
back-end. This has long been missing.
|
729 |
|
|
|
730 |
|
|
17-Apr-2004
|
731 |
|
|
Translating virtual addresses using the TLB costs time because the
|
732 |
|
|
parallel associative hardware must be simulated by serial software.
|
733 |
|
|
This is very noticeable with programs running in user mode; they run
|
734 |
|
|
at roughly one third of the speed kernel mode programs do. In order
|
735 |
|
|
to alleviate this I added a function which acts almost the same as
|
736 |
|
|
the TLB associative lookup does, but without any error checks. Its
|
737 |
|
|
sole pupose is to use up time and it is called whenever an unmapped
|
738 |
|
|
address is detected by the virtual-to-physical address translation.
|
739 |
|
|
|
740 |
|
|
21-Apr-2004
|
741 |
|
|
Up till now the assembler located the data segment directly above
|
742 |
|
|
the code segment. This is not a viable strategy once paging is in
|
743 |
|
|
effect. Due to code sharing and protection reasons, the data segment
|
744 |
|
|
should start on the next page boundary above the code. The resulting
|
745 |
|
|
gap may also be present in the executable file: there is no need to
|
746 |
|
|
store any bytes for it in the executable (at least as long as it is
|
747 |
|
|
an executable with a header - for headerless executables the gap
|
748 |
|
|
bytes must be stored within the file).
|
749 |
|
|
It would have been possible to define two different executable formats,
|
750 |
|
|
one with the data segment directly following the code segment, and
|
751 |
|
|
another one with the data segment aligned on a page boundary. The
|
752 |
|
|
two formats then would have to be distinguished by different magic
|
753 |
|
|
numbers in the header. I did not do this, however, because I saw
|
754 |
|
|
no reason to keep the "directly following" format. If one wants to
|
755 |
|
|
compress code and data as much as possible, one can in any case put
|
756 |
|
|
both into the code segment.
|
757 |
|
|
|
758 |
|
|
24-Apr-2004
|
759 |
|
|
The simulated graphics device did not detect memory accesses which
|
760 |
|
|
lie within the device address bounds but outside the screen memory.
|
761 |
|
|
These accesses were propagated to the X Window System and in turn an
|
762 |
|
|
X Window data structure was accessed outside of its allocated memory.
|
763 |
|
|
At least on our Sun computer this translated to an immediate death
|
764 |
|
|
of the simulator process. Now the graphics device detects such an
|
765 |
|
|
attempt to access simulated memory outside the screen, and produces
|
766 |
|
|
a 'bus timeout' exception.
|
767 |
|
|
|
768 |
|
|
06-May-2004
|
769 |
|
|
ECO32 Version 0.4 released.
|
770 |
|
|
|
771 |
|
|
08-May-2004
|
772 |
|
|
I intend to give the ECO32 simulator the ability to run with more than
|
773 |
|
|
one simulated terminal. This will work best if there is no difference
|
774 |
|
|
between the first terminal and the other ones, so I will open a separate
|
775 |
|
|
window for each terminal (and use the first window in which the simulator
|
776 |
|
|
was started only for controlling the simulator, and NOT for a simulated
|
777 |
|
|
terminal). Then using curses is no longer necessary and can be removed.
|
778 |
|
|
But I want to retain command line editing, so I will use the 'getline'
|
779 |
|
|
library.
|
780 |
|
|
Curses interface removed.
|
781 |
|
|
Getline library installed.
|
782 |
|
|
Interrupt priorities changed:
|
783 |
|
|
15 not used
|
784 |
|
|
14 timer
|
785 |
|
|
13 not used
|
786 |
|
|
12 not used
|
787 |
|
|
11 not used
|
788 |
|
|
10 not used
|
789 |
|
|
09 not used
|
790 |
|
|
08 disk
|
791 |
|
|
07 terminal 3 receiver
|
792 |
|
|
06 terminal 3 transmitter
|
793 |
|
|
05 terminal 2 receiver
|
794 |
|
|
04 terminal 2 transmitter
|
795 |
|
|
03 terminal 1 receiver
|
796 |
|
|
02 terminal 1 transmitter
|
797 |
|
|
01 terminal 0 receiver
|
798 |
|
|
00 terminal 0 transmitter
|
799 |
|
|
|
800 |
|
|
10-May-2004
|
801 |
|
|
SIGINT handler installed (for use within the control window to regain
|
802 |
|
|
control in case of a runaway program).
|
803 |
|
|
In order to use a single timer callback routine for all terminals, the
|
804 |
|
|
callback routine must get an argument, telling which terminal is doing
|
805 |
|
|
the callback. So ALL timer callbacks now have such an argument, which
|
806 |
|
|
can be used arbitrarily by the callback initiator to communicate an
|
807 |
|
|
integer to the callback routine.
|
808 |
|
|
|
809 |
|
|
17-May-2004
|
810 |
|
|
The new terminal implementation must be tested as well as the changed
|
811 |
|
|
interrupt priority scheme. And even more important: allocation of the
|
812 |
|
|
data segment on a page boundary (see 21-Apr-2004) must be verified!
|
813 |
|
|
Done for the 'tst' directory.
|
814 |
|
|
|
815 |
|
|
18-May-2004
|
816 |
|
|
Done for the 'eos' directory.
|
817 |
|
|
|
818 |
|
|
27-Feb-2005
|
819 |
|
|
ECO32 Version 0.5 released.
|
820 |
|
|
|
821 |
|
|
28-Feb-2005
|
822 |
|
|
Despite the long time since the release of the previous version this
|
823 |
|
|
was very premature: I did not read the comments above and forgot to
|
824 |
|
|
conduct many of the tests. And indeed, the bootstrap does not work
|
825 |
|
|
any longer.
|
826 |
|
|
|
827 |
|
|
01-Mar-2005
|
828 |
|
|
The bootstrap manager should not be compiled to any standard executable
|
829 |
|
|
format, because this part of the boot process is independent of any
|
830 |
|
|
operating system. It should be compiled to plain binary format, as is
|
831 |
|
|
the master boot record. Now we are facing a dilemma: We want to write
|
832 |
|
|
the boot manager (mostly) in C and therefore will have a separate data
|
833 |
|
|
segment, aligned on a page boundary. But we also want a headerless
|
834 |
|
|
binary output, so there will be no loading information. All gaps in
|
835 |
|
|
the loaded program and data will therefore be filled with zeroes.
|
836 |
|
|
Then either we must define another executable format in which the data
|
837 |
|
|
segment follows directly after the code segment (without padding to the
|
838 |
|
|
next page boundary, see discussion above) or we have to spend somewhat
|
839 |
|
|
more space on disk for the bootstrap managers's program/data image.
|
840 |
|
|
I think I will do the latter.
|
841 |
|
|
|
842 |
|
|
04-Mar-2005
|
843 |
|
|
The solution above is not very elegant: The same reasoning applies also
|
844 |
|
|
to the bootstrap within a partition. Then we are forced to reserve two
|
845 |
|
|
blocks instead of the traditional single one for the bootstrap. This is
|
846 |
|
|
not totally out of question, but not very appealing either.
|
847 |
|
|
There is another solution, if we accept the boot manager to be compiled
|
848 |
|
|
to standard executable format: write a very compact loader for this format
|
849 |
|
|
and squeeze it into the master boot record. Difficult, but it can be
|
850 |
|
|
done, as I proved today.
|
851 |
|
|
Changes from above reverted.
|
852 |
|
|
Disk partitioning, master boot record, and boot manager done.
|
853 |
|
|
|
854 |
|
|
05-Mar-2005
|
855 |
|
|
Boot record and bootstrap loader done.
|
856 |
|
|
|
857 |
|
|
08-Mar-2005
|
858 |
|
|
I think that today I completed the tests and changes which I begun
|
859 |
|
|
on 17-May-2004.
|
860 |
|
|
ECO32 Version 0.6 released.
|
861 |
|
|
|
862 |
|
|
27-Oct-2005
|
863 |
|
|
ECO32 Version 0.7 released.
|
864 |
|
|
This was done in order to have a stable release on which to build
|
865 |
|
|
a simplified version of the ECO32, which is named ECO32e (the 'e'
|
866 |
|
|
stands for 'embedded'). The ECO32e will get implemented in an FPGA.
|
867 |
|
|
|
868 |
|
|
26-Jun-2006
|
869 |
|
|
We do have an error in the implementation of the SAR instructions,
|
870 |
|
|
really! The C standard says that the result of shifts with shift
|
871 |
|
|
amounts greater than or equal to (!) the number of bits in the left
|
872 |
|
|
expression's type is undefined. Consequently, in the CPU implementation
|
873 |
|
|
cpu.c we have to replace
|
874 |
|
|
smsk = (MSB ? 0xFFFFFFFF << (32 - scnt) : 0);
|
875 |
|
|
in the SAR and SARI instructions with
|
876 |
|
|
smsk = (MSB ? ~(((Word) 0xFFFFFFFF) >> scnt) : 0);
|
877 |
|
|
because if scnt == 0 then 0xFFFFFFFF << (32 - scnt) is undefined.
|
878 |
|
|
Thanks to Rolf Viehmann for pointing this out.
|
879 |
|
|
|
880 |
|
|
27-Jun-2006
|
881 |
|
|
The rfx instruction must not be executed in user mode, because it
|
882 |
|
|
writes the previous mode and interrupt enable bits of the PSW over
|
883 |
|
|
the current ones. Therefore rfx becomes a privileged instruction
|
884 |
|
|
which triggers EXC_PRV_INSTRCT if executed in user mode.
|
885 |
|
|
Again thanks to Rolf Viehmann for recognizing the potential danger
|
886 |
|
|
if this instruction is executed in user mode.
|
887 |
|
|
|
888 |
|
|
09-Jul-2006
|
889 |
|
|
Pending interrupts are now displayed when executing the 'register'
|
890 |
|
|
command. It is not meaningful to display pending exceptions, however,
|
891 |
|
|
because these are immediately handled within the longjump framework
|
892 |
|
|
and thus would never show anything else but 'off'.
|
893 |
|
|
|
894 |
|
|
10-Jul-2006
|
895 |
|
|
We have a new command to display (and possibly change) the value of
|
896 |
|
|
the PSW. This comes in very handy if debugging in user mode and thus
|
897 |
|
|
not having access to privileged addresses.
|
898 |
|
|
|
899 |
|
|
12-Jul-2006
|
900 |
|
|
There is a new control bit in the PSW, the 'vector bit' V, which directs
|
901 |
|
|
interrupts to ROM_BASE + 4 if it is off and to RAM_BASE + 4 if it is on.
|
902 |
|
|
This bit is cleared when the CPU is reset. In this way the software can
|
903 |
|
|
decide whether the interrupt service routine is located in ROM or in RAM.
|
904 |
|
|
|
905 |
|
|
15-Jul-2006
|
906 |
|
|
I decided to give "user TLB misses" an extra interrupt service routine
|
907 |
|
|
entry point. These are TLB misses triggered by an access to a virtual
|
908 |
|
|
address with MSB = 0, regardless of execution mode (user or kernel).
|
909 |
|
|
|
910 |
|
|
22-Jul-2006
|
911 |
|
|
The physical address space (2^30 bytes) is partitioned as follows
|
912 |
|
|
(in order to be compatible with the ECO32e):
|
913 |
|
|
RAM virt start 0xC0000000 phys start 0x00000000 size 0x20000000
|
914 |
|
|
ROM virt start 0xE0000000 phys start 0x20000000 size 0x10000000
|
915 |
|
|
I/O virt start 0xF0000000 phys start 0x30000000 size 0x10000000
|
916 |
|
|
The I/O address space is evenly divided into 256 devices which may
|
917 |
|
|
occupy up to 1MByte each.
|
918 |
|
|
|
919 |
|
|
30-Jul-2006
|
920 |
|
|
We now have two control bits in the outgoing part of every entry of
|
921 |
|
|
the TLB: a "valid" bit (which triggers a "TLB invalid exception" if
|
922 |
|
|
this entry is selected by a memory translation and the bit is 0) and
|
923 |
|
|
a "write" bit (which triggers a "TLB write exception" if this entry
|
924 |
|
|
is used to map a write access to a page and the bit is 0). The "TLB
|
925 |
|
|
double hit exception" does not exist any longer.
|
926 |
|
|
The reason for existence of the "write" bit is obvious (possibility
|
927 |
|
|
to protect pages from writing, implement a copy-on-write policy).
|
928 |
|
|
The reason for existence of the "valid" bit is speed: the TLB refill
|
929 |
|
|
routine should run as fast as possible and therefore should avoid
|
930 |
|
|
tests for special cases as much as possible. If some processing must
|
931 |
|
|
be done for a page to be usable, the check for this condition should
|
932 |
|
|
not be done in the TLB miss handler. If the valid bit is cleared in
|
933 |
|
|
the page table, the refill routine will enter the translation that it
|
934 |
|
|
gets from the page table into the TLB without checking, but the next
|
935 |
|
|
use of this entry will lead to another exception, where the processing
|
936 |
|
|
then can be done.
|
937 |
|
|
|
938 |
|
|
31-Jul-2006
|
939 |
|
|
The implementation of the ECO32e suggested a different coding of the
|
940 |
|
|
single register operand in the jr and jalr instructions. It is now
|
941 |
|
|
coded in the src1 field instead of the dst field of these instructions.
|
942 |
|
|
|
943 |
|
|
01-Aug-2006
|
944 |
|
|
a) I rearranged the exceptions as follows:
|
945 |
|
|
EXC_BUS_TIMEOUT 16
|
946 |
|
|
EXC_ILL_INSTRCT 17
|
947 |
|
|
EXC_PRV_INSTRCT 18
|
948 |
|
|
EXC_DIVIDE 19
|
949 |
|
|
EXC_TRAP 20
|
950 |
|
|
EXC_TLB_MISS 21
|
951 |
|
|
EXC_TLB_WRITE 22
|
952 |
|
|
EXC_TLB_INVALID 23
|
953 |
|
|
EXC_ILL_ADDRESS 24
|
954 |
|
|
EXC_PRV_ADDRESS 25
|
955 |
|
|
In this way they are grouped together more logically.
|
956 |
|
|
b) The detection of an EXC_ILL_ADDRESS exception (formerly called
|
957 |
|
|
EXC_BUS_ADDRESS) is now done in the MMU and thus operates on logical
|
958 |
|
|
addresses. It is then possible to store the offending address in the
|
959 |
|
|
BadAddr register for further processing by OS software.
|
960 |
|
|
c) The EntryHi register now gets loaded with the page base address
|
961 |
|
|
if one of the three TLB exceptions occurs, so that it need not be
|
962 |
|
|
computed from the contents of the BadAddr register.
|
963 |
|
|
|
964 |
|
|
02-Aug-2006
|
965 |
|
|
A "context" register, which is preloaded by OS software with the base
|
966 |
|
|
address of memory-resident page tables, and where the page number of
|
967 |
|
|
a page with missing translation is ored-in by hardware would speed up
|
968 |
|
|
the TLB miss handler. On the other hand, it practically mandates the
|
969 |
|
|
use of a certain page table format (or, if the OS designer wants a
|
970 |
|
|
different format, the context register would not be used at all).
|
971 |
|
|
Therefore I will not implement a context register.
|
972 |
|
|
|
973 |
|
|
03-Oct-2006
|
974 |
|
|
Major instruction format redesign: the decision to put the destination
|
975 |
|
|
register address in a fixed location within the instruction was wrong.
|
976 |
|
|
It implied that the source register addresses were not fixed and thus
|
977 |
|
|
must be multiplexed early in the instruction cycle dependent upon the
|
978 |
|
|
opcode. It should be done the other way around. Completed.
|
979 |
|
|
|
980 |
|
|
19-Nov-2006
|
981 |
|
|
Today I completed the back-port of the display and keyboard from ECO32e.
|
982 |
|
|
Both are available if the command line switch -c ("console") is given.
|
983 |
|
|
The default number of terminals was in turn reduced to 0.
|
984 |
|
|
|
985 |
|
|
14-Feb-2007
|
986 |
|
|
Interrupts are now level triggered. If at any time interrupt sharing
|
987 |
|
|
would become necessary (this is in fact quite possible with only 16
|
988 |
|
|
interrupts) it cannot be realized if interrupts were edge triggered.
|
989 |
|
|
|
990 |
|
|
04-Jun-2008
|
991 |
|
|
Project finally split:
|
992 |
|
|
ECO32 (version 0.17) -- FPGA hardware, simulator, assembler
|
993 |
|
|
EOS32 (version 0.11) -- C compiler, ROM monitor, operating system
|
994 |
|
|
|
995 |
|
|
20-Feb-2009
|
996 |
|
|
ECO32 now has its own linkable object file format, which is a variant
|
997 |
|
|
of the venerable a.out format. Consequently, 'asld' has been split into
|
998 |
|
|
the assembler 'as' and the linking loader 'ld'. Additionally, there is
|
999 |
|
|
a program 'dof' which dumps the contents of an object file.
|
1000 |
|
|
|
1001 |
|
|
22-Feb-2009
|
1002 |
|
|
What is the exact meaning of 'jalr $31'? This can of course be defined
|
1003 |
|
|
arbitrarily, but the natural semantics would likely be "jump to the
|
1004 |
|
|
routine addressed by $31 and remember the return address (in $31)".
|
1005 |
|
|
To my surprise, the hardware did exactly that, while the simulator
|
1006 |
|
|
interpreted the instruction as "store the return address in $31 and
|
1007 |
|
|
then jump to the routine addressed by $31", which resulted in not
|
1008 |
|
|
taking the jump at all. Simulator corrected.
|
1009 |
|
|
|
1010 |
|
|
14-Feb-2011
|
1011 |
|
|
B_PHYS and B_MAP macros eliminated. They both are only used with the
|
1012 |
|
|
PDP-11 UNIBUS map functionality.
|
1013 |
|
|
|
1014 |
|
|
15-Feb-2011
|
1015 |
|
|
In the simulated ECO32, if I try to allocate 60 chunks of memory, each
|
1016 |
|
|
of them having 10000 bytes, I get a kernel panic: exception 22 in kernel
|
1017 |
|
|
mode. The reason is untested code, executed for the first time ever: the
|
1018 |
|
|
kernel is doing an "expansion swap" in order to get enough memory for
|
1019 |
|
|
the process.
|
1020 |
|
|
|
1021 |
|
|
16-Feb-2011
|
1022 |
|
|
Now this is interesting: what is the field "b_bcount" in struct buf
|
1023 |
|
|
(include/buf.h) good for? Do any transfers with b_bcount != BSIZE
|
1024 |
|
|
exist? The answer is yes, in two places:
|
1025 |
|
|
a) swap I/O (src/bio.c)
|
1026 |
|
|
b) raw I/O (src/bio.c)
|
1027 |
|
|
(There is a third (mis-)usage of the field b_bcount: it is used as
|
1028 |
|
|
b_active flag in some block device drivers.)
|
1029 |
|
|
Raw I/O has to be overhauled in any case, so we concentrate on swap
|
1030 |
|
|
I/O here. Swap I/O transfers possibly many pages at once, starting
|
1031 |
|
|
at a given disk block and a given memory address. But this is only
|
1032 |
|
|
correct under the current "contiguous physical memory per process"
|
1033 |
|
|
allocation policy. It is useless under any policy which allocates
|
1034 |
|
|
physical memory for a process non-contiguously - provided that the
|
1035 |
|
|
transfer mechanism accesses physical memory and not virtual memory
|
1036 |
|
|
(this is typically the case with DMA). So the kernel will no longer
|
1037 |
|
|
rely on the disk driver (and possibly the disk hardware) to transfer
|
1038 |
|
|
multiple blocks in a single call, but split them up into single block
|
1039 |
|
|
transfers. Done - the "expansion swap" is now running.
|
1040 |
26 |
hellwig |
|
1041 |
|
|
----------------------------------------------------------------
|
1042 |
|
|
|
1043 |
|
|
In the meantime...
|
1044 |
|
|
|
1045 |
|
|
- experiments with porting ECO32 to another FPGA board
|
1046 |
|
|
- splitting the project (separating the OS part)
|
1047 |
|
|
- experiments with a pipelined version of ECO32
|
1048 |
|
|
|
1049 |
|
|
----------------------------------------------------------------
|
1050 |
|
|
|
1051 |
|
|
03-Feb-2014
|
1052 |
|
|
Project "ECO32" created on OpenCores, based on version eco32-0.22:
|
1053 |
|
|
http://opencores.org/project,eco32
|
1054 |
|
|
|
1055 |
110 |
hellwig |
04-Feb-2014
|
1056 |
|
|
Main Makefile, lcc, docs, binutils, sim, and simtest added.
|
1057 |
|
|
|
1058 |
|
|
05-Feb-2014
|
1059 |
|
|
FPGA implementations, hwtests, monitor, disk and standalone
|
1060 |
|
|
programs added.
|
1061 |
|
|
|
1062 |
|
|
07-Feb-2014
|
1063 |
|
|
Release eco32-0.22 tagged.
|
1064 |
|
|
|
1065 |
|
|
08-Feb-2014
|
1066 |
|
|
ECO32 manual added. It can now be generated from TeX sources.
|
1067 |
|
|
|
1068 |
26 |
hellwig |
18-Feb-2014
|
1069 |
|
|
Several changes in the simulator:
|
1070 |
|
|
a) There are two independent identical timer/counters
|
1071 |
|
|
available, of course with different interrupts and I/O
|
1072 |
|
|
addresses (see below).
|
1073 |
|
|
b) The timer/counters are readable, so that they can
|
1074 |
|
|
be used for short-time measurements. They count clock
|
1075 |
|
|
cycles (no pre-scaling any longer). This change will
|
1076 |
|
|
affect all programs which use the timer/counters.
|
1077 |
|
|
c) The simulation timing model is completely based on
|
1078 |
110 |
hellwig |
clock cycles (and does no longer tries to function in
|
1079 |
26 |
hellwig |
some sort of "real-time"). As there is no real clock
|
1080 |
|
|
within the simulator, but the natural time unit is
|
1081 |
|
|
one instruction, the simulation time is incremented
|
1082 |
|
|
by the CPI value (clock cycles per instruction) every
|
1083 |
|
|
instruction. I measured the CPI value in the real ECO32
|
1084 |
|
|
implementation: it's a horrible 18 cycles per instruction,
|
1085 |
|
|
yielding an instruction rate of about 2.8 MIPS. There is
|
1086 |
|
|
so much room for improvements...
|
1087 |
|
|
d) I changed the resolution of the simulation timers to
|
1088 |
|
|
microseconds. All timing constants had to be adapted and
|
1089 |
|
|
can now be specified more precisely. They are automatically
|
1090 |
|
|
scaled to clock cycles (see above).
|
1091 |
|
|
e) The addressing scheme for peripherals of the same sort
|
1092 |
|
|
has changed slightly. Virtual addresses of I/O devices have
|
1093 |
|
|
the form 0xFxxyyrrr, where xx is the device type, yy is the
|
1094 |
|
|
device number, and rrr is the register within the device
|
1095 |
|
|
(must be a word address). This change could affect existent
|
1096 |
|
|
programs which use more than one terminal.
|
1097 |
|
|
f) The ECO32 simulation got a new peripheral, called the
|
1098 |
|
|
"shutdown device". A write to address 0xFF100000 results
|
1099 |
|
|
in terminating the simulation run, with the lower 8 bits
|
1100 |
|
|
of the data written supplied as exit status.
|
1101 |
110 |
hellwig |
|
1102 |
|
|
19-Feb-2014
|
1103 |
|
|
In the hardware section, only the latest FPGA implementation
|
1104 |
|
|
was kept.
|
1105 |
|
|
|
1106 |
|
|
20-Feb-2014
|
1107 |
|
|
New ISE project file created. In the LCC section, lburg/gram.c
|
1108 |
|
|
gets re-generated from the grammar file. Two new simulator
|
1109 |
|
|
tests written. Standalone programs updated.
|
1110 |
|
|
|
1111 |
|
|
22-Feb-2014
|
1112 |
|
|
Tools: bin2exo tool updated, bin2mcs tool added. Hardware:
|
1113 |
|
|
character generator generator added, display memory generator
|
1114 |
|
|
added. Monitor: load server added. Disk: disk server renamed
|
1115 |
|
|
and updated.
|
1116 |
|
|
|
1117 |
|
|
23-Feb-2014
|
1118 |
|
|
Monitor directories re-structured. Monitors extensively updated.
|
1119 |
|
|
FPGA implementation updated; timer is now equal to port-15.
|
1120 |
|
|
|
1121 |
|
|
24-Feb-2014
|
1122 |
|
|
Hardware: timer counts clock cycles, counter is readable, two
|
1123 |
|
|
timers are now available.
|
1124 |
|
|
|
1125 |
|
|
25-Feb-2014
|
1126 |
|
|
Simulator: IRQ 15 explanation added, IRQ 0-3 explanations
|
1127 |
|
|
changed.
|
1128 |
|
|
|
1129 |
|
|
26-Feb-2014
|
1130 |
|
|
Hardware: cpu is now equal to port-15. Constraints file for
|
1131 |
|
|
XESS board re-formatted.
|
1132 |
|
|
|
1133 |
|
|
27-Feb-2014
|
1134 |
|
|
Simulator: tlbBadAddr register is now called mmuBadAddr.
|
1135 |
|
|
|
1136 |
|
|
28-Feb-2014
|
1137 |
|
|
Hardware tests (kbdtest): second timer added.
|
1138 |
|
|
|
1139 |
|
|
01-Mar-2014
|
1140 |
|
|
Hardware tests (xcptest): test the bad address register too.
|
1141 |
|
|
Hardware: cpu now also has a bad address register.
|
1142 |
|
|
*****************************************************************
|
1143 |
|
|
Stefan Kristiansson's Linux port to ECO32 is running on the FPGA!
|
1144 |
|
|
*****************************************************************
|
1145 |
|
|
Simulator: change command @ -> #, better help for commands.
|
1146 |
|
|
Simulator: individual help messages corrected.
|
1147 |
|
|
|
1148 |
|
|
02-Mar-2014
|
1149 |
|
|
Monitor: bad address register added.
|
1150 |
|
|
Monitor: bootstrap parameters modified.
|
1151 |
|
|
Disk: master boot made compatible with monitor.
|
1152 |
|
|
|
1153 |
|
|
03-Mar-2014
|
1154 |
|
|
DE0-Nano board arrived. I can download a simple design.
|
1155 |
|
|
|
1156 |
|
|
04-Mar-2014
|
1157 |
|
|
The Nano board does only have a bit-serial ROM. Besides the
|
1158 |
|
|
configuration bitstring for the FPGA there is enough room in
|
1159 |
|
|
it to store the machine monitor, but this program cannot
|
1160 |
|
|
reasonably be executed from there. So it must be copied to
|
1161 |
|
|
RAM before it can be started. This is also the case with the
|
1162 |
|
|
S3E starter kit board - this board indeed does have a parallel
|
1163 |
|
|
ROM but alas, it must be disabled in order to use the A/D or
|
1164 |
|
|
D/A converters. Therefore it is best to run the monitor from
|
1165 |
|
|
RAM in any case. Consequences: the boot procedures must again
|
1166 |
|
|
be revised.
|
1167 |
|
|
Monitor: do not set sp on bootstrap.
|
1168 |
|
|
EOS32 bootstrap update.
|
1169 |
|
|
|
1170 |
|
|
05-Mar-2014
|
1171 |
|
|
Simulator: -a command line option added (which specifies a load
|
1172 |
|
|
address where a binary file is loaded when -l is given).
|
1173 |
|
|
Compiler: -Wo-kernel relocates code to 0xC0010000.
|
1174 |
|
|
|
1175 |
|
|
06-Mar-2014
|
1176 |
|
|
Standalone programs (hello, hello2, memsize, onetask, twotasks-1,
|
1177 |
|
|
twotasks-2) executable at 0xC0010000.
|
1178 |
|
|
|
1179 |
|
|
07-Mar-2014
|
1180 |
|
|
Standalone programs (wrtmbr, dskchk) executable at 0xC0010000.
|
1181 |
|
|
|
1182 |
|
|
08-Mar-2014
|
1183 |
|
|
Standalone programs (shpart, mkpart) executable at 0xC0010000.
|
1184 |
|
|
Verified the four ways that a standalone program can be executed:
|
1185 |
|
|
- simulator and -l/-a command line options
|
1186 |
|
|
- simulator and simulated disk (boot the standalone program)
|
1187 |
|
|
- FPGA and load server (load the standalone program)
|
1188 |
|
|
- FPGA and simulated disk (boot the standalone program)
|
1189 |
113 |
hellwig |
|
1190 |
|
|
09-Mar-2014
|
1191 |
|
|
NetBSD bootstrap now executing at 0xC0010000.
|
1192 |
116 |
hellwig |
|
1193 |
|
|
14-Mar-2014
|
1194 |
|
|
Hardware: kbd is now equal to port-15.
|
1195 |
117 |
hellwig |
Hardware: ser is now equal to port-15.
|
1196 |
118 |
hellwig |
|
1197 |
|
|
15-Mar-2014
|
1198 |
|
|
Hardware: rom is now equivalent to port-15.
|
1199 |
119 |
hellwig |
Hardware: ram is now equivalent to port-15.
|