Skip to content

Commit

Permalink
Merge pull request #313 from tactcomplabs/Zaamo_Zalrsc
Browse files Browse the repository at this point in the history
Fix LR/SC and split A into Zaamo and Zalrsc
  • Loading branch information
leekillough authored Aug 30, 2024
2 parents 16e65f1 + 18a7c54 commit c3dee3c
Show file tree
Hide file tree
Showing 17 changed files with 431 additions and 504 deletions.
4 changes: 2 additions & 2 deletions include/AllRevInstTables.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@
// and implementation for each block of RISC-V isntructions
//

#include "insns/RV32A.h"
#include "insns/RV32D.h"
#include "insns/RV32F.h"
#include "insns/RV32I.h"
#include "insns/RV32M.h"
#include "insns/RV64A.h"
#include "insns/RV64D.h"
#include "insns/RV64F.h"
#include "insns/RV64I.h"
#include "insns/RV64M.h"
#include "insns/RV64P.h"
#include "insns/Zaamo.h"
#include "insns/Zalrsc.h"
#include "insns/Zfa.h"
#include "insns/Zicbom.h"
#include "insns/Zicsr.h"
Expand Down
3 changes: 0 additions & 3 deletions include/RevCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,6 @@ class RevCore {
/// RevCore: Debug mode write a register
bool DebugWriteReg( unsigned Idx, uint64_t Value ) const;

/// RevCore: Is this an RV32 machine?
bool DebugIsRV32() { return feature->IsRV32(); }

/// RevCore: Set an optional tracer
void SetTracer( RevTracer* T ) { Tracer = T; }

Expand Down
40 changes: 19 additions & 21 deletions include/RevFeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,24 @@ enum RevFeatureType : uint32_t {
RV_I = 1 << 0, ///< RevFeatureType: I-extension
RV_E = 1 << 1, ///< RevFeatureType: E-extension
RV_M = 1 << 2, ///< RevFeatureType: M-extension
RV_A = 1 << 3, ///< RevFeatureType: A-extension
RV_F = 1 << 4, ///< RevFeatureType: F-extension
RV_D = 1 << 5, ///< RevFeatureType: D-extension
RV_Q = 1 << 6, ///< RevFeatureType: Q-extension
RV_C = 1 << 7, ///< RevFeatureType: C-extension
RV_B = 1 << 8, ///< RevFeatureType: C-extension
RV_P = 1 << 9, ///< RevFeatureType: P-Extension
RV_V = 1 << 10, ///< RevFeatureType: V-extension
RV_H = 1 << 11, ///< RevFeatureType: H-extension
RV_ZICBOM = 1 << 12, ///< RevFeatureType: Zicbom-extension
RV_ZICSR = 1 << 13, ///< RevFEatureType: Zicsr-extension
RV_ZIFENCEI = 1 << 14, ///< RevFeatureType: Zifencei-extension
RV_ZMMUL = 1 << 15, ///< RevFeatureType: Zmmul-extension
RV_ZFA = 1 << 16, ///< RevFeatureType: Zfa-extension
RV_ZFH = 1 << 17, ///< RevFeatureType: H-extension
RV_ZFHMIN = 1 << 18, ///< RevFeatureRtpe: Zfhmin extension
RV_ZTSO = 1 << 19, ///< RevFeatureType: Ztso-extension
RV_F = 1 << 3, ///< RevFeatureType: F-extension
RV_D = 1 << 4, ///< RevFeatureType: D-extension
RV_Q = 1 << 5, ///< RevFeatureType: Q-extension
RV_C = 1 << 6, ///< RevFeatureType: C-extension
RV_B = 1 << 7, ///< RevFeatureType: C-extension
RV_P = 1 << 8, ///< RevFeatureType: P-Extension
RV_V = 1 << 9, ///< RevFeatureType: V-extension
RV_H = 1 << 10, ///< RevFeatureType: H-extension
RV_ZICBOM = 1 << 11, ///< RevFeatureType: Zicbom-extension
RV_ZICSR = 1 << 12, ///< RevFEatureType: Zicsr-extension
RV_ZIFENCEI = 1 << 13, ///< RevFeatureType: Zifencei-extension
RV_ZMMUL = 1 << 14, ///< RevFeatureType: Zmmul-extension
RV_ZAAMO = 1 << 15, ///< RevFeatureType: Zaamo-extension
RV_ZALRSC = 1 << 16, ///< RevFeatureType: Zalrsc-extension
RV_ZFA = 1 << 17, ///< RevFeatureType: Zfa-extension
RV_ZFH = 1 << 18, ///< RevFeatureType: H-extension
RV_ZFHMIN = 1 << 19, ///< RevFeatureRtpe: Zfhmin extension
RV_ZTSO = 1 << 20, ///< RevFeatureType: Ztso-extension
};

class RevFeature {
Expand Down Expand Up @@ -77,11 +78,8 @@ class RevFeature {
/// GetMaxCost: get the maximum cost
auto GetMaxCost() const { return MaxCost; }

/// IsRV32: Is the device an RV32
bool IsRV32() const { return xlen == 32; }

/// IsRV64: Is the device an RV64
bool IsRV64() const { return xlen == 64; }
bool IsRV64() const { return xlen >= 64; }

/// HasF: Does the device support F?
bool HasF() const { return IsModeEnabled( RV_F ); }
Expand Down
32 changes: 16 additions & 16 deletions include/RevInstHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ uint32_t fclass( T val ) {
/// Load template
template<typename T>
bool load( RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) {
if( sizeof( T ) < sizeof( int64_t ) && R->IsRV32 ) {
if( sizeof( T ) < sizeof( int64_t ) && !R->IsRV64 ) {
static constexpr RevFlag flags =
sizeof( T ) < sizeof( int32_t ) ? std::is_signed_v<T> ? RevFlag::F_SEXT32 : RevFlag::F_ZEXT32 : RevFlag::F_NONE;
auto rs1 = R->GetX<uint64_t>( Inst.rs1 ); // read once for tracer
Expand Down Expand Up @@ -284,7 +284,7 @@ enum class OpKind { Imm, Reg };
// The optional fourth parameter indicates W mode (32-bit on XLEN == 64)
template<template<class> class OP, OpKind KIND, template<class> class SIGN = std::make_signed_t, bool W_MODE = false>
bool oper( RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) {
if( !W_MODE && R->IsRV32 ) {
if( !W_MODE && !R->IsRV64 ) {
using T = SIGN<int32_t>;
T rs1 = R->GetX<T>( Inst.rs1 );
T rs2 = KIND == OpKind::Imm ? T( Inst.ImmSignExt( 12 ) ) : R->GetX<T>( Inst.rs2 );
Expand Down Expand Up @@ -323,16 +323,7 @@ struct ShiftRight {
// Computes the UPPER half of multiplication, based on signedness
template<bool rs1_is_signed, bool rs2_is_signed>
bool uppermul( RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) {
if( R->IsRV32 ) {
uint32_t rs1 = R->GetX<uint32_t>( Inst.rs1 );
uint32_t rs2 = R->GetX<uint32_t>( Inst.rs2 );
uint32_t mul = static_cast<uint32_t>( rs1 * int64_t( rs2 ) >> 32 );
if( rs1_is_signed && ( rs1 & ( uint32_t{ 1 } << 31 ) ) != 0 )
mul -= rs2;
if( rs2_is_signed && ( rs2 & ( uint32_t{ 1 } << 31 ) ) != 0 )
mul -= rs1;
R->SetX( Inst.rd, mul );
} else {
if( R->IsRV64 ) {
uint64_t rs1 = R->GetX<uint64_t>( Inst.rs1 );
uint64_t rs2 = R->GetX<uint64_t>( Inst.rs2 );
uint64_t mul = static_cast<uint64_t>( rs1 * __int128( rs2 ) >> 64 );
Expand All @@ -341,6 +332,15 @@ bool uppermul( RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) {
if( rs2_is_signed && ( rs2 & ( uint64_t{ 1 } << 63 ) ) != 0 )
mul -= rs1;
R->SetX( Inst.rd, mul );
} else {
uint32_t rs1 = R->GetX<uint32_t>( Inst.rs1 );
uint32_t rs2 = R->GetX<uint32_t>( Inst.rs2 );
uint32_t mul = static_cast<uint32_t>( rs1 * int64_t( rs2 ) >> 32 );
if( rs1_is_signed && ( rs1 & ( uint32_t{ 1 } << 31 ) ) != 0 )
mul -= rs2;
if( rs2_is_signed && ( rs2 & ( uint32_t{ 1 } << 31 ) ) != 0 )
mul -= rs1;
R->SetX( Inst.rd, mul );
}
R->AdvancePC( Inst );
return true;
Expand All @@ -354,7 +354,7 @@ enum class DivRem { Div, Rem };
// The optional third parameter indicates W mode (32-bit on XLEN == 64)
template<DivRem DIVREM, template<class> class SIGN, bool W_MODE = false>
bool divrem( RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) {
if( !W_MODE && R->IsRV32 ) {
if( !W_MODE && !R->IsRV64 ) {
using T = SIGN<int32_t>;
T rs1 = R->GetX<T>( Inst.rs1 );
T rs2 = R->GetX<T>( Inst.rs2 );
Expand Down Expand Up @@ -388,10 +388,10 @@ bool divrem( RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) {
template<template<class> class OP, template<class> class SIGN = std::make_unsigned_t>
bool bcond( RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) {
bool cond;
if( R->IsRV32 ) {
cond = OP()( R->GetX<SIGN<int32_t>>( Inst.rs1 ), R->GetX<SIGN<int32_t>>( Inst.rs2 ) );
} else {
if( R->IsRV64 ) {
cond = OP()( R->GetX<SIGN<int64_t>>( Inst.rs1 ), R->GetX<SIGN<int64_t>>( Inst.rs2 ) );
} else {
cond = OP()( R->GetX<SIGN<int32_t>>( Inst.rs1 ), R->GetX<SIGN<int32_t>>( Inst.rs2 ) );
}
if( cond ) {
R->SetPC( R->GetPC() + Inst.ImmSignExt( 13 ) );
Expand Down
50 changes: 25 additions & 25 deletions include/RevInstTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
#define DECODE_FUNCT3( x ) ( ( ( x ) >> ( 12 ) ) & ( 0b111 ) )

#define DECODE_RM( x ) static_cast<FRMode>( DECODE_FUNCT3( x ) )
#define DECODE_RL( x ) ( ( ( x ) >> ( 25 ) ) & ( 0b1 ) )
#define DECODE_AQ( x ) ( ( ( x ) >> ( 26 ) ) & ( 0b1 ) )
#define DECODE_RL( x ) ( ( ( x ) >> 25 & 0b1 ) != 0 )
#define DECODE_AQ( x ) ( ( ( x ) >> 26 & 0b1 ) != 0 )

namespace SST::RevCPU {

Expand Down Expand Up @@ -79,29 +79,29 @@ enum RevImmFunc : int { ///< Rev Immediate Values
*
*/
struct RevInst {
uint8_t opcode = 0; ///< RevInst: opcode
uint8_t funct2 = 0; ///< RevInst: compressed funct2 value
uint8_t funct3 = 0; ///< RevInst: funct3 value
uint8_t funct4 = 0; ///< RevInst: compressed funct4 value
uint8_t funct6 = 0; ///< RevInst: compressed funct6 value
uint8_t funct2or7 = 0; ///< RevInst: uncompressed funct2 or funct7 value
uint64_t rd = ~0; ///< RevInst: rd value
uint64_t rs1 = ~0; ///< RevInst: rs1 value
uint64_t rs2 = ~0; ///< RevInst: rs2 value
uint64_t rs3 = ~0; ///< RevInst: rs3 value
uint64_t imm = 0; ///< RevInst: immediate value
bool raisefpe = 0; ///< RevInst: raises FP exceptions
FRMode rm{ FRMode::None }; ///< RevInst: floating point rounding mode
uint8_t aq = 0; ///< RevInst: aq field for atomic instructions
uint8_t rl = 0; ///< RevInst: rl field for atomic instructions
uint16_t offset = 0; ///< RevInst: compressed offset
uint16_t jumpTarget = 0; ///< RevInst: compressed jumpTarget
uint8_t instSize = 0; ///< RevInst: size of the instruction in bytes
bool compressed = 0; ///< RevInst: determines if the instruction is compressed
uint32_t cost = 0; ///< RevInst: the cost to execute this instruction, in clock cycles
unsigned entry = 0; ///< RevInst: Where to find this instruction in the InstTables
uint16_t hart = 0; ///< RevInst: What hart is this inst being executed on
bool isCoProcInst = 0; ///< RevInst: whether instruction is coprocessor instruction
uint8_t opcode = 0; ///< RevInst: opcode
uint8_t funct2 = 0; ///< RevInst: compressed funct2 value
uint8_t funct3 = 0; ///< RevInst: funct3 value
uint8_t funct4 = 0; ///< RevInst: compressed funct4 value
uint8_t funct6 = 0; ///< RevInst: compressed funct6 value
uint8_t funct2or7 = 0; ///< RevInst: uncompressed funct2 or funct7 value
uint64_t rd = ~0; ///< RevInst: rd value
uint64_t rs1 = ~0; ///< RevInst: rs1 value
uint64_t rs2 = ~0; ///< RevInst: rs2 value
uint64_t rs3 = ~0; ///< RevInst: rs3 value
uint64_t imm = 0; ///< RevInst: immediate value
bool raisefpe = 0; ///< RevInst: raises FP exceptions
FRMode rm{ FRMode::None }; ///< RevInst: floating point rounding mode
bool aq = false; ///< RevInst: aqr field for atomic instructions
bool rl = false; ///< RevInst: rel field for atomic instructions
uint16_t offset = 0; ///< RevInst: compressed offset
uint16_t jumpTarget = 0; ///< RevInst: compressed jumpTarget
uint8_t instSize = 0; ///< RevInst: size of the instruction in bytes
bool compressed = 0; ///< RevInst: determines if the instruction is compressed
uint32_t cost = 0; ///< RevInst: the cost to execute this instruction, in clock cycles
unsigned entry = 0; ///< RevInst: Where to find this instruction in the InstTables
uint16_t hart = 0; ///< RevInst: What hart is this inst being executed on
bool isCoProcInst = 0; ///< RevInst: whether instruction is coprocessor instruction

explicit RevInst() = default; // prevent aggregate initialization

Expand Down
36 changes: 10 additions & 26 deletions include/RevMem.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,17 +203,11 @@ class RevMem {
return ReadMem( Hart, Addr, sizeof( T ), Target, req, flags );
}

/// RevMem: template LOAD RESERVE memory interface
template<typename T>
bool LR( unsigned Hart, uint64_t Addr, T* Target, uint8_t aq, uint8_t rl, const MemReq& req, RevFlag flags ) {
return LRBase( Hart, Addr, sizeof( T ), Target, aq, rl, req, flags );
}
/// RevMem: LOAD RESERVE memory interface
void LR( unsigned hart, uint64_t addr, size_t len, void* target, const MemReq& req, RevFlag flags );

/// RevMem: template STORE CONDITIONAL memory interface
template<typename T>
bool SC( unsigned Hart, uint64_t Addr, T* Data, T* Target, uint8_t aq, uint8_t rl, RevFlag flags ) {
return SCBase( Hart, Addr, sizeof( T ), Data, Target, aq, rl, flags );
}
/// RevMem: STORE CONDITIONAL memory interface
bool SC( unsigned Hart, uint64_t addr, size_t len, void* data, RevFlag flags );

/// RevMem: template AMO memory interface
template<typename T>
Expand Down Expand Up @@ -246,15 +240,12 @@ class RevMem {
// ----------------------------------------------------
// ---- Atomic/Future/LRSC Interfaces
// ----------------------------------------------------
/// RevMem: Add a memory reservation for the target address
bool LRBase( unsigned Hart, uint64_t Addr, size_t Len, void* Data, uint8_t aq, uint8_t rl, const MemReq& req, RevFlag flags );

/// RevMem: Clear a memory reservation for the target address
bool SCBase( unsigned Hart, uint64_t Addr, size_t Len, void* Data, void* Target, uint8_t aq, uint8_t rl, RevFlag flags );

/// RevMem: Initiated an AMO request
bool AMOMem( unsigned Hart, uint64_t Addr, size_t Len, void* Data, void* Target, const MemReq& req, RevFlag flags );

/// RevMem: Invalidate Matching LR reservations
bool InvalidateLRReservations( unsigned hart, uint64_t addr, size_t len );

/// RevMem: Initiates a future operation [RV64P only]
bool SetFuture( uint64_t Addr );

Expand Down Expand Up @@ -424,16 +415,9 @@ class RevMem {
uint64_t heapstart{}; ///< RevMem: top of the stack
uint64_t stacktop{}; ///< RevMem: top of the stack

std::vector<uint64_t> FutureRes{}; ///< RevMem: future operation reservations

// these are LRSC tuple index macros
#define LRSC_HART 0
#define LRSC_ADDR 1
#define LRSC_AQRL 2
#define LRSC_VAL 3
std::vector<std::tuple<unsigned, uint64_t, unsigned, uint64_t*>> LRSC{}; ///< RevMem: load reserve/store conditional vector

}; // class RevMem
std::vector<uint64_t> FutureRes{}; ///< RevMem: future operation reservations
std::unordered_map<unsigned, std::pair<uint64_t, size_t>> LRSC{}; ///< RevMem: load reserve/store conditional set
}; // class RevMem

} // namespace SST::RevCPU

Expand Down
4 changes: 4 additions & 0 deletions include/RevMemCtrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ constexpr bool RevFlagHas( RevFlag flag, RevFlag has ) {
return ( static_cast<uint32_t>( flag ) & static_cast<uint32_t>( has ) ) != 0;
}

inline void RevFlagSet( RevFlag& flag, RevFlag set ) {
flag = RevFlag{ uint32_t( flag ) | uint32_t( set ) };
}

/// RevFlag: Handle flag response
void RevHandleFlagResp( void* target, size_t size, RevFlag flags );

Expand Down
Loading

0 comments on commit c3dee3c

Please sign in to comment.