All remaining assignments for this class are based on the creation and extension of a user-space device driver for a in memory filesystem that is built on top of a hierarchical random access memory system (HRAM). At the highest level, you will translate file system commands into memory frame level memory operations (see memory interface specification below). The file system commands include open, read, write, seek and close for files that are written to your file system driver. These operations perform the same as the normal UNIX I/O operations, with the caveat that they direct file contents to the HRAM storage device instead of the host filesystem. The arrangement of software is as follows:
System and Project Overview
You are to write a basic device driver
that will sit between a virtual application and virtualized hardware. The application makes use of the abstraction you will provide called HRAM “cartridge” memory system (CART). The design of the system is shown in the figure to the right:
Described in detail below, we can see three layers. The CART application is provided to you and will call your device driver functions with the basic UNIX file operations (open, …). You are to write the device driver code to implement the file operations. Your code will communicate with a virtual controller by sending opcodes and data
over an I/O bus.
All of the code for application (called the simulator) and CART memory system is given to you. Numerous utility functions are also provided to help debug and test your program, as well as create readable output. Sample workloads have been generated and will be used to extensively test the program.
The Cartridge Memory System Driver (CART)
You are to write the driver that will implement the the basic UNIX file interface using the memory system. You will write code to implement the filesystem, and make several design decisions that will determine the structure and performance of the driver. In essence you will write code for the read, write, open, close and other high level filesystem functions. Each function will translate the call into low-level operations on the device (see below).
The functions you will implement are:
int32_t cart_poweron(void); – This function will initialize the CART interface basic filesystem. To do this you will execute the init CART opcode and zero all of the memory locations. You will also need to setup your internal data structures that track the state of the filesystem.
int32_t cart_poweroff(void); – This function will show down the CART interface basic filesystem. To do this you will execute the shutdown CART opcode and close all of the files. You will also need to cleanup your internal data structures that track the state of the filesystem
int16_t cart_open(char *path); – This function will open a file (named path) in the filesystem. If the file does not exist, it should be created and set to zero length. If it does exist, it should be opened and its read/write postion should be set to the first byte. Note that there are no subdirectories in the filesystem, just files (so you can treat the path as a
filename). The function should return a unique file handle used for subsequent operations
or -1 if a failure occurs.
int16_t cart_close(int16_t fd); – This function closes the file referenced by the file handle
that was previously open. The function should fail (and return -1) if the file handle is bad
or the file was not previously open.
int32_t cart_read(int16_t fd, void *buf, int32_t count); – This function should
read count bytes from the file referenced by the file handle at the current position. Note that if there are not enough bytes left in the file, the function should read to the end of the file and return the number of bytes read. If there are enough bytes to fulfill the read, the function should return count. The function should fail (and return -1) if the file handle is bad or the file was not previously open.
int32_t cart_write(int16_t fd, void *buf, int32_t count); – The function should write count bytes into the file referenced by the file handle. If the write goes beyond the end of the file the size should be increased. The function should always return the number of bytes written, e.g., count. The function should fail (and return -1) if the file handle is bad or the file was not previously open.
int32_t cart_seek(int16_t fd, uint32_t loc); – The function should set the current position into the file to loc, where 0 is the first byte in the file. The function should fail (and return -1) if the loc is beyond the end of the file, the file handle is bad or the file was not previously open.
The key to this assignment if figuring out what you need to do to implement these functions. You are specifically not given guidance on how to do it. You need to (a) maintain information about current files in the file system, (b) allocate parts if the memory system to place data, (c) copy data
into and out of the memory system as needed to serve reads and writes. How you do this is up to you, but think carefull about it before beginning to code. What is important is that the code you write will be built upon the whole semester.
The Cartridge Memory System (CART)
You will implement your driver on top of the CART memory system (which is referred to throughout simply as the CART). The CART is a hierarchical memory system, which means that there are multiple levels of memory organization. In the case of the CART, there are three levels:
the system as a whole consists of multiple cartridges, each of which contain multiple frames. Each frame is a fixed byte sized memory block. Some key facts of the system include (see cart_controller.h for definitions):
There
are CART_MAX_CARTRIDGES cartridges in the system, each of which is numbered
from 0 to CART_MAX_CARTRIDGES-1.
Each cartridge contains are CART_CARTRIDGE_SIZE frames, each of which is numbered
from 0 to CART_MAX_CARTRIDGES-1.
A frame is memory block of CART_FRAME_SIZE bytes.
You communicate with the memory system by sending code through a set ofpacked registers. These registers are set within a 64-bit value to encode the opcode and arguments to the hardware device. The opcode is laid out as follows:
Bits Register (note that top is bit 0) —— —————-
——————-
0-7 – KY1 (Key
Register 1)
7-15 – KY2 (Key
Register 2)
16 – RT1 (Return
code register 1) 17-32 – CT1
(Cartridge register 1)
33-48 – FM1 (Frame register 1) 48-63 – UNUSED
The following opcodes define how you interact with the controller. Note that the UNUSED parts of the opcode should always be zero, as should any register not explicitly listed in the specifications below. If the frame argument is not specified, then it should be passed as NULL.
Register
Request Value
Response Value
CART_OP_INITMS – Initialize the memory system
Register: KY1
CART_OP_INITMS
CART_OP_INITMS
Register: RT 0 if successful, -1 if failure
CART_OP_BZERO – zero a cartridge
Register: KY1 CART_OP_BZERO
Register: RT 0 if successful, -1 if failure
Register: CT1 N/A
CART_OP_LDCART – load a cartridge
Register: KY1 CART_OP_LDCART
Register: RT 0 if successful, -1 if failure
Register: CT1 N/A
CART_OP_RDFRME – read a frame from the current cartridge
Register: KY1 CART_OP_RDFRME
Register: RT 0 if successful, -1 if failure
Register: FM1 N/A
CART_OP_WRFRME – write a frame to the current cartridge
Register: KY1 CART_OP_WRFRME
Register: RT 0 if successful, -1 if failure
Register: FM1 N/A
CART_OP_POWOFF – power off the memory system
Register: KY1 CART_OP_POWOFF
Register: RT 0 if successful, -1 if failure
N/A
CART_OP_BZERO
N/A
cartridge number to zero out
CART_OP_LDCART
N/A
cartridge number to load
CART_OP_RDFRME
N/A
frame number to read from
CART_OP_WRFRME
N/A
frame number to write to
CART_OP_POWOFF
N/A
To execute an opcode, create a 64 bit value (uint64_t) and pass it any needed buffers to the bus function defined in cart_controller.h:
CartXferRegister cart_io_bus(CartXferRegister regstate, void *buf)
The function returns packed register values with as listed in the “Response Value” above.
Instructions
A. Login to your virtual machine (虚拟 Ubuntu 使用 c 语言在终端写). From your virtual machine, download the starter source code provided for this assignment. To do this, use the wget utility to download the file off the main course website:
B. Create a directory for your assignments and copy the file into it. Change into that directory.
% mkdir cmpsc311
% cp assign2-starter.tgz cmpsc311 % cd cmpsc311
% tar xvzf assign2-starter.tgz
Once unpacked, you will have the starter files in the assign2, including the source code, libraries, and a Makefile. There is also a subdirectory containing workload files.
C. You are to complete the cart_drver.c functions defined above. Note that you may need to create additional supporting functions within the same file. Include functional prototypes for these functions at the top of the file.
D. Add comments to all of your files stating what the code is doing. Fill out the comment function header for each function you are defining in the code. A sample header you can copy for this purpose is provided for the main function in the code.
E. To test your program with these provided workload files, run the code specifying a workload file as follows:
./cart_sim –v workload/cmpsc311-f16-assign2-workload.txt
Note that you don’t necessarily have to use the -v option, but it provides a lot of debugging information that is helpful.
If the program completes successfully, the following should be displayed as the last log entry:
CART simulation: all tests successful!!!.
To turn in:
1. Create a tarball file containing the assign2 directory, source code and build files as completed above.
2. Before sending the tarball, test it using the following commands (in a temporary directory — NOT the directory you used to develop the code):
% tar xvzf LASTNAME-PSUEMAILID-assign2.tgz % cd assign2
% make
… (TEST THE PROGRAM)