Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added --permissive-dual-issue flag #27

Merged
merged 10 commits into from
Sep 11, 2023
19 changes: 15 additions & 4 deletions include/binary-format.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}

Expand Down Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions include/binary-formats.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
7 changes: 6 additions & 1 deletion include/decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
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
107 changes: 64 additions & 43 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 All @@ -1560,7 +1562,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;
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
9 changes: 8 additions & 1 deletion include/simulation-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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();
Expand Down
10 changes: 5 additions & 5 deletions src/binary-formats.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
1, false, 3)
{
}

Expand Down Expand Up @@ -691,7 +690,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)
{
}

Expand Down Expand Up @@ -860,7 +859,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)
{
}

Expand Down
4 changes: 4 additions & 0 deletions src/dbgstack.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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())) {
Expand All @@ -145,6 +148,7 @@ namespace patmos
}
}
}
*/
// Create a new stack frame
stack.push_back( dbgstack_frame_t(sim, base, offset, target) );

Expand Down
Loading