+++ /dev/null
-from soc.decoder.power_enums import (Function, Form, InternalOp,
- In1Sel, In2Sel, In3Sel, OutSel,
- RC, LdstLen, CryIn, get_csv,
- single_bit_flags,
- get_signal_name, default_values)
-import math
-
-
-class MemorySim:
- def __init__(self, bytes_per_word=8):
- self.mem = {}
- self.bytes_per_word = bytes_per_word
- self.word_log2 = math.ceil(math.log2(bytes_per_word))
-
- def _get_shifter_mask(self, width, remainder):
- shifter = ((self.bytes_per_word - width) - remainder) * \
- 8 # bits per byte
- mask = (1 << (width * 8)) - 1
- return shifter, mask
-
- # TODO: Implement ld/st of lesser width
- def ld(self, address, width=8):
- remainder = address & (self.bytes_per_word - 1)
- address = address >> self.word_log2
- assert remainder & (width - 1) == 0, "Unaligned access unsupported!"
- if address in self.mem:
- val = self.mem[address]
- else:
- val = 0
-
- if width != self.bytes_per_word:
- shifter, mask = self._get_shifter_mask(width, remainder)
- val = val & (mask << shifter)
- val >>= shifter
- print("Read {:x} from addr {:x}".format(val, address))
- return val
-
- def st(self, address, value, width=8):
- remainder = address & (self.bytes_per_word - 1)
- address = address >> self.word_log2
- assert remainder & (width - 1) == 0, "Unaligned access unsupported!"
- print("Writing {:x} to addr {:x}".format(value, address))
- if width != self.bytes_per_word:
- if address in self.mem:
- val = self.mem[address]
- else:
- val = 0
- shifter, mask = self._get_shifter_mask(width, remainder)
- val &= ~(mask << shifter)
- val |= value << shifter
- self.mem[address] = val
- else:
- self.mem[address] = value
-
-
-class RegFile:
- def __init__(self):
- self.regfile = [0] * 32
- self.sprs = {}
-
- def write_reg(self, regnum, value):
- all1s = (1 << 64)-1 # 64 bits worth of 1s
- value &= all1s
- print("Writing {:x} to reg r{}".format(value, regnum))
- self.regfile[regnum] = value
-
- def read_reg(self, regnum):
- val = self.regfile[regnum]
- print("Read {:x} from reg r{}".format(val, regnum))
- return val
-
- def assert_gpr(self, gpr, val):
- reg_val = self.read_reg(gpr)
- msg = "reg r{} got {:x}, expecting {:x}".format(
- gpr, reg_val, val)
- assert reg_val == val, msg
-
- def assert_gprs(self, gprs):
- for k, v in list(gprs.items()):
- self.assert_gpr(k, v)
-
- def set_xer(self, result, operanda, operandb):
- xer = 0
- if result & 1 << 64:
- xer |= XER.CA
-
- self.xer = xer
-
-
-class InternalOpSimulator:
- def __init__(self):
- self.mem_sim = MemorySim()
- self.regfile = RegFile()
-
- def execute_alu_op(self, op1, op2, internal_op, carry=0):
- print(internal_op)
- if internal_op == InternalOp.OP_ADD.value:
- return op1 + op2 + carry
- elif internal_op == InternalOp.OP_AND.value:
- return op1 & op2
- elif internal_op == InternalOp.OP_OR.value:
- return op1 | op2
- elif internal_op == InternalOp.OP_MUL_L64.value:
- return op1 * op2
- else:
- assert False, "Not implemented"
-
- def update_cr0(self, result):
- if result == 0:
- self.cr0 = 0b001
- elif result >> 63:
- self.cr0 = 0b100
- else:
- self.cr0 = 0b010
- print("update_cr0", self.cr0)
-
- def alu_op(self, pdecode2):
- all1s = (1 << 64)-1 # 64 bits worth of 1s
- internal_op = yield pdecode2.dec.op.internal_op
- operand1 = 0
- operand2 = 0
- result = 0
- carry = 0
- r1_ok = yield pdecode2.e.read_reg1.ok
- r2_ok = yield pdecode2.e.read_reg2.ok
- r3_ok = yield pdecode2.e.read_reg3.ok
- imm_ok = yield pdecode2.e.imm_data.ok
- if r1_ok:
- r1_sel = yield pdecode2.e.read_reg1.data
- operand1 = self.regfile.read_reg(r1_sel)
- elif r3_ok:
- r3_sel = yield pdecode2.e.read_reg3.data
- operand1 = self.regfile.read_reg(r3_sel)
- if r2_ok:
- r2_sel = yield pdecode2.e.read_reg2.data
- operand2 = self.regfile.read_reg(r2_sel)
- if imm_ok:
- operand2 = yield pdecode2.e.imm_data.data
-
- inv_a = yield pdecode2.dec.op.inv_a
- if inv_a:
- operand1 = (~operand1) & all1s
-
- cry_in = yield pdecode2.dec.op.cry_in
- if cry_in == CryIn.ONE.value:
- carry = 1
- elif cry_in == CryIn.CA.value:
- carry = self.carry_out
-
- # TODO rc_sel = yield pdecode2.dec.op.rc_sel
- result = self.execute_alu_op(operand1, operand2, internal_op,
- carry=carry)
-
- cry_out = yield pdecode2.dec.op.cry_out
- rc = yield pdecode2.e.rc.data
-
- if rc:
- self.update_cr0(result)
- if cry_out == 1:
- self.carry_out = (result >> 64)
- print("setting carry_out", self.carry_out)
-
- ro_ok = yield pdecode2.e.write_reg.ok
- if ro_ok:
- ro_sel = yield pdecode2.e.write_reg.data
- self.regfile.write_reg(ro_sel, result)
-
- def mem_op(self, pdecode2):
- internal_op = yield pdecode2.dec.op.internal_op
- addr_reg = yield pdecode2.e.read_reg1.data
- addr = self.regfile.read_reg(addr_reg)
-
- imm_ok = yield pdecode2.e.imm_data.ok
- r2_ok = yield pdecode2.e.read_reg2.ok
- width = yield pdecode2.e.data_len
- if imm_ok:
- imm = yield pdecode2.e.imm_data.data
- addr += imm
- elif r2_ok:
- r2_sel = yield pdecode2.e.read_reg2.data
- addr += self.regfile.read_reg(r2_sel)
- if internal_op == InternalOp.OP_STORE.value:
- val_reg = yield pdecode2.e.read_reg3.data
- val = self.regfile.read_reg(val_reg)
- self.mem_sim.st(addr, val, width)
- elif internal_op == InternalOp.OP_LOAD.value:
- dest_reg = yield pdecode2.e.write_reg.data
- val = self.mem_sim.ld(addr, width)
- self.regfile.write_reg(dest_reg, val)
-
- def execute_op(self, pdecode2):
- function = yield pdecode2.dec.op.function_unit
- if function == Function.ALU.value:
- yield from self.alu_op(pdecode2)
- elif function == Function.LDST.value:
- yield from self.mem_op(pdecode2)
+++ /dev/null
-from nmigen import Module, Signal
-from nmigen.back.pysim import Simulator, Delay
-from nmigen.test.utils import FHDLTestCase
-import unittest
-from soc.simulator.internalop_sim import InternalOpSimulator
-from soc.decoder.power_decoder import (create_pdecode)
-from soc.decoder.power_enums import (Function, InternalOp,
- In1Sel, In2Sel, In3Sel,
- OutSel, RC, LdstLen, CryIn,
- single_bit_flags, Form, SPR,
- get_signal_name, get_csv)
-from soc.decoder.power_decoder2 import (PowerDecode2)
-from soc.simulator.program import Program
-from soc.simulator.qemu import run_program
-
-
-class Register:
- def __init__(self, num):
- self.num = num
-
-
-class DecoderTestCase(FHDLTestCase):
-
- def run_tst(self, generator, simulator):
- m = Module()
- comb = m.d.comb
- instruction = Signal(32)
-
- pdecode = create_pdecode()
-
- m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
- comb += pdecode2.dec.raw_opcode_in.eq(instruction)
- sim = Simulator(m)
- gen = generator.generate_instructions()
-
- def process():
- for ins in gen:
-
- print("0x{:X}".format(ins & 0xffffffff))
-
- # ask the decoder to decode this binary data (endian'd)
- yield pdecode2.dec.bigendian.eq(0) # little / big?
- yield instruction.eq(ins) # raw binary instr.
- yield Delay(1e-6)
- yield from simulator.execute_op(pdecode2)
-
- sim.add_process(process)
- with sim.write_vcd("simulator.vcd", "simulator.gtkw",
- traces=pdecode2.ports()):
- sim.run()
-
- def test_example(self):
- lst = ["addi 1, 0, 0x1234",
- "addi 2, 0, 0x5678",
- "add 3, 1, 2",
- "and 4, 1, 2"]
- with Program(lst) as program:
- self.run_tst_program(program, [1, 2, 3, 4])
-
- def test_ldst(self):
- lst = ["addi 1, 0, 0x1234",
- "addi 2, 0, 0x5678",
- "stw 1, 0(2)",
- "lwz 3, 0(2)"]
- with Program(lst) as program:
- self.run_tst_program(program, [1, 2, 3])
-
- def test_ldst_extended(self):
- lst = ["addi 1, 0, 0x1234",
- "addi 2, 0, 0x5678",
- "addi 4, 0, 0x40",
- "stw 1, 0x40(2)",
- "lwzx 3, 4, 2"]
- with Program(lst) as program:
- self.run_tst_program(program, [1, 2, 3])
-
- def test_ldst_widths(self):
- lst = [" lis 1, 0xdead",
- "ori 1, 1, 0xbeef",
- "addi 2, 0, 0x1000",
- "std 1, 0(2)",
- "lbz 1, 5(2)",
- "lhz 3, 4(2)",
- "lwz 4, 4(2)",
- "addi 5, 0, 0x12",
- "stb 5, 5(2)",
- "ld 5, 0(2)"]
- with Program(lst) as program:
- self.run_tst_program(program, [1, 2, 3, 4, 5])
-
- def test_sub(self):
- lst = ["addi 1, 0, 0x1234",
- "addi 2, 0, 0x5678",
- "subf 3, 1, 2",
- "subfic 4, 1, 0x1337",
- "neg 5, 1"]
- with Program(lst) as program:
- self.run_tst_program(program, [1, 2, 3, 4, 5])
-
- def test_add_with_carry(self):
- lst = ["addi 1, 0, 5",
- "neg 1, 1",
- "addi 2, 0, 7",
- "neg 2, 2",
- "addc 3, 2, 1",
- "addi 3, 3, 1"
- ]
- with Program(lst) as program:
- self.run_tst_program(program, [1, 2, 3])
-
- def test_addis(self):
- lst = ["addi 1, 0, 0x0FFF",
- "addis 1, 1, 0x0F"
- ]
- with Program(lst) as program:
- self.run_tst_program(program, [1])
-
- def test_mulli(self):
- lst = ["addi 1, 0, 3",
- "mulli 1, 1, 2"
- ]
- with Program(lst) as program:
- self.run_tst_program(program, [1])
-
- def run_tst_program(self, prog, reglist):
- simulator = InternalOpSimulator()
- self.run_tst(prog, simulator)
- prog.reset()
- with run_program(prog) as q:
- qemu_register_compare(simulator, q, reglist)
-
-
-def qemu_register_compare(simulator, qemu, regs):
- for reg in regs:
- qemu_val = qemu.get_register(reg)
- simulator.regfile.assert_gpr(reg, qemu_val)
-
-
-if __name__ == "__main__":
- unittest.main()
--- /dev/null
+from soc.decoder.power_enums import (Function, Form, InternalOp,
+ In1Sel, In2Sel, In3Sel, OutSel,
+ RC, LdstLen, CryIn, get_csv,
+ single_bit_flags,
+ get_signal_name, default_values)
+import math
+
+
+class MemorySim:
+ def __init__(self, bytes_per_word=8):
+ self.mem = {}
+ self.bytes_per_word = bytes_per_word
+ self.word_log2 = math.ceil(math.log2(bytes_per_word))
+
+ def _get_shifter_mask(self, width, remainder):
+ shifter = ((self.bytes_per_word - width) - remainder) * \
+ 8 # bits per byte
+ mask = (1 << (width * 8)) - 1
+ return shifter, mask
+
+ # TODO: Implement ld/st of lesser width
+ def ld(self, address, width=8):
+ remainder = address & (self.bytes_per_word - 1)
+ address = address >> self.word_log2
+ assert remainder & (width - 1) == 0, "Unaligned access unsupported!"
+ if address in self.mem:
+ val = self.mem[address]
+ else:
+ val = 0
+
+ if width != self.bytes_per_word:
+ shifter, mask = self._get_shifter_mask(width, remainder)
+ val = val & (mask << shifter)
+ val >>= shifter
+ print("Read {:x} from addr {:x}".format(val, address))
+ return val
+
+ def st(self, address, value, width=8):
+ remainder = address & (self.bytes_per_word - 1)
+ address = address >> self.word_log2
+ assert remainder & (width - 1) == 0, "Unaligned access unsupported!"
+ print("Writing {:x} to addr {:x}".format(value, address))
+ if width != self.bytes_per_word:
+ if address in self.mem:
+ val = self.mem[address]
+ else:
+ val = 0
+ shifter, mask = self._get_shifter_mask(width, remainder)
+ val &= ~(mask << shifter)
+ val |= value << shifter
+ self.mem[address] = val
+ else:
+ self.mem[address] = value
+
+
+class RegFile:
+ def __init__(self):
+ self.regfile = [0] * 32
+ self.sprs = {}
+
+ def write_reg(self, regnum, value):
+ all1s = (1 << 64)-1 # 64 bits worth of 1s
+ value &= all1s
+ print("Writing {:x} to reg r{}".format(value, regnum))
+ self.regfile[regnum] = value
+
+ def read_reg(self, regnum):
+ val = self.regfile[regnum]
+ print("Read {:x} from reg r{}".format(val, regnum))
+ return val
+
+ def assert_gpr(self, gpr, val):
+ reg_val = self.read_reg(gpr)
+ msg = "reg r{} got {:x}, expecting {:x}".format(
+ gpr, reg_val, val)
+ assert reg_val == val, msg
+
+ def assert_gprs(self, gprs):
+ for k, v in list(gprs.items()):
+ self.assert_gpr(k, v)
+
+ def set_xer(self, result, operanda, operandb):
+ xer = 0
+ if result & 1 << 64:
+ xer |= XER.CA
+
+ self.xer = xer
+
+
+class InternalOpSimulator:
+ def __init__(self):
+ self.mem_sim = MemorySim()
+ self.regfile = RegFile()
+
+ def execute_alu_op(self, op1, op2, internal_op, carry=0):
+ print(internal_op)
+ if internal_op == InternalOp.OP_ADD.value:
+ return op1 + op2 + carry
+ elif internal_op == InternalOp.OP_AND.value:
+ return op1 & op2
+ elif internal_op == InternalOp.OP_OR.value:
+ return op1 | op2
+ elif internal_op == InternalOp.OP_MUL_L64.value:
+ return op1 * op2
+ else:
+ assert False, "Not implemented"
+
+ def update_cr0(self, result):
+ if result == 0:
+ self.cr0 = 0b001
+ elif result >> 63:
+ self.cr0 = 0b100
+ else:
+ self.cr0 = 0b010
+ print("update_cr0", self.cr0)
+
+ def alu_op(self, pdecode2):
+ all1s = (1 << 64)-1 # 64 bits worth of 1s
+ internal_op = yield pdecode2.dec.op.internal_op
+ operand1 = 0
+ operand2 = 0
+ result = 0
+ carry = 0
+ r1_ok = yield pdecode2.e.read_reg1.ok
+ r2_ok = yield pdecode2.e.read_reg2.ok
+ r3_ok = yield pdecode2.e.read_reg3.ok
+ imm_ok = yield pdecode2.e.imm_data.ok
+ if r1_ok:
+ r1_sel = yield pdecode2.e.read_reg1.data
+ operand1 = self.regfile.read_reg(r1_sel)
+ elif r3_ok:
+ r3_sel = yield pdecode2.e.read_reg3.data
+ operand1 = self.regfile.read_reg(r3_sel)
+ if r2_ok:
+ r2_sel = yield pdecode2.e.read_reg2.data
+ operand2 = self.regfile.read_reg(r2_sel)
+ if imm_ok:
+ operand2 = yield pdecode2.e.imm_data.data
+
+ inv_a = yield pdecode2.dec.op.inv_a
+ if inv_a:
+ operand1 = (~operand1) & all1s
+
+ cry_in = yield pdecode2.dec.op.cry_in
+ if cry_in == CryIn.ONE.value:
+ carry = 1
+ elif cry_in == CryIn.CA.value:
+ carry = self.carry_out
+
+ # TODO rc_sel = yield pdecode2.dec.op.rc_sel
+ result = self.execute_alu_op(operand1, operand2, internal_op,
+ carry=carry)
+
+ cry_out = yield pdecode2.dec.op.cry_out
+ rc = yield pdecode2.e.rc.data
+
+ if rc:
+ self.update_cr0(result)
+ if cry_out == 1:
+ self.carry_out = (result >> 64)
+ print("setting carry_out", self.carry_out)
+
+ ro_ok = yield pdecode2.e.write_reg.ok
+ if ro_ok:
+ ro_sel = yield pdecode2.e.write_reg.data
+ self.regfile.write_reg(ro_sel, result)
+
+ def mem_op(self, pdecode2):
+ internal_op = yield pdecode2.dec.op.internal_op
+ addr_reg = yield pdecode2.e.read_reg1.data
+ addr = self.regfile.read_reg(addr_reg)
+
+ imm_ok = yield pdecode2.e.imm_data.ok
+ r2_ok = yield pdecode2.e.read_reg2.ok
+ width = yield pdecode2.e.data_len
+ if imm_ok:
+ imm = yield pdecode2.e.imm_data.data
+ addr += imm
+ elif r2_ok:
+ r2_sel = yield pdecode2.e.read_reg2.data
+ addr += self.regfile.read_reg(r2_sel)
+ if internal_op == InternalOp.OP_STORE.value:
+ val_reg = yield pdecode2.e.read_reg3.data
+ val = self.regfile.read_reg(val_reg)
+ self.mem_sim.st(addr, val, width)
+ elif internal_op == InternalOp.OP_LOAD.value:
+ dest_reg = yield pdecode2.e.write_reg.data
+ val = self.mem_sim.ld(addr, width)
+ self.regfile.write_reg(dest_reg, val)
+
+ def execute_op(self, pdecode2):
+ function = yield pdecode2.dec.op.function_unit
+ if function == Function.ALU.value:
+ yield from self.alu_op(pdecode2)
+ elif function == Function.LDST.value:
+ yield from self.mem_op(pdecode2)
--- /dev/null
+from nmigen import Module, Signal
+from nmigen.back.pysim import Simulator, Delay
+from nmigen.test.utils import FHDLTestCase
+import unittest
+from soc.simulator.internalop_sim import InternalOpSimulator
+from soc.decoder.power_decoder import (create_pdecode)
+from soc.decoder.power_enums import (Function, InternalOp,
+ In1Sel, In2Sel, In3Sel,
+ OutSel, RC, LdstLen, CryIn,
+ single_bit_flags, Form, SPR,
+ get_signal_name, get_csv)
+from soc.decoder.power_decoder2 import (PowerDecode2)
+from soc.simulator.program import Program
+from soc.simulator.qemu import run_program
+
+
+class Register:
+ def __init__(self, num):
+ self.num = num
+
+
+class DecoderTestCase(FHDLTestCase):
+
+ def run_tst(self, generator, simulator):
+ m = Module()
+ comb = m.d.comb
+ instruction = Signal(32)
+
+ pdecode = create_pdecode()
+
+ m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
+ comb += pdecode2.dec.raw_opcode_in.eq(instruction)
+ sim = Simulator(m)
+ gen = generator.generate_instructions()
+
+ def process():
+ for ins in gen:
+
+ print("0x{:X}".format(ins & 0xffffffff))
+
+ # ask the decoder to decode this binary data (endian'd)
+ yield pdecode2.dec.bigendian.eq(0) # little / big?
+ yield instruction.eq(ins) # raw binary instr.
+ yield Delay(1e-6)
+ yield from simulator.execute_op(pdecode2)
+
+ sim.add_process(process)
+ with sim.write_vcd("simulator.vcd", "simulator.gtkw",
+ traces=pdecode2.ports()):
+ sim.run()
+
+ def test_example(self):
+ lst = ["addi 1, 0, 0x1234",
+ "addi 2, 0, 0x5678",
+ "add 3, 1, 2",
+ "and 4, 1, 2"]
+ with Program(lst) as program:
+ self.run_tst_program(program, [1, 2, 3, 4])
+
+ def test_ldst(self):
+ lst = ["addi 1, 0, 0x1234",
+ "addi 2, 0, 0x5678",
+ "stw 1, 0(2)",
+ "lwz 3, 0(2)"]
+ with Program(lst) as program:
+ self.run_tst_program(program, [1, 2, 3])
+
+ def test_ldst_extended(self):
+ lst = ["addi 1, 0, 0x1234",
+ "addi 2, 0, 0x5678",
+ "addi 4, 0, 0x40",
+ "stw 1, 0x40(2)",
+ "lwzx 3, 4, 2"]
+ with Program(lst) as program:
+ self.run_tst_program(program, [1, 2, 3])
+
+ def test_ldst_widths(self):
+ lst = [" lis 1, 0xdead",
+ "ori 1, 1, 0xbeef",
+ "addi 2, 0, 0x1000",
+ "std 1, 0(2)",
+ "lbz 1, 5(2)",
+ "lhz 3, 4(2)",
+ "lwz 4, 4(2)",
+ "addi 5, 0, 0x12",
+ "stb 5, 5(2)",
+ "ld 5, 0(2)"]
+ with Program(lst) as program:
+ self.run_tst_program(program, [1, 2, 3, 4, 5])
+
+ def test_sub(self):
+ lst = ["addi 1, 0, 0x1234",
+ "addi 2, 0, 0x5678",
+ "subf 3, 1, 2",
+ "subfic 4, 1, 0x1337",
+ "neg 5, 1"]
+ with Program(lst) as program:
+ self.run_tst_program(program, [1, 2, 3, 4, 5])
+
+ def test_add_with_carry(self):
+ lst = ["addi 1, 0, 5",
+ "neg 1, 1",
+ "addi 2, 0, 7",
+ "neg 2, 2",
+ "addc 3, 2, 1",
+ "addi 3, 3, 1"
+ ]
+ with Program(lst) as program:
+ self.run_tst_program(program, [1, 2, 3])
+
+ def test_addis(self):
+ lst = ["addi 1, 0, 0x0FFF",
+ "addis 1, 1, 0x0F"
+ ]
+ with Program(lst) as program:
+ self.run_tst_program(program, [1])
+
+ def test_mulli(self):
+ lst = ["addi 1, 0, 3",
+ "mulli 1, 1, 2"
+ ]
+ with Program(lst) as program:
+ self.run_tst_program(program, [1])
+
+ def run_tst_program(self, prog, reglist):
+ simulator = InternalOpSimulator()
+ self.run_tst(prog, simulator)
+ prog.reset()
+ with run_program(prog) as q:
+ qemu_register_compare(simulator, q, reglist)
+
+
+def qemu_register_compare(simulator, qemu, regs):
+ for reg in regs:
+ qemu_val = qemu.get_register(reg)
+ simulator.regfile.assert_gpr(reg, qemu_val)
+
+
+if __name__ == "__main__":
+ unittest.main()