Add support for extended/indexed ld/st
[soc.git] / src / soc / simulator / internalop_sim.py
1 from soc.decoder.power_enums import (Function, Form, InternalOp,
2 In1Sel, In2Sel, In3Sel, OutSel, RC, LdstLen,
3 CryIn, get_csv, single_bit_flags,
4 get_signal_name, default_values)
5 import math
6
7
8 class MemorySim:
9 def __init__(self, bytes_per_word=8):
10 self.mem = {}
11 self.bytes_per_word = bytes_per_word
12 self.word_log2 = math.ceil(math.log2(bytes_per_word))
13
14 # TODO: Implement ld/st of lesser width
15 def ld(self, address):
16 address = address >> self.word_log2
17 if address in self.mem:
18 val = self.mem[address]
19 else:
20 val = 0
21 print("Read {:x} from addr {:x}".format(val, address))
22 return val
23
24 def st(self, address, value):
25 address = address >> self.word_log2
26 print("Writing {:x} to addr {:x}".format(value, address))
27 self.mem[address] = value
28
29
30 class RegFile:
31 def __init__(self):
32 self.regfile = [0] * 32
33 self.sprs = {}
34
35 def write_reg(self, regnum, value):
36 print("Writing {:x} to reg r{}".format(value, regnum))
37 self.regfile[regnum] = value
38
39 def read_reg(self, regnum):
40 val = self.regfile[regnum]
41 print("Read {:x} from reg r{}".format(val, regnum))
42 return val
43
44 def assert_gprs(self, gprs):
45 for k,v in list(gprs.items()):
46 reg_val = self.read_reg(k)
47 msg = "reg r{} got {:x}, expecting {:x}".format(
48 k, reg_val, v)
49 assert reg_val == v, msg
50
51
52 class InternalOpSimulator:
53 def __init__(self):
54 self.mem_sim = MemorySim()
55 self.regfile = RegFile()
56
57 def execute_alu_op(self, op1, op2, internal_op):
58 print(internal_op)
59 if internal_op == InternalOp.OP_ADD.value:
60 return op1 + op2
61 elif internal_op == InternalOp.OP_AND.value:
62 return op1 & op2
63 else:
64 assert(False, "Not implemented")
65
66 def alu_op(self, pdecode2):
67 internal_op = yield pdecode2.dec.op.internal_op
68 operand1 = 0
69 operand2 = 0
70 result = 0
71 r1_ok = yield pdecode2.e.read_reg1.ok
72 r2_ok = yield pdecode2.e.read_reg2.ok
73 r3_ok = yield pdecode2.e.read_reg3.ok
74 imm_ok = yield pdecode2.e.imm_data.ok
75 if r1_ok:
76 r1_sel = yield pdecode2.e.read_reg1.data
77 operand1 = self.regfile.read_reg(r1_sel)
78 elif r3_ok:
79 r3_sel = yield pdecode2.e.read_reg3.data
80 operand1 = self.regfile.read_reg(r3_sel)
81 if r2_ok:
82 r2_sel = yield pdecode2.e.read_reg2.data
83 operand2 = self.regfile.read_reg(r2_sel)
84 if imm_ok:
85 operand2 = yield pdecode2.e.imm_data.data
86
87 result = self.execute_alu_op(operand1, operand2, internal_op)
88 ro_ok = yield pdecode2.e.write_reg.ok
89 if ro_ok:
90 ro_sel = yield pdecode2.e.write_reg.data
91 self.regfile.write_reg(ro_sel, result)
92
93 def mem_op(self, pdecode2):
94 internal_op = yield pdecode2.dec.op.internal_op
95 addr_reg = yield pdecode2.e.read_reg1.data
96 addr = self.regfile.read_reg(addr_reg)
97
98 imm_ok = yield pdecode2.e.imm_data.ok
99 r2_ok = yield pdecode2.e.read_reg2.ok
100 if imm_ok:
101 imm = yield pdecode2.e.imm_data.data
102 addr += imm
103 elif r2_ok:
104 r2_sel = yield pdecode2.e.read_reg2.data
105 addr += self.regfile.read_reg(r2_sel)
106 if internal_op == InternalOp.OP_STORE.value:
107 val_reg = yield pdecode2.e.read_reg3.data
108 val = self.regfile.read_reg(val_reg)
109 self.mem_sim.st(addr, val)
110 elif internal_op == InternalOp.OP_LOAD.value:
111 dest_reg = yield pdecode2.e.write_reg.data
112 val = self.mem_sim.ld(addr)
113 self.regfile.write_reg(dest_reg, val)
114
115
116 def execute_op(self, pdecode2):
117 function = yield pdecode2.dec.op.function_unit
118 if function == Function.ALU.value:
119 yield from self.alu_op(pdecode2)
120 elif function == Function.LDST.value:
121 yield from self.mem_op(pdecode2)