Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

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

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

C++ Database Development

Authors: Al Stevens

1st Edition

1558283579, 978-1558283572

More Books

Students also viewed these Databases questions

Question

Draw a labelled diagram of the Dicot stem.

Answered: 1 week ago

Question

Group Size and Communication

Answered: 1 week ago

Question

Understanding Group Roles

Answered: 1 week ago