Logisim Memory File generation using yo file
This section describes how to create logisim memory file out of .yo file. Let’s suppose we have Y86-64 SEQ processor implemented with the logisim tool. Then, how can you run test programs? In real computer system, we usually write a program with high level programming language such as C/C++ and compile it to make an executable file. Then, operating system loads the executable to the main memory and the processor starts program execution.
Since we focus on the processor design so we simplify the above processes.
1. Overall Steps
.ys --yas--> .yo --yo2mem--> .mem
Specifically, we rely on yas which is Y86-64 assembler. yas takes assembly code (.ys) as an input and outputs a memory file .yo that contains both machine code and data.
However, Y86-64 SEQ implemented with logisim tool cannot directly understand yo file.
Therefore, we are supposed to make a convertor from .yo to something that logisim can understand.
2. .yo file format
| # Execution begins at address 0
0x000: | .pos 0
0x000: 30f40002000000000000 | irmovq stack, %rsp # Set up stack pointer
0x00a: 803800000000000000 | call main # Execute main program
0x013: 00 | halt # Terminate program
|
| # Array of 4 elements
0x018: | .align 8
0x018: 0d000d000d000000 | array: .quad 0x000d000d000d
0x020: c000c000c0000000 | .quad 0x00c000c000c0
0x028: 000b000b000b0000 | .quad 0x0b000b000b00
0x030: 00a000a000a00000 | .quad 0xa000a000a000
|
0x038: 30f71800000000000000 | main: irmovq array,%rdi
0x042: 30f60400000000000000 | irmovq $4,%rsi
0x04c: 805600000000000000 | call sum # sum(array, 4)
0x055: 90 | ret
|
| # long sum(long *start, long count)
| # start in %rdi, count in %rsi
0x056: 30f80800000000000000 | sum: irmovq $8,%r8 # Constant 8
0x060: 30f90100000000000000 | irmovq $1,%r9 # Constant 1
0x06a: 6300 | xorq %rax,%rax # sum = 0
0x06c: 6266 | andq %rsi,%rsi # Set CC
0x06e: 708700000000000000 | jmp test # Goto test
0x077: 50a70000000000000000 | loop: mrmovq (%rdi),%r10 # Get *start
0x081: 60a0 | addq %r10,%rax # Add to sum
0x083: 6087 | addq %r8,%rdi # start++
0x085: 6196 | subq %r9,%rsi # count--. Set CC
0x087: 747700000000000000 | test: jne loop # Stop when 0
0x090: 90 | ret # Return
|
| # Stack starts here and grows to lower addresses
0x200: | .pos 0x200
0x200: | stack:
`.yo file includes memmory contents followed by its corresponding assembly code in the input .ys file.
In memory contents, it starts with start memory address followed by machine code or data. We just need memory contents for the logisim memory file.
3. Logisim Memory File
Logisim has its own file format that represents the content of memory. There are some versions of the memory file.
If you are interested in logisim’s memory file format in detail, please refer to the logisim reference.
In our term project, we are stick to use v3.0 hex words addressed.
4. YO2MEM pytyon script
1 import sys
2 import argparse
3
4 def parse(line):
5 data = line.split('|')[0].strip()
6 if ':' not in data:
7 return None, None
8
9 addr = data.split(':')[0].strip()[2:]
10 data = data.split(':')[1].strip()
11
12 if len(data) == 0:
13 return None, None
14
15 assert(len(data) % 2 == 0)
16 num_bytes = int(len(data) / 2)
17
18 data_split = ''
19 for offset in range(num_bytes):
20 #print('offset: %d, idx: %d' % (offset, offset*2))
21 data_split += data[offset*2:offset*2+2] + ' '
22 return addr, data_split[:-1]
23
24 def add(memory, addr, data):
25 #assert(len(data) % 2 == 0)
26 addr = int(addr, 16)
27 memory[addr] = data
28
29 def translate(yo, mem):
30 #print("yo: %s, mem: %s" % (yo, mem))
31 memory = []
32 with open(yo, 'r') as f:
33 for line in f:
34 addr, data = parse(line)
35 if addr is not None:
36 #print('addr: %s data: %s(%d)' % (addr, data, len(data)))
37 memory.append((addr, data))
38
39 f = open(mem, 'w')
40 f.write('v3.0 hex words addressed\n')
41 for addr, data in memory:
42 f.write('%s: %s\n' % (addr, data))
43 f.close()
44 print("Translated %s file to memory file logisim-evolution. Find %s." % (yo, mem))
45
46 def main():
47 parser = argparse.ArgumentParser(
48 prog="yo2mem",
49 description="y86-64 object file to logisim-evolution memory file translator",
50 formatter_class=argparse.ArgumentDefaultsHelpFormatter
51 )
52 parser.set_defaults(func=lambda x: parser.print_help())
53 parser.add_argument('yo', action='store', type=str, help="input yo file")
54 parser.add_argument('mem', action='store', type=str, help="output memory file")
55
56 args = parser.parse_args(sys.argv[1:])
57 translate(args.yo, args.mem)
58
59 if __name__ == "__main__":
60 sys.exit(main())
This pythone script take two command line arguments as follows:
❯ python yo2mem -h
usage: yo2mem [-h] yo mem
y86-64 object file to logisim-evolution memory file translator
positional arguments:
yo input yo file
mem output memory file
optional arguments:
-h, --help show this help message and exit
The generated memory file will be used for both instruction and data memory.
v3.0 hex words addressed
000: 30 f4 00 02 00 00 00 00 00 00
00a: 80 38 00 00 00 00 00 00 00
013: 00
018: 0d 00 0d 00 0d 00 00 00
020: c0 00 c0 00 c0 00 00 00
028: 00 0b 00 0b 00 0b 00 00
030: 00 a0 00 a0 00 a0 00 00
038: 30 f7 18 00 00 00 00 00 00 00
042: 30 f6 04 00 00 00 00 00 00 00
04c: 80 56 00 00 00 00 00 00 00
055: 90
056: 30 f8 08 00 00 00 00 00 00 00
060: 30 f9 01 00 00 00 00 00 00 00
06a: 63 00
06c: 62 66
06e: 70 87 00 00 00 00 00 00 00
077: 50 a7 00 00 00 00 00 00 00 00
081: 60 a0
083: 60 87
085: 61 96
087: 74 77 00 00 00 00 00 00 00
090: 90