This should implement the same ISA as the emulator, but aims to be synthesizable inside an FPGA or ASIC.
For simulation only, you need the GHDL compiler, and possibly GTKWave to display the simulated waveforms.
If you want to synthesize a bitstream or simulate for the actual hardware, you need the vendor toolchain. For the Phi board (which is rather seldom, but the first board implemented here, this would be Intel Quartus 16.1.
There are four scripts inside the logic/
directory:
sim.sh : Compile and simulate using GHDL
gen.sh : Generate the vendor IP blocks for synthesis and simulation
msim.sh : Simulate using ModelSim
syn.sh : Synthesize bitstreams
The display/
directory contains the Vulkan frontend to display the output
generated inside the FPGA. Configure using ./configure
and build with
make
, as per usual; you need X11 and Vulkan headers and libraries.
The linux/
directory contains the Linux driver for the PCIe
implementation. Compile using make
, possibly passing the KVERSION
variable to target a different kernel version than the one running.
The main CPU core (cpu
) has separate 64 bit instruction and 32 bit data
buses that are fully synchronous and assumes that any memory interface or
peripherals are external.
To run the CPU on actual hardware, memory and peripherals are required. These are implemented in the PCIe example by using 16 MiB of host memory, and in cooperation with a driver running on the host.
This BAR is 32 bit addressable non-prefetchable memory, so accesses are performed exactly as the host CPU generates them. The BAR only supports only 64 bit wide accesses to 64 bit aligned addresses.
This is the CPU status. Currently, only bit 0 is defined, which indicates that the CPU is currently running.
This controls the emulated CPU. The upper half acts as a mask on the lower half, so if bit n+32 is clear, bit n will be unaffected by a write.
While this bit is set, the CPU is held in reset.
Setting this bit updates the host's copy of the textmode display. This bit auto-resets after the update is complete.
These are the host interrupt status flags.
This is set when the emulated CPU halts, but is not in reset.
This is set when the display contents have changed.
This allows enabling interrupt sources. The bits are the same as for the Interrupt Status.
This is the host physical address of a 2 MiB buffer that should receive the graphical output while the emulated system is in text mode.
These are eight host physical addresses of 2 MiB pages that should be used as the memory for the emulated CPU.
The driver matches the implementation inside the FPGA, performs the necessary initialization and provides access to the emulated peripherals.
This is the main interface. Open this device node in read-write mode.
The memory of the emulated system is accessible by read/write/llseek on the
device node. mmap
is not supported yet.
The CPU is reset by calling the BSS2K_IOC_RESET
ioctl. This ioctl has no
arguments.
The CPU can be started by submitting the BSS2K_IOC_START_CPU
ioctl. No
arguments.
The control registers can be accessed directly using
BSS2K_IOC_READ_STATUS
BSS2K_IOC_READ_CONTROL
BSS2K_IOC_READ_INTSTS
BSS2K_IOC_READ_INTMASK
BSS2K_IOC_WRITE_CONTROL
BSS2K_IOC_WRITE_INTMASK
These require a pointer to a 64 bit unsigned integer that is overwritten by the READ ioctls and needs to be initialized for the WRITE ioctls.
The BSS2K_IOC_GET_TEXTMODE_TEXTURE
returns a file descriptor that can be
converted to a dma_buf
object in another kernel driver, and that gives
access to a 32 bit RGBA bitmap containing the current contents of the
textmode display.
This file descriptor can be passed to the VK_EXT_external_memory_dma_buf Vulkan extension to get a texture image that can be rendered.
Testbenches can be run automatically using the sim.sh
script, and require
GHDL to run, and GtkWave to inspect the waveform data.
This testbench loads the "Hello world" example binary, and executes it in the CPU, then terminates when the CPU stops.