Implement load and store of bytes, halfwords, and words
[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 def _get_shifter_mask(self, width, remainder):
15 shifter = ((self.bytes_per_word - width) - remainder) * \
16 8 # bits per byte
17 mask = (1 << (width * 8)) - 1
18 return shifter, mask
19
20 # TODO: Implement ld/st of lesser width
21 def ld(self, address, width=8):
22 remainder = address & (self.bytes_per_word - 1)
23 address = address >> self.word_log2
24 assert remainder & (width - 1) == 0, "Unaligned access unsupported!"
25 if address in self.mem:
26 val = self.mem[address]
27 else:
28 val = 0
29
30 if width != self.bytes_per_word:
31 shifter, mask = self._get_shifter_mask(width, remainder)
32 val = val & (mask << shifter)
33 val >>= shifter
34 print("Read {:x} from addr {:x}".format(val, address))
35 return val
36
37 def st(self, address, value, width=8):
38 remainder = address & (self.bytes_per_word - 1)
39 address = address >> self.word_log2
40 assert remainder & (width - 1) == 0, "Unaligned access unsupported!"
41 print("Writing {:x} to addr {:x}".format(value, address))
42 if width != self.bytes_per_word:
43 if address in self.mem:
44 val = self.mem[address]
45 else:
46 val = 0
47 shifter, mask = self._get_shifter_mask(width, remainder)
48 val &= ~(mask << shifter)
49 val |= value << shifter
50 self.mem[address] = val
51 else:
52 self.mem[address] = value
53
54
55 class RegFile:
56 def __init__(self):
57 self.regfile = [0] * 32
58 self.sprs = {}
59
60 def write_reg(self, regnum, value):
61 print("Writing {:x} to reg r{}".format(value, regnum))
62 self.regfile[regnum] = value
63
64 def read_reg(self, regnum):
65 val = self.regfile[regnum]
66 print("Read {:x} from reg r{}".format(val, regnum))
67 return val
68
69 def assert_gprs(self, gprs):
70 for k,v in list(gprs.items()):
71 reg_val = self.read_reg(k)
72 msg = "reg r{} got {:x}, expecting {:x}".format(
73 k, reg_val, v)
74 assert reg_val == v, msg
75
76
77 class InternalOpSimulator:
78 def __init__(self):
79 self.mem_sim = MemorySim()
80 self.regfile = RegFile()
81
82 def execute_alu_op(self, op1, op2, internal_op):
83 print(internal_op)
84 if internal_op == InternalOp.OP_ADD.value:
85 return op1 + op2
86 elif internal_op == InternalOp.OP_AND.value:
87 return op1 & op2
88 elif internal_op == InternalOp.OP_OR.value:
89 return op1 | op2
90 else:
91 assert False, "Not implemented"
92
93 def alu_op(self, pdecode2):
94 internal_op = yield pdecode2.dec.op.internal_op
95 operand1 = 0
96 operand2 = 0
97 result = 0
98 r1_ok = yield pdecode2.e.read_reg1.ok
99 r2_ok = yield pdecode2.e.read_reg2.ok
100 r3_ok = yield pdecode2.e.read_reg3.ok
101 imm_ok = yield pdecode2.e.imm_data.ok
102 if r1_ok:
103 r1_sel = yield pdecode2.e.read_reg1.data
104 operand1 = self.regfile.read_reg(r1_sel)
105 elif r3_ok:
106 r3_sel = yield pdecode2.e.read_reg3.data
107 operand1 = self.regfile.read_reg(r3_sel)
108 if r2_ok:
109 r2_sel = yield pdecode2.e.read_reg2.data
110 operand2 = self.regfile.read_reg(r2_sel)
111 if imm_ok:
112 operand2 = yield pdecode2.e.imm_data.data
113
114 result = self.execute_alu_op(operand1, operand2, internal_op)
115 ro_ok = yield pdecode2.e.write_reg.ok
116 if ro_ok:
117 ro_sel = yield pdecode2.e.write_reg.data
118 self.regfile.write_reg(ro_sel, result)
119
120 def mem_op(self, pdecode2):
121 internal_op = yield pdecode2.dec.op.internal_op
122 addr_reg = yield pdecode2.e.read_reg1.data
123 addr = self.regfile.read_reg(addr_reg)
124
125 imm_ok = yield pdecode2.e.imm_data.ok
126 r2_ok = yield pdecode2.e.read_reg2.ok
127 width = yield pdecode2.e.data_len
128 if imm_ok:
129 imm = yield pdecode2.e.imm_data.data
130 addr += imm
131 elif r2_ok:
132 r2_sel = yield pdecode2.e.read_reg2.data
133 addr += self.regfile.read_reg(r2_sel)
134 if internal_op == InternalOp.OP_STORE.value:
135 val_reg = yield pdecode2.e.read_reg3.data
136 val = self.regfile.read_reg(val_reg)
137 self.mem_sim.st(addr, val, width)
138 elif internal_op == InternalOp.OP_LOAD.value:
139 dest_reg = yield pdecode2.e.write_reg.data
140 val = self.mem_sim.ld(addr, width)
141 self.regfile.write_reg(dest_reg, val)
142
143
144 def execute_op(self, pdecode2):
145 function = yield pdecode2.dec.op.function_unit
146 if function == Function.ALU.value:
147 yield from self.alu_op(pdecode2)
148 elif function == Function.LDST.value:
149 yield from self.mem_op(pdecode2)