EE382N Project Specifications

Addendum posted April 18, 2000
Constant values you can hardcode in Verilog:

TLB Entries:
Vir. Page  Phy. Page Valid Present R/W
    20'h0    20'h0     1     1     0
    20'h2    20'h2     1     1     1
    20'h4    20'h5     1     1     1
    20'hb    20'h4     1     1     1
    20'hc    20'h7     1     1     1
    20'ha    20'h5     1     1     1

There are eight entries total.  The other two entries are not defined for the test programs, but you may use them for testing your I/O  devices.  For the final testing, the valid bits of these two entries  should be zero.

The IDT base register is 0x3000.  This means 0x3000 is the physical address of the base of the Interrupt Descriptor Table.  The code for  the service routines will be in one of the pages listed above.

Segment Limits
 CS: 0x4fff
 DS: 0x11ff
 SS: 0x4000
 ES: 0x43ff
 FS: 0x3ff
 GS: 0x7ff

Effective addresses larger than the limit will cause a general protection exception (except for the SS limit, which you aren't required to implement).

Addendum posted March 22, 2000

Main Memory should be 32 KB in size.  Because different groups may use different memory configurations, the input file format may be different for each group.  Before the final testing, I will create input files that are easily readable for your memory configurations, and I will let you know which areas of memory should be initialized.  (Each test case will only use a small portion of the memory, so there is no point in initializing all 256 SRAM modules.)

You will need to support at least the following Flags: OF, SF, ZF, AF, CF, and PF.

Interrupts, Exceptions
You may assume that an exception will not occur while transferring control to the exception handler or servicing an interrupt or exception.

March 9, 2000

There will be no self-modifying code.

Operand and Address sizes
- 32-bit addresses
- operand sizes:
     - 8-bit (if specified by the opcode)
     - 16-bit (with operand size override prefix)
     - 32-bit (default)

Operand Addressing Modes
- immediate
- register
- ModR/M: all 32-bit addressing forms
- SIB: all except Base = (100 or 101)
- far pointers (ptr16:16, ptr16:32)

- operand size override prefix
- segment override prefixes

Instruction Subset
MOV : all forms listed on page 3-402 except "moffs" format
JMP,CALL : all formats except m16:16 and m16:32

Memory Hierarchy
Instruction and data caches should each contain a total of 1KB of data store, but you may configure them any way you wish.  The tag and data store should be made out of the RAM (not SRAM) parts.  Since valid bits must be initialized to 0, you can use registers for these bits if you wish.

Main memory should be made out of the SRAM parts.  The size and configuration will be determined later.

You will need to design a bus to connect main memory, the processor, and I/O devices.  You can decide how wide to make this bus and what type of arbitration scheme you use.

Linear addresses are calculated by adding the 32-bit effective address to the 16-bit value in a segment register shifted left by four bits (i.e. {12'b0, segment[15:0], 4'b0}) to form a 32-bit linear address. Associated with each segment is a segment limit.  The values of the segment limits will be constant, so they can be hardwired into your design.  I will specify the values of the segment limits at a later date.  If an effective address exceeds the segment limit, a general protection exception should be taken.  Note that if you access a word or doubleword, none of the bytes accessed can exceed the segment limit.

Virtual Memory
Virtual memory will be divided into pages of size 4KB.  You will implement a TLB to translate virtual page numbers (specified by the upper 20 bits of the address) to physical page numbers.  In addition to the virtual and physical translations, each TLB should also have at least three additional fields: a Valid bit, a Present flag, and a R/W (read / write) flag.  The Present flag indicates if the page being pointed to is currently present in physical memory.  The valid bit determines if the TLB entry is being used.  The R/W flag determines read / write permissions of the page.  When the R/W flag is clear, the page is read only; when it is set, the page can be written or read.

You may need to support other flags such as PCD (page-level cache disable) for memory-mapped I/O, or if you are implementing a DMA controller.  Descriptions of other flags in x86 page table entries is given in Section 3.6 of Volume 3 of the Intel Architecture Software Developer's Manual.  You will not be required to support these other flags, though.

The TLB will have eight entries, and both the virtual page numbers and the corresponding physical page numbers will be hardcoded.  The values to be hardcoded in six of the page table entries will be specified at a later date.  The two remaining entries can be used for memory-mapped I/O or anything needed for individual projects.  If the processor attempts to write to a read-only page, a general protection exception should be taken.  If the processor attempts to access either a page with a clear present bit or a page not in the TLB, a page fault should be taken.  (Note: in a real machine, a TLB miss would cause a page table lookup.  However, you are not required to implement the x86 page directory table for this project. )

I/O Devices
You should support at least two simple I/O devices such as memory-mapped monitor and keyboard registers.  These may access the same bus as main memory.  You may optionally support a more sophisticated I/O device such as a DMA controller.

Exceptions and Interrupts
You should support at least one (external) interrupt that is triggered by the I/O devices.

The exceptions that you must support are general protection exceptions (vector no. 13) and page faults (vector no. 14).  Both instruction and data accesses may cause exceptions.

Exception Handling is outlined in Chapter 4 of Volume 1 of the Intel Architecture Software Developer's Manual.  Each type of interrupt has a vector number that is an offset into the Interrupt Descriptor Table (IDT).  Each entry of the IDT is a 4-byte far pointer (16-bit code segment and 16-bit IP).  This far pointer is used as a jump target which will take the processor to an interrupt service routine.  The address of the IDT entry is calculated as: <vector_number> * 4 + IDT_base, where IDT_base is the *physical* address of the IDT.  Since IDT is located in physical memory, your interrupt handler must have a way of bypassing the TLB. The vector numbers are listed in table 4-1.

In your project, you should do the following when calling the interrupt or exception handler:
1.  Push EFLAGS on the stack
2.  Push CS
3.  Push EIP
4.  Calculate the address of the IDT entry containing the far pointer that points to the service routine.  Load the contents of the CS and EIP with the far pointer in the IDT entry.

The IRETD at the end of a service routine will pop EIP, CS, and EFLAGS, in that order.

The base address of the IDT will be specified later.

You will not be required to write service routines for general protection exceptions or page faults.  You may need to write service routines to demonstrate the functionality of your I/O devices, though.