Memory Map (E2, Headless/Single-Chip Design)
The memory layout of the Headless Kestrel-3 was designed with easy emulation (especially by another RV64 processor) in mind. There are only three broad categories of devices on the CPU's bus: ROM, RAM, and I/O devices. These three broad categories are placed on Sv39 mega-page boundaries.
||SIA #2 (Mass Storage)|
||SIA #1 (User's Console)|
For both the ROM and the RAM, only 1MB will be exposed to the processor. The ROM is actually the SPI Flash ROM, the same used to program the FPGA with. RAM will be the 1MB SRAM on the icoBoard Gamma card. This means that the memory map more closely resembles the following:
||SIA #2 (Mass Storage)|
||SIA #1 (User's Console)|
All unmapped regions (in physical hardware at least) will generate either an access fault or a page fault, depending on whether or not the MMU is enabled. If the MMU is enabled, the virtual machine monitoring the virtual Kestrel-3 process should reflect the page fault back to the Kestrel-3 firmware as an access fault.
You'll notice that I/O devices appear on 4KiB page boundaries. This is intended to facilitate operating systems which intend to expose specific I/O devices to specific user-mode processes. E.g., a console driver running in a microkernel would run in user-space, and have access to SIA #1 from within user-space. However, page protections will ensure that SIA #2 will be off-limits, for that resource is almost certainly going to belong to the filesystem driver.
SIA: Serial Interface Adapter
+--------+--------+--------+--------+ | INTENA | RXINP | STAT | TXOUT | +0 +--------+--------+--------+--------+ | BAUD | +4 +-----------------------------------+
TXOUT +0 xxxxxxxx W Transmitter Data Register
This register is write-only. If you attempt to read from this register, the value returned is not specified.
This write-only 8-bit register accepts data to send serially to another peripheral. Bits are transmitted using one start-bit, 8-data bits (LSB first), no parity, and finally one stop-bit.
If the SIA is busy transmitting a byte when another byte is written to this register, the hart will block until the shift register is ready to accept the latter byte. Thus, it is not necessary for software to explicitly poll the SIA to see if it's ready before sending another byte, as the following example illustrates.
send_buffer: ; A0 -> buffer, A1 = length of buffer, A2 -> SIA base lb t0,0(a0) sb t0,0(a2) addi a0,a0,1 addi a1,a1,-1 bne a1,x0,send_buffer jalr x0,0(ra)
STAT.TXR bit will be clear while the shift register is busy;
otherwise, it will be set.
RXST exists in the software emulator E2, and has the following definition.
RXST +1 .......1 R RXV RXINP holds valid data
STAT register replaces
RXST in the hardware implementation of the SIA,
RXST with status information for both the receiver and the transmitter.
STAT +1 .......1 R RXV RXINP holds valid data ......1. R RXO RXINP overrun .....1.. R TXR TXOUT ready for another byte ....1... R RXI Receiver is currently idle ...1.... R RXF Receiver frame error detected ..0..... R --- .1...... R RX0 Start bit (should always be 0) 1....... R RX9 Stop bit (should always be 1)
RXINP section below for an example of how to use this register to poll for new data.
All other bits are undefined, and are read back as 0.
RXINP +2 xxxxxxxx R
This register holds the most recently received byte.
If another byte is being received, this register's contents will remain stable until the stop-bit of the new byte is received.
When a hart reads this register. the valid data and overrun flags will clear automatically.
If a byte has been received while the valid data is already set (that is, a new byte has arrived before a host could receive the old byte), the overrun flag will be set.
The following code illustrates how to read a byte of data from the SIA:
read_byte: ; On entry: A0 -> SIA core ; On exit: A0 = byte retrieved. ; Destroyed: T0 lb t0,1(a0) andi t0,t0,1 beq t0,x0,read_byte lb a0,2(a0) jalr x0,0(ra)
INTENA register contains a number of bits which can be used to mask reasons for interrupt.
INTENA +1 .......1 R EV Interrupt when RXINP holds valid data ......1. R EO Interrupt when RXINP is overrun. .....1.. R ER Interrupt when TXOUT is ready for another byte ....1... R EI Interrupt when the receiver falls idle ...1.... R EF Interrupt if a frame error is detected
BAUD +4 ........ ....xxxx xxxxxxxx xxxxxxxx RW Baud Rate Divisor ..x..... ........ ........ ........ RW RXD Loopback Control xx...... ........ ........ ........ RW TXD Loopback Control
This register holds the divisor for baud rate generation and some control bits that affects the operation of the TXD and RXD pins. These control bits should be written as 0 for normal operation.
The data rate which the SIA uses to communicate with a remote device is calculated according to this formula:
100 000 000 MHz data_rate (bits/sec) = --------------- BAUD + 1
More useful to software, perhaps, is to solve for
BAUD given a preferred data rate:
100 000 000 MHz BAUD = floor( --------------- ) - 1 data_rate (bps)
For example, to communicate with another device at 9600 bps,
BAUD to 10415.
Because the divisor is only 20 bits wide, the slowest data rate is approximately 95 bits per second. Setting the divisor to zero will yield a 100Mbps transmission speed. The SIA, however, will not be able to receive at this speed. The fastest practical, bidirectional speed will come to around 12.5Mbps or, under more tightly controlled conditions, 25Mbps.
The top two bits instructs the SIA how to handle the TXD output pin, according to the following table:
|0||0||The serial output shift register drives the
When configured for remote loopback, any data received from a remote device is echoed, bit for bit, back to that device. Any data sent by the local device is ignored and never makes it to the output. This is very helpful for testing a serial connection at the remote end.
NOTE: Unless configured otherwise, the data received from the remote device still makes it to the receiver! This allows, for instance, the remote device to instruct the local device when to switch back to normal operation.
BAUD controls the local loopback configuration. If set to 0, the RXD input is tied to the receiver's input shift register. This is the normal behavior for a UART.
If BAUD is 1, however, the input shift register is tied to the transmitter's shift register output. Any signals appearing on the RXD input pin is ignored by the SIA (except for remote loopback configuration; see above).
Local loopback mode allows the software of the local machine to test if the SIA exists and works, and should not be used for any other purpose.
NOTE: The SIA does not currently implement a receiver FIFO. A future version of the SIA may support a FIFO on the receiving path. With clever use of loopback mode, you can measure the depth of the FIFO as well.