Skip to content

Commit

Permalink
Further refined the requirements on '--permissive-dual-issue'
Browse files Browse the repository at this point in the history
Now also cannot bundle two main-memory operations and two stack operations.
  • Loading branch information
Emoun committed Sep 7, 2023
1 parent 4b3edc3 commit 2e766a2
Show file tree
Hide file tree
Showing 8 changed files with 207 additions and 53 deletions.
10 changes: 10 additions & 0 deletions include/instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
105 changes: 63 additions & 42 deletions include/instructions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:\
Expand All @@ -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); \
Expand All @@ -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
Expand Down Expand Up @@ -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:\
Expand All @@ -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); \
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -2088,6 +2093,8 @@ namespace patmos
}
}

virtual bool is_main_mem_op() const { return true; }

virtual bool is_call() const {
return true;
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -2454,6 +2467,8 @@ namespace patmos
}
}

virtual bool is_main_mem_op() const { return true; }

virtual bool is_call() const {
return true;
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down
26 changes: 17 additions & 9 deletions src/simulation-core.cc
Original file line number Diff line number Diff line change
Expand Up @@ -127,23 +127,31 @@ 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];
auto &pipe_instr1 = Pipeline[pst][1];
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<const char*> 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<const char*> 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) {
Expand Down
20 changes: 18 additions & 2 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Expand Down Expand Up @@ -385,17 +393,25 @@ 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")

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")

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")

26 changes: 26 additions & 0 deletions tests/test67.s
Original file line number Diff line number Diff line change
@@ -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;

20 changes: 20 additions & 0 deletions tests/test68.s
Original file line number Diff line number Diff line change
@@ -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;

20 changes: 20 additions & 0 deletions tests/test69.s
Original file line number Diff line number Diff line change
@@ -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;

Loading

0 comments on commit 2e766a2

Please sign in to comment.