From 81d8401ac4444b5782426aeee886961f56603994 Mon Sep 17 00:00:00 2001 From: Emad Jacob Maroun Date: Mon, 28 Aug 2023 17:01:00 +0200 Subject: [PATCH 01/10] Added '--permissive-dual-issue' It enables instructions that otherwise aren't allowed in the second issue slot to be allowed. The only restriction is that only one of each type is allowed to be enabled at a time. --- include/binary-format.h | 19 +++++++++++++++---- include/decoder.h | 7 ++++++- include/simulation-core.h | 9 ++++++++- src/binary-formats.cc | 2 +- src/decoder.cc | 6 +++--- src/pacheck.cc | 2 +- src/padasm.cc | 4 ++-- src/pasim.cc | 7 +++++-- src/simulation-core.cc | 16 ++++++++++++++-- tests/CMakeLists.txt | 17 +++++++++++++++++ tests/test55.s | 18 ++++++++++++++++++ tests/test56.s | 17 +++++++++++++++++ 12 files changed, 107 insertions(+), 17 deletions(-) create mode 100644 tests/test55.s create mode 100644 tests/test56.s diff --git a/include/binary-format.h b/include/binary-format.h index 21d3669..fc929f6 100644 --- a/include/binary-format.h +++ b/include/binary-format.h @@ -72,6 +72,10 @@ namespace patmos /// instruction. const unsigned int Slots; + /// A bit mask indicating the valid slots, within a bundle, for the + /// instruction when "permissive-dual-issue" is enabled. + unsigned int Permissive_slots; + /// Indicate whether the instruction assumes a long immediate field in the /// second slot of the instruction bundle (exclusively for the ALUl format). bool Is_long; @@ -83,14 +87,21 @@ namespace patmos /// @param slots The set of legal slots of the instruction. /// @param is_long A flag indicating whether the format represents an ALUl /// instruction. + /// @param permissive_slots The set of legal slots of the instruction when "permissive-dual-issue" is enabled. binary_format_t(const instruction_t &instruction, word_t mask, - word_t opcode, unsigned int slots, bool is_long = false) : + word_t opcode, unsigned int slots, bool is_long = false, unsigned int permissive_slots=0) : Instruction(instruction), Bit_mask(mask), Opcode(opcode), Slots(slots), Is_long(is_long) { assert((opcode & mask) == opcode); + if(permissive_slots == 0) { + Permissive_slots = slots; + } else { + Permissive_slots = permissive_slots; + } assert(slots != 0 && slots <= 3); + assert(Permissive_slots != 0 && Permissive_slots <= 3); assert(!is_long || slots == 1); } @@ -127,13 +138,13 @@ namespace patmos /// bundle. /// @return True when the instruction word matches the instruction format; /// false otherwise. - bool matches(word_t iw, unsigned int slot) const + bool matches(word_t iw, unsigned int slot, bool permissive_slots) const { assert(slot <= 2); - + auto slot_mask = permissive_slots? Permissive_slots: Slots; // check the bit pattern against the mask and verify the slot position return ((iw & Bit_mask) == Opcode) && - (Slots & (1 << (slot & 1))) != 0; + (slot_mask & (1 << (slot & 1))) != 0; } /// Return whether the instruction format is a long format (exclusively ALUl diff --git a/include/decoder.h b/include/decoder.h index ece58be..53bec56 100644 --- a/include/decoder.h +++ b/include/decoder.h @@ -98,8 +98,13 @@ namespace patmos unsigned int decode(word_t iw, word_t imm, unsigned int slot, instruction_data_t &result); public: + /// Allow the use of loads, stores, and branch in the second issue slot + /// as long as only one of each is enabled per bundle. I.e. is two loads + /// are in the same slot, only one of them may be enabled. + bool Use_permissive_dual_issue; + /// Construct a new instance of a Patmos decoder. - decoder_t(); + decoder_t(bool use_permissive_dual_issue); /// Decode a binary encoded instruction bundle. /// @param iwp Pointer to binary data of the instruction bundle, the pointer diff --git a/include/simulation-core.h b/include/simulation-core.h index 4052d2d..4c6ffc8 100644 --- a/include/simulation-core.h +++ b/include/simulation-core.h @@ -262,6 +262,11 @@ namespace patmos /// Profiling information for function profiling profiling_t Profiling; + /// Allow the use of loads, stores, and branch in the second issue slot + /// as long as only one of each is enabled per bundle. I.e. is two loads + /// are in the same slot, only one of them may be enabled. + bool Use_permissive_dual_issue; + /// Print the internal register state of the simulator to an output stream /// (excluding memories and caches) /// @param os An output stream. @@ -318,10 +323,12 @@ namespace patmos /// @param instr_cache The instruction cache to use during the simulation. /// @param stack_cache The stack cache to use during the simulation. /// @param symbols A mapping from addresses to symbols. + /// @param excunit + /// @param use_permissive_dual_issue Whether to use permissive dual issue simulator_t(unsigned int freq, memory_t &memory, memory_t &local_memory, data_cache_t &data_cache, instr_cache_t &instr_cache, stack_cache_t &stack_cache, symbol_map_t &symbols, - excunit_t &excunit); + excunit_t &excunit, bool use_permissive_dual_issue); // Destroy an instance of a Patms-core simulator ~simulator_t(); diff --git a/src/binary-formats.cc b/src/binary-formats.cc index 24c6466..7328343 100644 --- a/src/binary-formats.cc +++ b/src/binary-formats.cc @@ -601,7 +601,7 @@ namespace patmos ldt_format_t::ldt_format_t(const instruction_t &instruction, word_t opcode, bool is_stack) : binary_format_t(instruction, 0x7C00F80, insert(0x2800000, 7, 5, opcode), - is_stack ? 3 : 1) + is_stack ? 3 : 1, false, 3) { } diff --git a/src/decoder.cc b/src/decoder.cc index c9c0aac..2993b5e 100644 --- a/src/decoder.cc +++ b/src/decoder.cc @@ -50,7 +50,7 @@ namespace patmos int decoder_t::NOP_ID; - decoder_t::decoder_t() + decoder_t::decoder_t(bool use_permissive_dual_issue) : Use_permissive_dual_issue(use_permissive_dual_issue) { // initialize the known instructions and binary formats. initialize_instructions(); @@ -67,7 +67,7 @@ namespace patmos ie(Instructions.end()); i != ie; i++) { const binary_format_t &fmt = *i->get<1>(); - if (fmt.matches(iw, slot)) + if (fmt.matches(iw, slot, Use_permissive_dual_issue)) { // ensure that only one instruction type matches. assert(!matched); @@ -120,7 +120,7 @@ namespace patmos // decode second instruction of bundle else if (decode(imm, 0, 1, result[1]) == 1) { - // two instructinos of the bundle decoded + // two instructions of the bundle decoded return 2; } else diff --git a/src/pacheck.cc b/src/pacheck.cc index fe80a69..e9902cd 100644 --- a/src/pacheck.cc +++ b/src/pacheck.cc @@ -162,7 +162,7 @@ int main(int argc, char **argv) // free streams free_stream(in); - decoder_t decoder; + decoder_t decoder(false); instruction_checker_t instruction_checker; int retcode = 0; diff --git a/src/padasm.cc b/src/padasm.cc index 976a854..4793bd7 100644 --- a/src/padasm.cc +++ b/src/padasm.cc @@ -81,7 +81,7 @@ class instruction_printer_t : public patmos::decoder_callback_t int main(int argc, char **argv) { - patmos::decoder_t padasm; + patmos::decoder_t padasm(false); patmos::symbol_map_t symbols; patmos::section_list_t text; @@ -104,7 +104,7 @@ int main(int argc, char **argv) patmos::loader_t *loader = patmos::create_loader(in); loader->load_symbols(symbols, text); - patmos::decoder_t decoder; + patmos::decoder_t decoder(false); instruction_printer_t printer(out); for (patmos::section_list_t::iterator t = text.begin(), te = text.end(); diff --git a/src/pasim.cc b/src/pasim.cc index ad5a21e..7b86d63 100644 --- a/src/pasim.cc +++ b/src/pasim.cc @@ -434,7 +434,8 @@ int main(int argc, char **argv) ("led_offset", boost::program_options::value()->default_value(patmos::LED_OFFSET), "offset where the LED device is mapped") ("deadline_offset", boost::program_options::value()->default_value(patmos::DEADLINE_OFFSET), "offset where the deadline device is mapped") ("ethmac_offset", boost::program_options::value()->default_value(patmos::ETHMAC_OFFSET), "offset where the EthMac device is mapped") - ("ethmac_ip_addr", boost::program_options::value()->default_value(""), "Provide virtual network interface with the given IP address"); + ("ethmac_ip_addr", boost::program_options::value()->default_value(""), "Provide virtual network interface with the given IP address") + ("permissive-dual-issue", "loads, stores, and branches allowed in second slot when only one of each is enabled in either slot"); boost::program_options::options_description uart_options("UART options"); uart_options.add_options() @@ -511,6 +512,8 @@ int main(int argc, char **argv) unsigned int deadline_offset = vm["deadline_offset"].as().value(); unsigned int ethmac_offset = vm["ethmac_offset"].as().value(); std::string ethmac_ip_addr = vm["ethmac_ip_addr"].as(); + bool permissive_dual_issue = vm.count("permissive-dual-issue") != 0; + #ifdef RAMULATOR patmos::main_memory_kind_e gkind = patmos::GM_SIMPLE; @@ -656,7 +659,7 @@ int main(int argc, char **argv) patmos::symbol_map_t sym; - patmos::simulator_t s(freq, gm, mm, dc, ic, sc, sym, excunit); + patmos::simulator_t s(freq, gm, mm, dc, ic, sc, sym, excunit, permissive_dual_issue); // setup statistics printing patmos::stats_options_t &stats_options = s.Dbg_stack.get_stats_options(); diff --git a/src/simulation-core.cc b/src/simulation-core.cc index cedb184..2e2f428 100644 --- a/src/simulation-core.cc +++ b/src/simulation-core.cc @@ -57,7 +57,7 @@ namespace patmos memory_t &local_memory, data_cache_t &data_cache, instr_cache_t &instr_cache, stack_cache_t &stack_cache, symbol_map_t &symbols, - excunit_t &excunit) + excunit_t &excunit, bool use_permissive_dual_issue) : Dbg_cnt_delay(0), Freq(freq), Cycle(0), Memory(memory), Local_memory(local_memory), Data_cache(data_cache), Instr_cache(instr_cache), @@ -70,7 +70,7 @@ namespace patmos Flush_Cache_PC(std::numeric_limits::max()), Stats_Start_Cycle(0), Traced_instructions(0), - Num_NOPs(0) + Num_NOPs(0), Use_permissive_dual_issue(use_permissive_dual_issue), Decoder(use_permissive_dual_issue) { // initialize the pipeline for(unsigned int i = 0; i < NUM_STAGES; i++) @@ -126,6 +126,18 @@ namespace patmos debug_out << pst << " : "; } + // Check permissive instructions + if( Use_permissive_dual_issue && f == &instruction_data_t::DR) { + auto pred0 = PRR.get(Pipeline[pst][0].Pred).get(); + auto pred1 = PRR.get(Pipeline[pst][1].Pred).get(); + + if(pred0 && pred1) { + if(Pipeline[pst][0].I->is_load() && Pipeline[pst][1].I->is_load()) { + patmos::simulation_exception_t::illegal("Two simultaneously enabled loads", Pipeline[pst][0]); + } + } + } + // invoke simulation functions for(unsigned int i = 0; i < NUM_SLOTS; i++) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 009ecea..0adbc3a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -151,6 +151,12 @@ Errors : 0") test_asm(52 "Emitted: 40 bytes Errors : 0") +test_asm(55 "Emitted: 60 bytes +Errors : 0") + +test_asm(56 "Emitted: 52 bytes +Errors : 0") + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # SIMULATOR TESTS # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @@ -160,6 +166,11 @@ macro (test_sim num expr) SET_TESTS_PROPERTIES(sim-test-${num} PROPERTIES PASS_REGULAR_EXPRESSION ${expr} DEPENDS asm-test-${num}) endmacro (test_sim) +macro (test_sim_arg num args expr) + ADD_TEST(sim-test-arg-${num} ${CMAKE_BINARY_DIR}/src/pasim -V --maxc 40000 -o - ${CMAKE_CURRENT_BINARY_DIR}/test${num}.bin ${args}) + SET_TESTS_PROPERTIES(sim-test-arg-${num} PROPERTIES PASS_REGULAR_EXPRESSION ${expr} DEPENDS asm-test-${num}) +endmacro (test_sim) + macro (test_dsim num expr) ADD_TEST(simd-test-${num} ${CMAKE_BINARY_DIR}/src/pasim -V -G 10 --maxc 40000 ${CMAKE_CURRENT_BINARY_DIR}/test${num}.bin) SET_TESTS_PROPERTIES(simd-test-${num} PROPERTIES PASS_REGULAR_EXPRESSION ${expr} DEPENDS asm-test-${num}) @@ -332,3 +343,9 @@ test_elf_exit_sim(53 "r1 : 00000000") test_elf_exit_sim(54 "r1 : 0000007b r2 : 000001c8") +test_sim(55 "\\\\\\[Error\\\\\\] Illegal instruction: 8a861180.*PC : 00000014") + +test_sim_arg(55 "--permissive-dual-issue" "r3 : 0000007b r4 : 000001c8") + +test_sim_arg(56 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled loads.*\\\\\\( p1\\\\\\) lwm r3 = \\\\\\[r1 \\\\\\+ 0\\\\\\]") + diff --git a/tests/test55.s b/tests/test55.s new file mode 100644 index 0000000..b86085d --- /dev/null +++ b/tests/test55.s @@ -0,0 +1,18 @@ +# +# Tests the use of loads in the second issue slot where only one is enabled +# + + .word 60; + addi r1 = r0, DUMMY1; + addi r2 = r0, DUMMY2; + pand p1 = p0, p0 + pand p2 = p0, !p0 + (p1)lwm r3 = [r1] || (p2) lwm r4 = [r2] + (p2)lwm r3 = [r1] || (p1) lwm r4 = [r2] + halt; + nop; + nop; + nop; + +DUMMY1: .word 123; +DUMMY2: .word 456; diff --git a/tests/test56.s b/tests/test56.s new file mode 100644 index 0000000..3a38031 --- /dev/null +++ b/tests/test56.s @@ -0,0 +1,17 @@ +# +# Tests the use of loads in the second issue slot where they are both enabled +# + + .word 60; + addi r1 = r0, DUMMY1; + addi r2 = r0, DUMMY2; + pand p1 = p0, p0 + pand p2 = p0, p0 + (p1)lwm r3 = [r1] || (p2) lwm r4 = [r2] + halt; + nop; + nop; + nop; + +DUMMY1: .word 123; +DUMMY2: .word 456; From b73dcd6fc85346f3053b0118f59f2a0efe006a32 Mon Sep 17 00:00:00 2001 From: Emad Jacob Maroun Date: Mon, 28 Aug 2023 18:00:55 +0200 Subject: [PATCH 02/10] Added store instruction to 'permissive-dual-issue' --- include/instructions.h | 2 +- src/binary-formats.cc | 2 +- src/simulation-core.cc | 11 ++++++++--- tests/CMakeLists.txt | 16 ++++++++++++++++ tests/test57.s | 24 ++++++++++++++++++++++++ tests/test58.s | 17 +++++++++++++++++ tests/test59.s | 18 ++++++++++++++++++ 7 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 tests/test57.s create mode 100644 tests/test58.s create mode 100644 tests/test59.s diff --git a/include/instructions.h b/include/instructions.h index db82474..76398de 100755 --- a/include/instructions.h +++ b/include/instructions.h @@ -1560,7 +1560,7 @@ namespace patmos public: i_stt_t() { reset_stats(); } - virtual bool is_store() { return true; } + virtual bool is_store() const { return true; } virtual GPR_e get_src1_reg(const instruction_data_t &ops) const { return ops.OPS.STT.Ra; diff --git a/src/binary-formats.cc b/src/binary-formats.cc index 7328343..1171881 100644 --- a/src/binary-formats.cc +++ b/src/binary-formats.cc @@ -691,7 +691,7 @@ namespace patmos stt_format_t::stt_format_t(const instruction_t &instruction, word_t opcode, bool is_stack) : binary_format_t(instruction, 0x7FE0000, insert(0x2C00000, 17, 5, opcode), - is_stack ? 3 : 1) + is_stack ? 3 : 1, false, 3) { } diff --git a/src/simulation-core.cc b/src/simulation-core.cc index 2e2f428..b2e5d85 100644 --- a/src/simulation-core.cc +++ b/src/simulation-core.cc @@ -128,13 +128,18 @@ namespace patmos // Check permissive instructions if( Use_permissive_dual_issue && f == &instruction_data_t::DR) { - auto pred0 = PRR.get(Pipeline[pst][0].Pred).get(); - auto pred1 = PRR.get(Pipeline[pst][1].Pred).get(); + auto &pipe_instr0 = Pipeline[pst][0]; + auto &pipe_instr1 = Pipeline[pst][1]; + auto pred0 = PRR.get(pipe_instr0.Pred).get(); + auto pred1 = PRR.get(pipe_instr1.Pred).get(); if(pred0 && pred1) { - if(Pipeline[pst][0].I->is_load() && Pipeline[pst][1].I->is_load()) { + if(pipe_instr0.I->is_load() && pipe_instr1.I->is_load()) { patmos::simulation_exception_t::illegal("Two simultaneously enabled loads", Pipeline[pst][0]); } + if(pipe_instr0.I->is_store() && pipe_instr1.I->is_store()) { + patmos::simulation_exception_t::illegal("Two simultaneously enabled stores", Pipeline[pst][0]); + } } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0adbc3a..8856869 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -157,6 +157,15 @@ Errors : 0") test_asm(56 "Emitted: 52 bytes Errors : 0") +test_asm(57 "Emitted: 84 bytes +Errors : 0") + +test_asm(58 "Emitted: 52 bytes +Errors : 0") + +test_asm(59 "Emitted: 56 bytes +Errors : 0") + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # SIMULATOR TESTS # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @@ -349,3 +358,10 @@ test_sim_arg(55 "--permissive-dual-issue" "r3 : 0000007b r4 : 000001c8") test_sim_arg(56 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled loads.*\\\\\\( p1\\\\\\) lwm r3 = \\\\\\[r1 \\\\\\+ 0\\\\\\]") +test_sim(57 "\\\\\\[Error\\\\\\] Illegal instruction: 92c61180.*PC : 00000024") + +test_sim_arg(57 "--permissive-dual-issue" "r5 : 0000000c r6 : 00000022") + +test_sim_arg(58 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled stores.*\\\\\\( p1\\\\\\) swm \\\\\\[r1 \\\\\\+ 0\\\\\\] = r3") + +test_sim_arg(59 "--permissive-dual-issue" "r4 : 0000007b r5 : 000001c8") diff --git a/tests/test57.s b/tests/test57.s new file mode 100644 index 0000000..3dd81a1 --- /dev/null +++ b/tests/test57.s @@ -0,0 +1,24 @@ +# +# Tests the use of stores in the second issue slot where only one is enabled +# + + .word 84; + addi r1 = r0, DUMMY1; + addi r2 = r0, DUMMY2; + addi r3 = r0, 12; + addi r4 = r0, 34; + addi r5 = r0, 0; + addi r6 = r0, 0; + pand p2 = p0, p0 + pand p3 = p0, !p0 + (p2)swm [r1] = r3 || (p3) swm [r2] = r4 + (p3)swm [r1] = r3 || (p2) swm [r2] = r4 + lwm r5 = [r1] + lwm r6 = [r2] + halt; + nop; + nop; + nop; + +DUMMY1: .word 0; +DUMMY2: .word 0; diff --git a/tests/test58.s b/tests/test58.s new file mode 100644 index 0000000..d7236bb --- /dev/null +++ b/tests/test58.s @@ -0,0 +1,17 @@ +# +# Tests the use of stores in the second issue slot where only one is enabled +# + + .word 60; + addi r1 = r0, DUMMY1; + addi r2 = r0, DUMMY2; + addi r3 = r0, 12; + pand p1 = p0, p0 + (p1) swm [r1] = r3 || (p1) swm [r2] = r4 + halt; + nop; + nop; + nop; + +DUMMY1: .word 0; +DUMMY2: .word 0; diff --git a/tests/test59.s b/tests/test59.s new file mode 100644 index 0000000..e32f7b8 --- /dev/null +++ b/tests/test59.s @@ -0,0 +1,18 @@ +# +# Tests can have store and load enabled at the same time +# + + .word 60; + addi r1 = r0, DUMMY1; + addi r2 = r0, DUMMY2; + addi r3 = r0, 456; + pand p3 = p0, p0 + (p3) swm [r2] = r3 || (p0) lwm r4 = [r1] + lwm r5 = [r2] + halt; + nop; + nop; + nop; + +DUMMY1: .word 123; +DUMMY2: .word 0; From b13ad555682dc4da52f09d2e1aabb847e03cae88 Mon Sep 17 00:00:00 2001 From: Emad Jacob Maroun Date: Tue, 29 Aug 2023 13:41:42 +0200 Subject: [PATCH 03/10] Added immediate control flow instruction to 'permissive-dual-issue' --- src/binary-formats.cc | 3 ++- src/simulation-core.cc | 16 +++++++++++++-- tests/CMakeLists.txt | 24 +++++++++++++++++++++++ tests/test60.s | 37 +++++++++++++++++++++++++++++++++++ tests/test61.s | 15 ++++++++++++++ tests/test62.s | 44 ++++++++++++++++++++++++++++++++++++++++++ tests/test63.s | 15 ++++++++++++++ 7 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 tests/test60.s create mode 100644 tests/test61.s create mode 100644 tests/test62.s create mode 100644 tests/test63.s diff --git a/src/binary-formats.cc b/src/binary-formats.cc index 1171881..f80aceb 100644 --- a/src/binary-formats.cc +++ b/src/binary-formats.cc @@ -860,7 +860,8 @@ namespace patmos cfli_format_t::cfli_format_t(const instruction_t &instruction, word_t opcode, word_t flag) : binary_format_t(instruction, 0x7c00000, - insert(insert(0x4000000, 23, 2, opcode), 22, 1, flag), 1) + insert(insert(0x4000000, 23, 2, opcode), 22, 1, flag), + 1, false, 3) { } diff --git a/src/simulation-core.cc b/src/simulation-core.cc index b2e5d85..4490ef1 100644 --- a/src/simulation-core.cc +++ b/src/simulation-core.cc @@ -44,6 +44,7 @@ #include "excunit.h" #include "instructions.h" #include "rtc.h" +#include #include #include @@ -128,17 +129,28 @@ namespace patmos // Check permissive instructions if( Use_permissive_dual_issue && f == &instruction_data_t::DR) { + assert(NUM_SLOTS = 2); auto &pipe_instr0 = Pipeline[pst][0]; auto &pipe_instr1 = Pipeline[pst][1]; auto pred0 = PRR.get(pipe_instr0.Pred).get(); auto pred1 = PRR.get(pipe_instr1.Pred).get(); if(pred0 && pred1) { + boost::optional err; if(pipe_instr0.I->is_load() && pipe_instr1.I->is_load()) { - patmos::simulation_exception_t::illegal("Two simultaneously enabled loads", Pipeline[pst][0]); + err = "loads"; } if(pipe_instr0.I->is_store() && pipe_instr1.I->is_store()) { - patmos::simulation_exception_t::illegal("Two simultaneously enabled stores", Pipeline[pst][0]); + err = "stores"; + } + if(pipe_instr0.I->is_flow_control() && pipe_instr1.I->is_flow_control()) { + err = "control flows"; + } + + if(err) { + auto msg = std::string("Two simultaneously enabled "); + msg.append(*err); + patmos::simulation_exception_t::illegal(msg, Pipeline[pst][0]); } } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8856869..08a19f5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -166,6 +166,18 @@ Errors : 0") test_asm(59 "Emitted: 56 bytes Errors : 0") +test_asm(60 "Emitted: 128 bytes +Errors : 0") + +test_asm(61 "Emitted: 40 bytes +Errors : 0") + +test_asm(62 "Emitted: 160 bytes +Errors : 0") + +test_asm(63 "Emitted: 40 bytes +Errors : 0") + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # SIMULATOR TESTS # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @@ -365,3 +377,15 @@ test_sim_arg(57 "--permissive-dual-issue" "r5 : 0000000c r6 : 00000022") test_sim_arg(58 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled stores.*\\\\\\( p1\\\\\\) swm \\\\\\[r1 \\\\\\+ 0\\\\\\] = r3") test_sim_arg(59 "--permissive-dual-issue" "r4 : 0000007b r5 : 000001c8") + +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(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") diff --git a/tests/test60.s b/tests/test60.s new file mode 100644 index 0000000..df4db2f --- /dev/null +++ b/tests/test60.s @@ -0,0 +1,37 @@ +# +# Tests branches in both issue slots with only one enabled +# + + .word 128; + add r1 = r0, r0; + add r2 = r0, r0; + add r3 = r0, r0; + add r4 = r0, r0; + (!p0) br brto1 || (p0) br brto2 + addi r1 = r0, 123; + addi r2 = r0, 456; + halt; + nop; + nop; + nop; + +brto1: addi r3 = r0, 789; + halt; + nop; + nop; + nop; + +brto2: addi r3 = r0, 159; + (p0) br brto3 || (!p0) br brto1 + nop; + nop; + halt; + nop; + nop; + nop; + +brto3: addi r4 = r0, 753; + halt; + nop; + nop; + nop; diff --git a/tests/test61.s b/tests/test61.s new file mode 100644 index 0000000..f93ed6e --- /dev/null +++ b/tests/test61.s @@ -0,0 +1,15 @@ +# +# Tests branches in both issue slots with only one enabled +# + + .word 40; + add r1 = r0, r0; + (p0) br brto1 || (p0) br brto2 + nop; + nop; + halt; + nop; + nop; + nop; +brto1: +brto2: \ No newline at end of file diff --git a/tests/test62.s b/tests/test62.s new file mode 100644 index 0000000..68265e8 --- /dev/null +++ b/tests/test62.s @@ -0,0 +1,44 @@ +# +# Tests a call and branch in bundle with only one enabled +# + + .word 160; + add r1 = r0, 111; + add r2 = r0, r0; + add r3 = r0, r0; + add r4 = r0, r0; + add r5 = r0, r0; + add r6 = r0, r0; + add r7 = r0, r0; + add r8 = r0, r0; + pand p5 = p0, p0; + (p5) br brto1 || (!p0) call brto2 + addi r2 = r0, 222; + addi r3 = r0, 333; + addi r1 = r0, 0; # shouldn't be executed + halt; + nop; + nop; + nop; + +brto1: addi r4 = r0, 444; + (!p5) br brto1 || (p0) call brto3 + addi r5 = r0, 555; + addi r6 = r0, 666; + addi r7 = r0, 777; + halt; + nop; + nop; + nop; + +brto2: addi r1 = r0, 0; # shouldn't be executed + halt; + nop; + nop; + nop; + +brto3: addi r8 = r0, 888; + halt; + nop; + nop; + nop; diff --git a/tests/test63.s b/tests/test63.s new file mode 100644 index 0000000..967df47 --- /dev/null +++ b/tests/test63.s @@ -0,0 +1,15 @@ +# +# Tests cannot have enabled branch and call in bundle +# + + .word 40; + add r1 = r0, r0; + (p0) br brto1 || (p0) call brto2 + nop; + nop; + halt; + nop; + nop; + nop; +brto1: +brto2: \ No newline at end of file From df4e8fe6cb5c722ff4c362329678690da28c0a9b Mon Sep 17 00:00:00 2001 From: Emad Jacob Maroun Date: Mon, 4 Sep 2023 14:08:34 +0200 Subject: [PATCH 04/10] Instructions in second slot now have the correct address assigned to them --- src/simulation-core.cc | 4 +--- tests/CMakeLists.txt | 5 +++++ tests/test66.s | 27 +++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 tests/test66.s diff --git a/src/simulation-core.cc b/src/simulation-core.cc index 4490ef1..7c5d9f7 100644 --- a/src/simulation-core.cc +++ b/src/simulation-core.cc @@ -245,8 +245,6 @@ namespace patmos } } - - void simulator_t::instruction_fetch() { // we get a pointer to the instructions of the IF stage, for easier @@ -339,7 +337,7 @@ namespace patmos for(unsigned int j = 0; j < NUM_SLOTS; j++) { // assign fetch address to new instructions - instr_SIF[j].Address = PC; + instr_SIF[j].Address = PC + j*sizeof(word_t); // track instructions fetched if (instr_SIF[j].I) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 08a19f5..5854b6e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -178,6 +178,8 @@ Errors : 0") test_asm(63 "Emitted: 40 bytes Errors : 0") +test_asm(66 "Errors : 0") + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # SIMULATOR TESTS # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @@ -389,3 +391,6 @@ 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(66 "--permissive-dual-issue" "r1 : 000001c8.*r2 : 000000b3.*r3 : 0000007b.*r4 : 00000315.*r5 : 0000009f.*r6 : 00000000") + diff --git a/tests/test66.s b/tests/test66.s new file mode 100644 index 0000000..2e18cf9 --- /dev/null +++ b/tests/test66.s @@ -0,0 +1,27 @@ +# +# Tests branches in second issue slot +# + + .word 100; + addi r2 = r0, 0; + addi r3 = r0, 123; + addi r4 = r0, 0; + addi r5 = r0, 0; + addi r6 = r0, 0; + addi r1 = r0, 456 || br branch_tar; + addi r4 = r0, 789; + addi r5 = r0, 159; + addi r6 = r0, 753; +halt_label: halt; + nop; + nop; + nop; + + addi r3 = r0, 0; # Ensure if 'branch_tar' isn't hit, r3 is cleared +branch_tar: + addi r2 = r0, 179; + halt; + nop; + nop; + nop; + From b3dd80b4722eb5ee514d5fdbd74576ea26fcf721 Mon Sep 17 00:00:00 2001 From: Emad Jacob Maroun Date: Mon, 4 Sep 2023 15:23:37 +0200 Subject: [PATCH 05/10] pasim data-cache kind help message no longer misrepresents the defualt. --- src/pasim.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pasim.cc b/src/pasim.cc index 7b86d63..803d796 100644 --- a/src/pasim.cc +++ b/src/pasim.cc @@ -399,7 +399,7 @@ int main(int argc, char **argv) cache_options.add_options() ("dcsize,d", boost::program_options::value()->default_value(patmos::NUM_DATA_CACHE_BYTES), "data cache size in bytes") ("dckind,D", boost::program_options::value()->default_value(patmos::set_assoc_cache_type(patmos::SAC_DM,1)), - "kind of direct mapped/fully-/set-associative data cache, defaults to lru2 (ideal, no, dm, lru[N], fifo[N])") + "kind of direct mapped/fully-/set-associative data cache (ideal, no, dm, lru[N], fifo[N])") ("dlsize", boost::program_options::value()->default_value(0), "size of a data cache line in bytes, defaults to burst size if set to 0") ("scsize,s", boost::program_options::value()->default_value(patmos::NUM_STACK_CACHE_BYTES), "stack cache size in bytes") From 8203a596486833b5cf49f24d336b3cbed9b558f2 Mon Sep 17 00:00:00 2001 From: Emad Jacob Maroun Date: Tue, 5 Sep 2023 08:52:33 +0200 Subject: [PATCH 06/10] Stack load/store no longer allowed in second slot by default. Like other loads/stores, stack load/store now only allowed in second issue slot when using the '--permissive-dual-issue' flag. Also no longer allows two stack loads/stores enabled in the same bundle. --- include/binary-formats.h | 3 +-- src/binary-formats.cc | 5 ++--- src/decoder.cc | 8 -------- src/instructions.inc | 16 ++++++++-------- tests/CMakeLists.txt | 6 ++++++ tests/test14.s | 6 ++++-- tests/test64.s | 26 ++++++++++++++++++++++++++ 7 files changed, 47 insertions(+), 23 deletions(-) create mode 100644 tests/test64.s diff --git a/include/binary-formats.h b/include/binary-formats.h index 8004ce8..a6b25bf 100644 --- a/include/binary-formats.h +++ b/include/binary-formats.h @@ -242,8 +242,7 @@ namespace patmos /// @param opcode The instruction's opcode. /// @param is_stack Flag indicating whether the instruction accesses the /// stack. - ldt_format_t(const instruction_t &instruction, word_t opcode, - bool is_stack = false); + ldt_format_t(const instruction_t &instruction, word_t opcode); virtual instruction_data_t decode_operands(word_t iw, word_t longimm) const; diff --git a/src/binary-formats.cc b/src/binary-formats.cc index f80aceb..e3c64aa 100644 --- a/src/binary-formats.cc +++ b/src/binary-formats.cc @@ -598,10 +598,9 @@ namespace patmos return iw; } - ldt_format_t::ldt_format_t(const instruction_t &instruction, word_t opcode, - bool is_stack) : + ldt_format_t::ldt_format_t(const instruction_t &instruction, word_t opcode) : binary_format_t(instruction, 0x7C00F80, insert(0x2800000, 7, 5, opcode), - is_stack ? 3 : 1, false, 3) + 1, false, 3) { } diff --git a/src/decoder.cc b/src/decoder.cc index 2993b5e..5fd9290 100644 --- a/src/decoder.cc +++ b/src/decoder.cc @@ -211,14 +211,6 @@ namespace patmos Instructions.push_back(boost::make_tuple(itmp, ftmp)); \ } -#define MK_SINSTR(name, format, opcode) \ - { \ - instruction_t *itmp = new i_ ## name ## _t(); \ - itmp->ID = Instructions.size(); \ - itmp->Name = #name; \ - binary_format_t *ftmp = new format ## _format_t(*itmp, opcode, true); \ - Instructions.push_back(boost::make_tuple(itmp, ftmp)); \ - } #define MK_NINSTR_ALIAS(classname, name, format, opcode) #define MK_FINSTR(classname, name, format, opcode, flag) \ diff --git a/src/instructions.inc b/src/instructions.inc index 9e40098..2fa78a6 100644 --- a/src/instructions.inc +++ b/src/instructions.inc @@ -86,37 +86,37 @@ MK_NINSTR(spcf, mfs , spcf, 0) // LDT - MK_SINSTR(lws , ldt, 0) + MK_INSTR(lws , ldt, 0) MK_INSTR(lwl , ldt, 1) MK_INSTR(lwc , ldt, 2) MK_INSTR(lwm , ldt, 3) - MK_SINSTR(lhs , ldt, 4) + MK_INSTR(lhs , ldt, 4) MK_INSTR(lhl , ldt, 5) MK_INSTR(lhc , ldt, 6) MK_INSTR(lhm , ldt, 7) - MK_SINSTR(lbs , ldt, 8) + MK_INSTR(lbs , ldt, 8) MK_INSTR(lbl , ldt, 9) MK_INSTR(lbc , ldt, 10) MK_INSTR(lbm , ldt, 11) - MK_SINSTR(lhus, ldt, 12) + MK_INSTR(lhus , ldt, 12) MK_INSTR(lhul , ldt, 13) MK_INSTR(lhuc , ldt, 14) MK_INSTR(lhum , ldt, 15) - MK_SINSTR(lbus, ldt, 16) + MK_INSTR(lbus , ldt, 16) MK_INSTR(lbul , ldt, 17) MK_INSTR(lbuc , ldt, 18) MK_INSTR(lbum , ldt, 19) // STT - MK_SINSTR(sws, stt, 0) + MK_INSTR(sws , stt, 0) MK_INSTR(swl , stt, 1) MK_INSTR(swc , stt, 2) MK_INSTR(swm , stt, 3) - MK_SINSTR(shs, stt, 4) + MK_INSTR(shs , stt, 4) MK_INSTR(shl , stt, 5) MK_INSTR(shc , stt, 6) MK_INSTR(shm , stt, 7) - MK_SINSTR(sbs, stt, 8) + MK_INSTR(sbs , stt, 8) MK_INSTR(sbl , stt, 9) MK_INSTR(sbc , stt, 10) MK_INSTR(sbm , stt, 11) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5854b6e..649d9c9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -178,6 +178,8 @@ Errors : 0") test_asm(63 "Emitted: 40 bytes Errors : 0") +test_asm(64 "Errors : 0") + test_asm(66 "Errors : 0") # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @@ -392,5 +394,9 @@ test_sim_arg(62 "--permissive-dual-issue" "r1 : 0000006f.*r2 : 000000de.*r3 : 00 test_sim_arg(63 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled control flows.*br 8") +test_sim(64 "\\\\\\[Error\\\\\\] Illegal instruction: 800801c8") + +test_sim_arg(64 "--permissive-dual-issue" "r3 : 0000007b.*r4 : 000001c8.*r5 : 00000315") + test_sim_arg(66 "--permissive-dual-issue" "r1 : 000001c8.*r2 : 000000b3.*r3 : 0000007b.*r4 : 00000315.*r5 : 0000009f.*r6 : 00000000") diff --git a/tests/test14.s b/tests/test14.s index 4187e36..4b77e6b 100644 --- a/tests/test14.s +++ b/tests/test14.s @@ -12,8 +12,10 @@ shs [r0 + 2] = r1; sbs [r0 + 6] = r1; lws r2 = [r0 + 0]; - lhs r3 = [r0 + 0] || lbs r4 = [r0 + 1]; - lhus r5 = [r0 + 0] || lbus r6 = [r0 + 1]; + lhs r3 = [r0 + 0]; + lbs r4 = [r0 + 1]; + lhus r5 = [r0 + 0]; + lbus r6 = [r0 + 1]; sfree 4; halt; nop; diff --git a/tests/test64.s b/tests/test64.s new file mode 100644 index 0000000..52f54e2 --- /dev/null +++ b/tests/test64.s @@ -0,0 +1,26 @@ +# +# Tests stack load/store in second issue slot +# + + .word 100; + addi r1 = r0, stack_base; + addi r2 = r0, 123; + addi r3 = r0, 0; + addi r4 = r0, 0; + addi r5 = r0, 0; + mts s5 = r1; + mts s6 = r1; + sres 2; + addi r4 = r0, 456 || sws [0] = r2; + addi r5 = r0, 789 || lws r3 = [0]; + sfree 2; + halt; + nop; + nop; + nop; +stack_base: + .word 0; + .word 0; + .word 0; + .word 0; + From 4b3edc3a68774a3c020fb87d5eeeb4ddaf458e6c Mon Sep 17 00:00:00 2001 From: Emad Jacob Maroun Date: Tue, 5 Sep 2023 09:14:00 +0200 Subject: [PATCH 07/10] '--permissive-dual-issue' now disallows two enabled load/store. This is because implemented allowing that in hardware would be difficult. --- src/simulation-core.cc | 11 +++++------ tests/CMakeLists.txt | 9 ++++----- tests/test59.s | 16 ++++++---------- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/simulation-core.cc b/src/simulation-core.cc index 7c5d9f7..dbc58e3 100644 --- a/src/simulation-core.cc +++ b/src/simulation-core.cc @@ -137,14 +137,13 @@ namespace patmos if(pred0 && pred1) { boost::optional err; - if(pipe_instr0.I->is_load() && pipe_instr1.I->is_load()) { - err = "loads"; - } - if(pipe_instr0.I->is_store() && pipe_instr1.I->is_store()) { - err = "stores"; + 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"; + err = "control flows"; } if(err) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 649d9c9..4bacb65 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -163,8 +163,7 @@ Errors : 0") test_asm(58 "Emitted: 52 bytes Errors : 0") -test_asm(59 "Emitted: 56 bytes -Errors : 0") +test_asm(59 "Errors : 0") test_asm(60 "Emitted: 128 bytes Errors : 0") @@ -372,15 +371,15 @@ test_sim(55 "\\\\\\[Error\\\\\\] Illegal instruction: 8a861180.*PC : 00000014") test_sim_arg(55 "--permissive-dual-issue" "r3 : 0000007b r4 : 000001c8") -test_sim_arg(56 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled loads.*\\\\\\( p1\\\\\\) lwm r3 = \\\\\\[r1 \\\\\\+ 0\\\\\\]") +test_sim_arg(56 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled load/store.*\\\\\\( p1\\\\\\) lwm r3 = \\\\\\[r1 \\\\\\+ 0\\\\\\]") test_sim(57 "\\\\\\[Error\\\\\\] Illegal instruction: 92c61180.*PC : 00000024") test_sim_arg(57 "--permissive-dual-issue" "r5 : 0000000c r6 : 00000022") -test_sim_arg(58 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled stores.*\\\\\\( p1\\\\\\) swm \\\\\\[r1 \\\\\\+ 0\\\\\\] = r3") +test_sim_arg(58 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled load/store.*\\\\\\( p1\\\\\\) swm \\\\\\[r1 \\\\\\+ 0\\\\\\] = r3") -test_sim_arg(59 "--permissive-dual-issue" "r4 : 0000007b r5 : 000001c8") +test_sim_arg(59 "--permissive-dual-issue" "\\\\\\[Error\\\\\\] Illegal instruction: Two simultaneously enabled load/store.*\\\\\\( p7\\\\\\) lwc r3 = \\\\\\[r0 \\\\\\+ 0\\\\\\]") test_sim(60 "\\\\\\[Error\\\\\\] Illegal instruction: c4c00008.*PC : 00000014") diff --git a/tests/test59.s b/tests/test59.s index e32f7b8..1e84d49 100644 --- a/tests/test59.s +++ b/tests/test59.s @@ -1,18 +1,14 @@ # -# Tests can have store and load enabled at the same time +# Tests two enabled loads and stores in the same bundle # - .word 60; - addi r1 = r0, DUMMY1; - addi r2 = r0, DUMMY2; - addi r3 = r0, 456; - pand p3 = p0, p0 - (p3) swm [r2] = r3 || (p0) lwm r4 = [r1] - lwm r5 = [r2] + .word 100; + addi r1 = r0, dummy; + pand p7 = p0, p0; + (p7) lwc r3 = [0] || (p7) swc [0] = r2; halt; nop; nop; nop; +dummy: .word 0; -DUMMY1: .word 123; -DUMMY2: .word 0; From 2e766a2d0b5aa01a98f780d4c19e4bd48f83e57c Mon Sep 17 00:00:00 2001 From: Emad Jacob Maroun Date: Thu, 7 Sep 2023 11:47:11 +0200 Subject: [PATCH 08/10] 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 | 26 ++++++---- tests/CMakeLists.txt | 20 +++++++- tests/test67.s | 26 ++++++++++ tests/test68.s | 20 ++++++++ tests/test69.s | 20 ++++++++ tests/test70.s | 33 +++++++++++++ 8 files changed, 207 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..1b5bf0e 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,23 @@ 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(is_combi(is_flow_control, 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; + From 5d5011dc6fd6683bb20d5da0c659604c221ab78f Mon Sep 17 00:00:00 2001 From: Emad Jacob Maroun Date: Mon, 11 Sep 2023 14:10:41 +0200 Subject: [PATCH 09/10] Fixed issue with functions not getting statistics printed --- src/dbgstack.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/dbgstack.cc b/src/dbgstack.cc index 334812b..b7c91bf 100644 --- a/src/dbgstack.cc +++ b/src/dbgstack.cc @@ -132,6 +132,9 @@ namespace patmos void dbgstack_t::push(uword_t base, uword_t offset, uword_t target) { + // The following (commented out) code is bugged, resulting in otherwise correct programs to not print + // statistics. +/* if (!stack.empty()) { // Check if the call is coming from the TOS. if (!is_active_frame(stack.back())) { @@ -145,6 +148,7 @@ namespace patmos } } } +*/ // Create a new stack frame stack.push_back( dbgstack_frame_t(sim, base, offset, target) ); From e4e73941f61fcbde1a7dc462ed8f0001c9e1ce1a Mon Sep 17 00:00:00 2001 From: Emad Jacob Maroun Date: Mon, 11 Sep 2023 16:29:09 +0200 Subject: [PATCH 10/10] Updated 'permissive-dual-issue' help message. --- src/pasim.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pasim.cc b/src/pasim.cc index 803d796..5d18283 100644 --- a/src/pasim.cc +++ b/src/pasim.cc @@ -435,7 +435,7 @@ int main(int argc, char **argv) ("deadline_offset", boost::program_options::value()->default_value(patmos::DEADLINE_OFFSET), "offset where the deadline device is mapped") ("ethmac_offset", boost::program_options::value()->default_value(patmos::ETHMAC_OFFSET), "offset where the EthMac device is mapped") ("ethmac_ip_addr", boost::program_options::value()->default_value(""), "Provide virtual network interface with the given IP address") - ("permissive-dual-issue", "loads, stores, and branches allowed in second slot when only one of each is enabled in either slot"); + ("permissive-dual-issue", "Enables instructions in the second issue slot that are otherwise prohibited (e.g. loads, stores, branches). Some restrictions apply, which require some instruction combinations to not be enabled simultaneously (e.g. 2 loads)."); boost::program_options::options_description uart_options("UART options"); uart_options.add_options()