Question: Develop an assembler that translates programs written in RISC - V assembly language into the binary code understood by the processor. You have been provided

Develop an assembler that translates programs written in RISC-V assembly language into the binary code
understood by the processor.
You have been provided with starter code in C for the assembler which take the RISC-V assembly-language
file as a command-line argument. If the input file name is trace 1, usage is as follows:
$./assembler trace_1
The trace file consists of text lines, each representing a RISC-V assembly instruction. Your assembler must
translate each of these instructions into machine code and store them in instruction memory. Use the skeleton
code provided to you as a starting point for your solution. In particular, an example of how to assemble an
R-type instruction is provided within the parse R type() function in parser.c.
Testing Your Assembler
Test the correctness of the machine code generated by your assembler using the provided trace file which
contains the following instruction classes: R-type, I-type, and SB-type.
add x10, x10, x25
ld x9,0(x10)
addi x22, x22,1
slli x11, x22,3
bne x8, x24,-4
First, translate these instructions into their corresponding binary representation by hand. Then, run the file
through your assembler implementation to compare the results and verify correctness.
Code for the Parser.c file to be edited is
#include "parser.h"
// FIXME: add support to identify and parse I-type and SB-type instructions
void load_instructions(instruction_memory_t *i_mem, const char *trace)
{
printf("Loading trace file: %s
", trace);
FILE *fd = fopen(trace,"r");
if (fd == NULL){
perror("Cannot open trace file.
");
exit(EXIT_FAILURE);
}
// Iterate over all the assembly instructions
char *line = NULL;
size_t len =0;
ssize_t read;
addr_t PC =0; // program counter points to the zeroth location initially.
int IMEM_index =0;
while ((read = getline(&line, &len, fd))!=-1){
// Assign program counter
i_mem->instructions[IMEM_index].addr = PC;
// Extract operation or opcode from the assembly instruction
char *raw_instr = strtok(line,"");
if (strcmp(raw_instr, "add")==0||
strcmp(raw_instr, "sub")==0||
strcmp(raw_instr, "sll")==0||
strcmp(raw_instr, "srl")==0||
strcmp(raw_instr, "xor")==0||
strcmp(raw_instr, "or")==0||
strcmp(raw_instr, "and")==0){
parse_R_type(raw_instr, &(i_mem->instructions[IMEM_index]));
i_mem->last = &(i_mem->instructions[IMEM_index]);
}
IMEM_index++;
PC +=4;
}
fclose(fd);
}
// Parse and assemble R-type instruction
void parse_R_type(char *opr, instruction_t *instr)
{
instr->instruction =0;
unsigned opcode =0;
unsigned funct3=0;
unsigned funct7=0;
if (strcmp(opr, "add")==0){
opcode =51;
funct3=0;
funct7=0;
}
char *reg = strtok(NULL,",");
unsigned rd = get_register_number(reg);
reg = strtok(NULL,",");
unsigned rs_1= get_register_number(reg);
reg = strtok(NULL,",");
reg[strlen(reg)-1]='\0';
unsigned rs_2= get_register_number(reg);
// Print the tokens
printf("Opcode: %u
", opcode);
printf("funct3: %u
", funct3);
printf("funct7: %u
", funct7);
printf("Source register 1: %u
", rs_1);
printf("Source register 2: %u
", rs_2);
printf("Destination register: %u
", rd);
// Contruct instruction
instr->instruction |= opcode;
instr->instruction |=(rd <<7);
instr->instruction |=(funct3<<(7+5));
instr->instruction |=(rs_1<<(7+5+3));
instr->instruction |=(rs_2<<(7+5+3+5));
instr->instruction |=(funct7<<(7+5+3+5+5));
}
// FIXME: parse and assemble I-type instruction
void parse_I_type(char *opr, instruction_t *instr)
{
}
// FIXME: parse and assemble SB-type instruction
void parse_SB_type(char *opr, instruction_t *instr)
{
}
unsigned int get_register_number(char *reg)
{
unsigned i =0;
for (i; i < NUM_OF_REGS; i++){
if (strcmp(REGISTER_NAME[i], reg)==0)
break;
}
return i;
}
Code for main.c is
#include
#include
#include "parser.h"
int main(int argc, char **argv)
{
if (argc !=2){
printf("Usage: %s %s
", argv[0],"");
exit(EXIT_SUCCESS);
}
// Load instructions from the trace file into memory
instruction_memory_t instr_mem;
instr_mem.last = NULL;
load_instructions(&instr_mem, argv[1]);
// Print instructions in binary format
unsigned PC =0;
while (1){
instruction_t *instr = &(instr_mem.instructions[PC /4]);
printf("
Instruction at PC: %u
", PC);
unsigned mask =(1<<31);
for (int i =31; i >=0; i--){
if (instr->instruction & mask)
printf("1");
else
printf

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!