From: Michael Nolan Date: Mon, 23 Mar 2020 14:21:44 +0000 (-0400) Subject: Begin adding backend simulator X-Git-Tag: div_pipeline~1648 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ab0652a9ace9e1145a11cf64f913079ef39e6052;p=soc.git Begin adding backend simulator --- diff --git a/src/soc/simulator/internalop_sim.py b/src/soc/simulator/internalop_sim.py new file mode 100644 index 00000000..035277b4 --- /dev/null +++ b/src/soc/simulator/internalop_sim.py @@ -0,0 +1,71 @@ +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) + + +class MemorySim: + def __init__(self): + self.mem = {} + + +class RegFile: + def __init__(self): + self.regfile = [0] * 32 + self.sprs = {} + + def write_reg(self, regnum, value): + 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 + + +class InternalOpSimulator: + def __init__(self): + self.mem_sim = MemorySim() + self.regfile = RegFile() + + def execute_alu_op(self, op1, op2, internal_op): + print(internal_op) + if internal_op == InternalOp.OP_ADD.value: + return op1 + op2 + elif internal_op == InternalOp.OP_AND.value: + return op1 & op2 + else: + return 0 + + def alu_op(self, pdecode2): + internal_op = yield pdecode2.dec.op.internal_op + operand1 = 0 + operand2 = 0 + result = 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 + + result = self.execute_alu_op(operand1, operand2, internal_op) + 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 execute_op(self, pdecode2): + function = yield pdecode2.dec.op.function_unit + if function == Function.ALU.value: + yield from self.alu_op(pdecode2) diff --git a/src/soc/simulator/test_sim.py b/src/soc/simulator/test_sim.py new file mode 100644 index 00000000..d26aaf72 --- /dev/null +++ b/src/soc/simulator/test_sim.py @@ -0,0 +1,74 @@ +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.gas import get_assembled_instruction + + +class Register: + def __init__(self, num): + self.num = num + + +class InstrList: + def __init__(self, lst): + self.instrs = [x + "\n" for x in lst] + + def generate_instructions(self): + return iter(self.instrs) + + +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("instr", ins.strip()) + + # turn the instruction into binary data (endian'd) + ibin = get_assembled_instruction(ins, 0) + + # ask the decoder to decode this binary data (endian'd) + yield pdecode2.dec.bigendian.eq(0) # little / big? + yield instruction.eq(ibin) # 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"] + gen = InstrList(lst) + + simulator = InternalOpSimulator() + + self.run_tst(gen, simulator) + + +if __name__ == "__main__": + unittest.main()