From db21f520fb7a4b5b86f3bbbfa4aef793e3f51d17 Mon Sep 17 00:00:00 2001 From: Emad Jacob Maroun Date: Thu, 7 Sep 2023 11:47:11 +0200 Subject: [PATCH] Further refined the requirements on '--permissive-dual-issue' Now also cannot bundle two main-memory operations and two stack operations. --- include/instruction.h | 10 ++++ include/instructions.h | 105 ++++++++++++++++++++++++----------------- src/simulation-core.cc | 28 +++++++---- tests/CMakeLists.txt | 20 +++++++- tests/test67.s | 26 ++++++++++ tests/test68.s | 20 ++++++++ tests/test69.s | 20 ++++++++ tests/test70.s | 33 +++++++++++++ 8 files changed, 209 insertions(+), 53 deletions(-) create mode 100644 tests/test67.s create mode 100644 tests/test68.s create mode 100644 tests/test69.s create mode 100644 tests/test70.s diff --git a/include/instruction.h b/include/instruction.h index d17a6fc..f20c9eb 100644 --- a/include/instruction.h +++ b/include/instruction.h @@ -84,14 +84,24 @@ namespace patmos /// Returns true if the instruction is a flow control instruction virtual bool is_flow_control() const = 0; + /// Returns true if the instruction is a call instruction virtual bool is_call() const { return false; } + /// Returns true if the instruction is a return instruction virtual bool is_return() const { return false; } + /// Returns true if the instruction operates on the stack + virtual bool is_stack_op() const { return false; } + + /// Returns true if the instruction is a load instruction virtual bool is_load() const { return false; } + /// Returns true if the instruction is a store instruction virtual bool is_store() const { return false; } + /// Returns true if the instruction may load from or store to main memory + virtual bool is_main_mem_op() const { return false; } + /// Returns the number of delay slot cycles of this instruction virtual unsigned get_delay_slots(const instruction_data_t &ops) const = 0; diff --git a/include/instructions.h b/include/instructions.h index 76398de..a956d55 100755 --- a/include/instructions.h +++ b/include/instructions.h @@ -1490,7 +1490,7 @@ namespace patmos } }; -#define LD_INSTR(name, base, atype, ctype) \ +#define LD_INSTR(name, base, atype, ctype, is_stack, is_main_mem) \ class i_ ## name ## _t : public i_ldt_t \ { \ public:\ @@ -1502,6 +1502,8 @@ namespace patmos % ops.OPS.LDT.Rd % ops.OPS.LDT.Ra % ops.OPS.LDT.Imm; \ symbols.print(os, ops.EX_Address); \ } \ + virtual bool is_stack_op() const { return is_stack; }\ + virtual bool is_main_mem_op() const { return is_main_mem; }\ virtual void EX(simulator_t &s, instruction_data_t &ops) const \ { \ ops.EX_Address = read_GPR_EX(s, ops.DR_Rs1) + ops.OPS.LDT.Imm*sizeof(atype); \ @@ -1523,33 +1525,33 @@ namespace patmos } \ }; - LD_INSTR(lws , s.Stack_cache, word_t, word_t) - LD_INSTR(lhs , s.Stack_cache, hword_t, word_t) - LD_INSTR(lbs , s.Stack_cache, byte_t, word_t) - LD_INSTR(lwus, s.Stack_cache, uword_t, uword_t) - LD_INSTR(lhus, s.Stack_cache, uhword_t, uword_t) - LD_INSTR(lbus, s.Stack_cache, ubyte_t, uword_t) - - LD_INSTR(lwl , s.Local_memory, word_t, word_t) - LD_INSTR(lhl , s.Local_memory, hword_t, word_t) - LD_INSTR(lbl , s.Local_memory, byte_t, word_t) - LD_INSTR(lwul, s.Local_memory, uword_t, uword_t) - LD_INSTR(lhul, s.Local_memory, uhword_t, uword_t) - LD_INSTR(lbul, s.Local_memory, ubyte_t, uword_t) - - LD_INSTR(lwc , s.Data_cache, word_t, word_t) - LD_INSTR(lhc , s.Data_cache, hword_t, word_t) - LD_INSTR(lbc , s.Data_cache, byte_t, word_t) - LD_INSTR(lwuc, s.Data_cache, uword_t, uword_t) - LD_INSTR(lhuc, s.Data_cache, uhword_t, uword_t) - LD_INSTR(lbuc, s.Data_cache, ubyte_t, uword_t) - - LD_INSTR(lwm , s.Memory, word_t, word_t) - LD_INSTR(lhm , s.Memory, hword_t, word_t) - LD_INSTR(lbm , s.Memory, byte_t, word_t) - LD_INSTR(lwum, s.Memory, uword_t, uword_t) - LD_INSTR(lhum, s.Memory, uhword_t, uword_t) - LD_INSTR(lbum, s.Memory, ubyte_t, uword_t) + LD_INSTR(lws , s.Stack_cache, word_t, word_t, true, false) + LD_INSTR(lhs , s.Stack_cache, hword_t, word_t, true, false) + LD_INSTR(lbs , s.Stack_cache, byte_t, word_t, true, false) + LD_INSTR(lwus, s.Stack_cache, uword_t, uword_t, true, false) + LD_INSTR(lhus, s.Stack_cache, uhword_t, uword_t, true, false) + LD_INSTR(lbus, s.Stack_cache, ubyte_t, uword_t, true, false) + + LD_INSTR(lwl , s.Local_memory, word_t, word_t, false, false) + LD_INSTR(lhl , s.Local_memory, hword_t, word_t, false, false) + LD_INSTR(lbl , s.Local_memory, byte_t, word_t, false, false) + LD_INSTR(lwul, s.Local_memory, uword_t, uword_t, false, false) + LD_INSTR(lhul, s.Local_memory, uhword_t, uword_t, false, false) + LD_INSTR(lbul, s.Local_memory, ubyte_t, uword_t, false, false) + + LD_INSTR(lwc , s.Data_cache, word_t, word_t, false, true) + LD_INSTR(lhc , s.Data_cache, hword_t, word_t, false, true) + LD_INSTR(lbc , s.Data_cache, byte_t, word_t, false, true) + LD_INSTR(lwuc, s.Data_cache, uword_t, uword_t, false, true) + LD_INSTR(lhuc, s.Data_cache, uhword_t, uword_t, false, true) + LD_INSTR(lbuc, s.Data_cache, ubyte_t, uword_t, false, true) + + LD_INSTR(lwm , s.Memory, word_t, word_t, false, true) + LD_INSTR(lhm , s.Memory, hword_t, word_t, false, true) + LD_INSTR(lbm , s.Memory, byte_t, word_t, false, true) + LD_INSTR(lwum, s.Memory, uword_t, uword_t, false, true) + LD_INSTR(lhum, s.Memory, uhword_t, uword_t, false, true) + LD_INSTR(lbum, s.Memory, ubyte_t, uword_t, false, true) /// Base class for memory store instructions. class i_stt_t : public i_pred_t @@ -1664,7 +1666,7 @@ namespace patmos } }; -#define ST_INSTR(name, base, type) \ +#define ST_INSTR(name, base, type, is_stack, is_main_mem) \ class i_ ## name ## _t : public i_stt_t \ { \ public:\ @@ -1676,6 +1678,8 @@ namespace patmos % ops.OPS.STT.Ra % ops.OPS.STT.Imm2 % ops.OPS.STT.Rs1; \ symbols.print(os, ops.EX_Address); \ } \ + virtual bool is_stack_op() const { return is_stack; }\ + virtual bool is_main_mem_op() const { return is_main_mem; }\ virtual void EX(simulator_t &s, instruction_data_t &ops) const \ { \ ops.EX_Address = read_GPR_EX(s, ops.DR_Rs1) + ops.OPS.STT.Imm2*sizeof(type); \ @@ -1690,21 +1694,21 @@ namespace patmos } \ }; - ST_INSTR(sws, s.Stack_cache, word_t) - ST_INSTR(shs, s.Stack_cache, hword_t) - ST_INSTR(sbs, s.Stack_cache, byte_t) + ST_INSTR(sws, s.Stack_cache, word_t, true, false) + ST_INSTR(shs, s.Stack_cache, hword_t, true, false) + ST_INSTR(sbs, s.Stack_cache, byte_t, true, false) - ST_INSTR(swl, s.Local_memory, word_t) - ST_INSTR(shl, s.Local_memory, hword_t) - ST_INSTR(sbl, s.Local_memory, byte_t) + ST_INSTR(swl, s.Local_memory, word_t, false, false) + ST_INSTR(shl, s.Local_memory, hword_t, false, false) + ST_INSTR(sbl, s.Local_memory, byte_t, false, false) - ST_INSTR(swc, s.Data_cache, word_t) - ST_INSTR(shc, s.Data_cache, hword_t) - ST_INSTR(sbc, s.Data_cache, byte_t) + ST_INSTR(swc, s.Data_cache, word_t, false, true) + ST_INSTR(shc, s.Data_cache, hword_t, false, true) + ST_INSTR(sbc, s.Data_cache, byte_t, false, true) - ST_INSTR(swm, s.Memory, word_t) - ST_INSTR(shm, s.Memory, hword_t) - ST_INSTR(sbm, s.Memory, byte_t) + ST_INSTR(swm, s.Memory, word_t, false, true) + ST_INSTR(shm, s.Memory, hword_t, false, true) + ST_INSTR(sbm, s.Memory, byte_t, false, true) class i_stc_t : public i_pred_t @@ -1720,7 +1724,8 @@ namespace patmos instruction_data_t &ops) const = 0; public: - + virtual bool is_main_mem_op() const { return true; } + virtual bool is_stack_op() const { return true; } virtual void EX(simulator_t &s, instruction_data_t &ops) const { // Get the size argument @@ -2088,6 +2093,8 @@ namespace patmos } } + virtual bool is_main_mem_op() const { return true; } + virtual bool is_call() const { return true; } @@ -2167,6 +2174,8 @@ namespace patmos symbols.print(os, ops.OPS.CFLi.UImm * sizeof(word_t)); } + virtual bool is_main_mem_op() const { return true; } + virtual void EX(simulator_t &s, instruction_data_t &ops) const { ops.EX_Base = ops.OPS.CFLi.UImm*sizeof(word_t); @@ -2225,6 +2234,8 @@ namespace patmos os << "trap " << ops.OPS.CFLi.UImm; } + virtual bool is_main_mem_op() const { return true; } + virtual void DR(simulator_t &s, instruction_data_t &ops) const { ops.DR_Pred = s.PRR.get(ops.Pred).get(); @@ -2281,6 +2292,8 @@ namespace patmos symbols.print(os, ops.OPS.CFLi.UImm * sizeof(word_t)); } + virtual bool is_main_mem_op() const { return true; } + virtual void EX(simulator_t &s, instruction_data_t &ops) const { ops.EX_Address = ops.OPS.CFLi.UImm; @@ -2454,6 +2467,8 @@ namespace patmos } } + virtual bool is_main_mem_op() const { return true; } + virtual bool is_call() const { return true; } @@ -2506,6 +2521,8 @@ namespace patmos os << "brcfr" << (ops.OPS.CFLi.D ? " r" : "nd r") << ops.OPS.CFLrt.Rs1 << ", r" << ops.OPS.CFLrt.Rs2; } + virtual bool is_main_mem_op() const { return true; } + virtual void EX(simulator_t &s, instruction_data_t &ops) const { ops.EX_Base = read_GPR_EX(s, ops.DR_Rs1); @@ -2544,6 +2561,8 @@ namespace patmos class i_ret_t : public i_cflri_t { public: + virtual bool is_main_mem_op() const { return true; } + virtual bool is_return() const { return true; } /// Print the instruction to an output stream. @@ -2617,6 +2636,8 @@ namespace patmos class i_xret_t : public i_cflri_t { public: + virtual bool is_main_mem_op() const { return true; } + virtual bool is_return() const { return true; } virtual void print(std::ostream &os, const instruction_data_t &ops, diff --git a/src/simulation-core.cc b/src/simulation-core.cc index dbc58e3..4ef4327 100644 --- a/src/simulation-core.cc +++ b/src/simulation-core.cc @@ -127,7 +127,7 @@ namespace patmos debug_out << pst << " : "; } - // Check permissive instructions + // Check permissive instructions if( Use_permissive_dual_issue && f == &instruction_data_t::DR) { assert(NUM_SLOTS = 2); auto &pipe_instr0 = Pipeline[pst][0]; @@ -135,15 +135,25 @@ namespace patmos auto pred0 = PRR.get(pipe_instr0.Pred).get(); auto pred1 = PRR.get(pipe_instr1.Pred).get(); +#define is_combi(pred1, pred2) (\ + (pipe_instr0.I->pred1() && pipe_instr1.I->pred2()) || \ + (pipe_instr0.I->pred2() && pipe_instr1.I->pred1()) ) + if(pred0 && pred1) { - boost::optional err; - if((pipe_instr0.I->is_load() || pipe_instr0.I->is_store()) && - (pipe_instr1.I->is_load() || pipe_instr1.I->is_store()) - ) { - err = "load/store"; - } - if(pipe_instr0.I->is_flow_control() && pipe_instr1.I->is_flow_control()) { - err = "control flows"; + boost::optional err; + if( is_combi(is_load, is_load) || + is_combi(is_store, is_store) || + is_combi(is_store, is_load) + ){ + err = "load/store operations"; + } else if( is_combi(is_stack_op, is_stack_op) + ){ + err = "stack operations"; + } else if( is_combi(is_main_mem_op, is_main_mem_op) + ){ + err = "main-memory operations"; + } else if(pipe_instr0.I->is_flow_control() && pipe_instr1.I->is_flow_control()) { + err = "control-flow operations"; } if(err) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4bacb65..30181e8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -181,6 +181,14 @@ test_asm(64 "Errors : 0") test_asm(66 "Errors : 0") +test_asm(67 "Errors : 0") + +test_asm(68 "Errors : 0") + +test_asm(69 "Errors : 0") + +test_asm(70 "Errors : 0") + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # SIMULATOR TESTS # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @@ -385,13 +393,13 @@ test_sim(60 "\\\\\\[Error\\\\\\] Illegal instruction: c4c00008.*PC : 00000014") test_sim_arg(60 "--permissive-dual-issue" "r1 : 0000007b r2 : 000001c8 r3 : 0000009f r4 : 000002f1") -test_sim_arg(61 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled control flows.*br 8") +test_sim_arg(61 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled control-flow operations.*br 8") test_sim(62 "\\\\\\[Error\\\\\\] Illegal instruction: acc00009") test_sim_arg(62 "--permissive-dual-issue" "r1 : 0000006f.*r2 : 000000de.*r3 : 0000014d.*r4 : 000001bc.*r5 : 0000022b.*r6 : 0000029a.*r7 : 00000309.*r8 : 00000378") -test_sim_arg(63 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled control flows.*br 8") +test_sim_arg(63 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled control-flow operations.*br 8") test_sim(64 "\\\\\\[Error\\\\\\] Illegal instruction: 800801c8") @@ -399,3 +407,11 @@ test_sim_arg(64 "--permissive-dual-issue" "r3 : 0000007b.*r4 : 000001c8.*r5 : 00 test_sim_arg(66 "--permissive-dual-issue" "r1 : 000001c8.*r2 : 000000b3.*r3 : 0000007b.*r4 : 00000315.*r5 : 0000009f.*r6 : 00000000") +test_sim_arg(67 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled main-memory operations") + +test_sim_arg(68 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled main-memory operations") + +test_sim_arg(69 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled control-flow operations") + +test_sim_arg(70 "--permissive-dual-issue" "r1 : 0000007b.*r3 : 000001c8") + diff --git a/tests/test67.s b/tests/test67.s new file mode 100644 index 0000000..216209f --- /dev/null +++ b/tests/test67.s @@ -0,0 +1,26 @@ +# +# Tests main-memory store bundled with call (both enabled) +# + + .word 60; + addi r1 = r0, 123; + addi r2 = r0, dummy; + addi r3 = r0, 456; + addi r4 = r0, 0; + addi r5 = r0, 0; + callnd call_tar || swm [r2] = r3; + addi r5 = r0, 789; + halt; + nop; + nop; + nop; + + .word 20 +call_tar: + lwm r4 = [r2]; + retnd; + nop; + nop; + nop; +dummy: .word 0; + diff --git a/tests/test68.s b/tests/test68.s new file mode 100644 index 0000000..82dfaae --- /dev/null +++ b/tests/test68.s @@ -0,0 +1,20 @@ +# +# Tests load bundled with branch with cache fill (both enabled) +# + + .word 60; + addi r2 = r0, dummy; + brcf br_tar || lwc r3 = [r2]; + nop; + nop; + nop; + halt; + + .word 20 +br_tar: + halt; + nop; + nop; + nop; +dummy: .word 0; + diff --git a/tests/test69.s b/tests/test69.s new file mode 100644 index 0000000..24b9ce4 --- /dev/null +++ b/tests/test69.s @@ -0,0 +1,20 @@ +# +# Tests branch bundled with call (both enabled) +# + + .word 60; + pand p1 = p0, p0 + call br_tar || br br_tar; + nop; + nop; + nop; + halt; + + .word 20 +br_tar: + halt; + nop; + nop; + nop; +dummy: .word 0; + diff --git a/tests/test70.s b/tests/test70.s new file mode 100644 index 0000000..7f42ad8 --- /dev/null +++ b/tests/test70.s @@ -0,0 +1,33 @@ +# +# Tests stack store bundled with call (both enabled) +# + + .word 60; + addi r1 = r0, 123; + addi r2 = r0, 456; + addi r3 = r0, 0; + addi r4 = r0, stack_top; + mts ss = r4; + mts st = r4; + sres 1 + callnd call_tar || sws [0] = r2; + addi r1 = r0, 0; # If executed, clear r1 + halt; + nop; + nop; + nop; + + .word 20 +call_tar: + lws r3 = [0]; + halt; + nop; + nop; + nop; +stack_top: + .word 0; + .word 0; + .word 0; + .word 0; + .word 0; +