simX refactoring + removed oldRTL + CSR updates

This commit is contained in:
Blaise Tine
2021-02-06 12:52:54 -08:00
parent 111cc29482
commit 6c1dc96626
131 changed files with 4014 additions and 12138 deletions

1
simX/.gitignore vendored
View File

@@ -1 +0,0 @@
obj_dir

View File

View File

@@ -1,12 +0,0 @@
Copyright (c) 2011, Georgia Institute of Technology
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,37 +1,34 @@
CFLAGS += -std=c++11 -O2 -Wall -Wextra -Wfatal-errors
#CFLAGS += -std=c++11 -g -O0 -Wall -Wextra -Wfatal-errors
#CXXFLAGS += -std=c++11 -O2 -Wall -Wextra -Wfatal-errors
CXXFLAGS += -std=c++11 -g -O0 -Wall -Wextra -Wfatal-errors
CFLAGS += -Wno-aligned-new -Wno-maybe-uninitialized
CXXFLAGS += -Wno-aligned-new -Wno-maybe-uninitialized
CXXFLAGS += -I. -I../hw
CXXFLAGS += -DDUMP_PERF_STATS
CFLAGS += -I../../hw
LDFLAGS +=
TOP = cache_simX
TOP = vx_cache_sim
RTL_DIR = ../hw/old_rtl
RTL_DIR = ../hw/rtl
SRCS = simX.cpp args.cpp mem.cpp core.cpp instruction.cpp enc.cpp util.cpp
PROJECT = simX
RTL_INCLUDE=-I$(RTL_DIR) -I$(RTL_DIR)/interfaces -I$(RTL_DIR)/cache -I$(RTL_DIR)/shared_memory
VL_FLAGS += -O2 --language 1800-2009 --assert
VL_FLAGS += -Wno-DECLFILENAME
VL_FLAGS += --x-initial unique --x-assign unique
VL_FLAGS += -Wno-UNOPTFLAT -Wno-WIDTH
SRCS = util.cpp args.cpp mem.cpp core.cpp warp.cpp instr.cpp decode.cpp execute.cpp simX.cpp
# Debugigng
ifdef DEBUG
VL_FLAGS += -DVCD_OUTPUT --trace --trace-structs $(DBG_FLAGS)
CFLAGS += -DVCD_OUTPUT $(DBG_FLAGS)
CXXFLAGS += $(DBG_FLAGS)
else
VL_FLAGS += -DNDEBUG
CFLAGS += -DNDEBUG
CXXFLAGS += -DNDEBUG
endif
all: simX
all: $(PROJECT)
simX:
verilator --exe --cc $(TOP) --top-module $(TOP) $(RTL_INCLUDE) $(VL_FLAGS) $(SRCS) -CFLAGS '$(CFLAGS)'
make -j -C obj_dir -f V$(TOP).mk
$(PROJECT): $(SRCS)
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@
.depend: $(SRCS)
$(CXX) $(CXXFLAGS) -MM $^ > .depend;
clean:
rm -rf obj_dir
rm -rf $(PROJECT) *.o .depend

View File

@@ -1,14 +0,0 @@
- Anonymous chunks whose names are not saved by the object writer.
- 32-bit instruction encoding for larger-pointered architecture versions.
- HOFDump mode for HARPTool/HOFTool
- Make operation information tables into member functions of Instruction, if
possible.
- Anonymous assigned values in the assembler.
- References (pointers) as .word directive contents in the assembler.
- Instruction validation before encoding.
- Make readError in obj.cpp throw something instead of printing a message and
exiting.
- Limit checking for byte/word encoders (e.g. 255 pRegs, 256 regs for byte)
- Eliminate the tmp_buf nonsense from the chunk encoder.
- Loosen arch restrictions imposed for interoperability (the number of lanes is
typically unimportant)

166
simX/archdef.h Normal file
View File

@@ -0,0 +1,166 @@
#pragma once
#include <string>
#include <sstream>
#include <cstdlib>
#include <stdio.h>
#include "types.h"
namespace vortex {
class ArchDef {
public:
struct Undefined {};
ArchDef(const std::string &s,
int num_cores,
int num_warps,
int num_threads) {
std::istringstream iss(s.c_str());
wordSize_ = 4;
encChar_ = 'w';
numRegs_ = 32;
numPRegs_ = 0;
numCores_ = num_cores;
numWarps_ = num_warps;
numThreads_ = num_threads;
extent_ = EXT_END;
}
operator std::string () const {
if (extent_ == EXT_NULL)
return "";
std::ostringstream oss;
if (extent_ >= EXT_WORDSIZE) oss << wordSize_;
if (extent_ >= EXT_ENC ) oss << encChar_;
if (extent_ >= EXT_REGS ) oss << numRegs_;
if (extent_ >= EXT_PREGS ) oss << '/' << numPRegs_;
if (extent_ >= EXT_THREADS ) oss << '/' << numThreads_;
if (extent_ >= EXT_WARPS ) oss << '/' << numWarps_;
if (extent_ >= EXT_CORES ) oss << '/' << numCores_;
return oss.str();
}
bool operator==(const ArchDef &r) const {
Extent minExtent(r.extent_ > extent_ ? extent_ : r.extent_);
// Can't be equal if we can't specify a binary encoding at all.
if (minExtent < EXT_PREGS)
return false;
if (minExtent >= EXT_WORDSIZE) {
if (wordSize_!=r.wordSize_)
return false;
}
if (minExtent >= EXT_ENC) {
if (encChar_ != r.encChar_)
return false;
}
if (minExtent >= EXT_REGS) {
if (numRegs_ != r.numRegs_)
return false;
}
if (minExtent >= EXT_PREGS) {
if (numPRegs_ != r.numPRegs_)
return false;
}
if (minExtent >= EXT_THREADS) {
if (numThreads_ != r.numThreads_)
return false;
}
if (minExtent >= EXT_WARPS) {
if (numWarps_ != r.numWarps_)
return false;
}
if (minExtent >= EXT_CORES) {
if (numCores_ != r.numCores_)
return false;
}
return true;
}
bool operator!=(const ArchDef &r) const {
return !(*this == r);
}
Size getWordSize() const {
if (extent_ < EXT_WORDSIZE)
throw Undefined();
return wordSize_;
}
char getEncChar() const {
if ((extent_ < EXT_ENC) || (encChar_ == 'x'))
throw Undefined();
return encChar_;
}
RegNum getNumRegs() const {
if (extent_ < EXT_REGS)
throw Undefined();
return numRegs_;
}
RegNum getNumPRegs() const {
if (extent_ < EXT_PREGS)
throw Undefined();
return numPRegs_;
}
ThdNum getNumThreads() const {
if (extent_ < EXT_THREADS)
throw Undefined();
return numThreads_;
}
ThdNum getNumWarps() const {
if (extent_ < EXT_WARPS)
throw Undefined();
return numWarps_;
}
ThdNum getNumCores() const {
if (extent_ < EXT_CORES)
throw Undefined();
return numCores_;
}
bool is_cpu_mode() const {
return cpu_mode_;
}
private:
enum Extent {
EXT_NULL,
EXT_WORDSIZE,
EXT_ENC,
EXT_REGS,
EXT_PREGS,
EXT_THREADS,
EXT_WARPS,
EXT_CORES,
EXT_END
};
Extent extent_;
Size wordSize_;
ThdNum numThreads_;
ThdNum numWarps_;
ThdNum numCores_;
RegNum numRegs_;
ThdNum numPRegs_;
char encChar_;
bool cpu_mode_;
};
}

View File

@@ -1,39 +1,34 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#include "include/args.h"
#include <iostream>
#include <string>
#include "args.h"
using namespace HarpTools;
using namespace vortex;
using std::string;
std::string CommandLineArg::helpString;
std::map<string, CommandLineArg *> CommandLineArg::longArgs;
std::map<string, CommandLineArg *> CommandLineArg::shortArgs;
std::string CommandLineArg::helpString_;
std::unordered_map<string, CommandLineArg *> CommandLineArg::longArgs_;
std::unordered_map<string, CommandLineArg *> CommandLineArg::shortArgs_;
CommandLineArg::CommandLineArg(string s, string l, const char *helpText)
{
helpString += helpText;
longArgs[l] = this;
shortArgs[s] = this;
CommandLineArg::CommandLineArg(string s, string l, const char *helpText) {
helpString_ += helpText;
longArgs_[l] = this;
shortArgs_[s] = this;
}
CommandLineArg::CommandLineArg(string l, const char *helpText) {
helpString += helpText;
longArgs[l] = this;
helpString_ += helpText;
longArgs_[l] = this;
}
void CommandLineArg::readArgs(int argc, char **argv) {
for (int i = 0; i < argc; i++) {
std::map<string, CommandLineArg *>::iterator
s = shortArgs.find(std::string(argv[i])),
l = longArgs.find(std::string(argv[i]));
std::unordered_map<string, CommandLineArg *>::iterator
s = shortArgs_.find(std::string(argv[i])),
l = longArgs_.find(std::string(argv[i]));
if (s != shortArgs.end()) {
if (s != shortArgs_.end()) {
i += s->second->read(argc - i, &argv[i]);
} else if (l != longArgs.end()) {
} else if (l != longArgs_.end()) {
i += l->second->read(argc - i, &argv[i]);
} else {
throw BadArg(string(argv[i]));
@@ -42,11 +37,11 @@ void CommandLineArg::readArgs(int argc, char **argv) {
}
void CommandLineArg::clearArgs() {
shortArgs.clear();
longArgs.clear();
helpString = "";
shortArgs_.clear();
longArgs_.clear();
helpString_ = "";
}
void CommandLineArg::showHelp(std::ostream &os) {
os << helpString;
os << helpString_;
}

64
simX/args.h Normal file
View File

@@ -0,0 +1,64 @@
#pragma once
#include <iostream>
#include <string>
#include <sstream>
#include <unordered_map>
#include "util.h"
namespace vortex {
struct BadArg { BadArg(std::string s) : arg(s) {} std::string arg; };
class CommandLineArg {
public:
CommandLineArg(std::string s, std::string l, const char *helpText);
CommandLineArg(std::string l, const char *helpText);
virtual int read(int argc, char** argv) = 0;
static void readArgs(int argc, char **argv);
static void clearArgs();
static void showHelp(std::ostream &os);
private:
static std::string helpString_;
static std::unordered_map<std::string, CommandLineArg *> longArgs_;
static std::unordered_map<std::string, CommandLineArg *> shortArgs_;
};
template <typename T> class CommandLineArgSetter : public CommandLineArg {
public:
CommandLineArgSetter(std::string s, std::string l, const char *ht, T &x) :
CommandLineArg(s, l, ht), arg_(x) {}
CommandLineArgSetter(std::string l, const char *ht, T &x) :
CommandLineArg(l, ht), arg_(x) {}
int read(int argc, char **argv) {
__unused(argc);
std::istringstream iss(argv[1]);
iss >> arg_;
return 1;
}
private:
T &arg_;
};
class CommandLineArgFlag : public CommandLineArg {
public:
CommandLineArgFlag(std::string s, std::string l, const char *ht, bool &x) :
CommandLineArg(s, l, ht), arg_(x) { arg_ = false; }
CommandLineArgFlag(std::string l, const char *ht, bool &x) :
CommandLineArg(l, ht), arg_(x) { arg_ = false; }
int read(int argc, char **argv) {
__unused(argc, argv);
arg_ = true;
return 0;
}
private:
bool &arg_;
};
}

View File

@@ -1,113 +0,0 @@
`include "VX_define.v"
module cache_simX (
input wire clk, // Clock
input wire reset,
// Icache
input wire[31:0] icache_pc_addr,
input wire icache_valid_pc_addr,
output wire icache_stall,
// Dcache
input wire[2:0] dcache_mem_read,
input wire[2:0] dcache_mem_write,
input wire dcache_in_valid[`NT_M1:0],
input wire[31:0] dcache_in_addr[`NT_M1:0],
output wire dcache_stall
);
//////////////////// ICACHE ///////////////////
VX_icache_request_inter VX_icache_req;
assign VX_icache_req.pc_address = icache_pc_addr;
assign VX_icache_req.out_cache_driver_in_mem_read = (icache_valid_pc_addr) ? `LW_MEM_READ : `NO_MEM_READ;
assign VX_icache_req.out_cache_driver_in_mem_write = `NO_MEM_WRITE;
assign VX_icache_req.out_cache_driver_in_valid = icache_valid_pc_addr;
assign VX_icache_req.out_cache_driver_in_data = 0;
VX_icache_response_inter VX_icache_rsp;
assign icache_stall = VX_icache_rsp.delay;
VX_dram_req_rsp_inter #(
.NUMBER_BANKS(`ICACHE_BANKS),
.NUM_WORDS_PER_BLOCK(`ICACHE_NUM_WORDS_PER_BLOCK)
) VX_dram_req_rsp_icache();
reg icache_i_m_ready;
assign VX_dram_req_rsp_icache.i_m_ready = icache_i_m_ready;
//////////////////// DCACHE ///////////////////
VX_dcache_request_inter VX_dcache_req;
assign VX_dcache_req.out_cache_driver_in_mem_read = dcache_mem_read;
assign VX_dcache_req.out_cache_driver_in_mem_write = dcache_mem_write;
assign VX_dcache_req.out_cache_driver_in_data = 0;
genvar curr_t;
for (curr_t = 0; curr_t < `NT; curr_t=curr_t+1)
begin
assign VX_dcache_req.out_cache_driver_in_address[curr_t] = dcache_in_addr[curr_t];
assign VX_dcache_req.out_cache_driver_in_valid[curr_t] = dcache_in_valid[curr_t];
end
VX_dcache_response_inter VX_dcache_rsp;
assign dcache_stall = VX_dcache_rsp.delay;
VX_dram_req_rsp_inter #(
.NUMBER_BANKS(`DCACHE_BANKS),
.NUM_WORDS_PER_BLOCK(`DCACHE_NUM_WORDS_PER_BLOCK)
) VX_dram_req_rsp();
reg dcache_i_m_ready;
assign VX_dram_req_rsp.i_m_ready = dcache_i_m_ready;
VX_dmem_controller dmem_ctrl (
.clk (clk),
.reset (reset),
.VX_dram_req_rsp (VX_dram_req_rsp),
.VX_dram_req_rsp_icache(VX_dram_req_rsp_icache),
.VX_icache_req (VX_icache_req),
.VX_icache_rsp (VX_icache_rsp),
.VX_dcache_req (VX_dcache_req),
.VX_dcache_rsp (VX_dcache_rsp)
);
always @(posedge clk, posedge reset) begin
if (reset)
begin
icache_i_m_ready = 0;
dcache_i_m_ready = 0;
end else begin
if (VX_dram_req_rsp_icache.o_m_valid) begin
icache_i_m_ready = 1;
// $display("cache_simX.v: setting icache_i_m_ready = %d", icache_i_m_ready);
end else if (icache_i_m_ready) begin
icache_i_m_ready = 0;
end else begin
icache_i_m_ready = 0;
end
if (VX_dram_req_rsp.o_m_valid) begin
dcache_i_m_ready = 1;
end else if (dcache_i_m_ready) begin
dcache_i_m_ready = 0;
end else begin
dcache_i_m_ready = 0;
end
end
end
endmodule

File diff suppressed because it is too large Load Diff

100
simX/core.h Normal file
View File

@@ -0,0 +1,100 @@
#pragma once
#include <string>
#include <vector>
#include <stack>
#include <unordered_map>
#include <set>
#include "debug.h"
#include "types.h"
#include "archdef.h"
#include "decode.h"
#include "mem.h"
#include "warp.h"
#include "trace.h"
namespace vortex {
class Core {
public:
Core(const ArchDef &arch, Decoder &decoder, MemoryUnit &mem, Word id = 0);
~Core();
bool interrupt(Word r0);
bool running() const;
void getCacheDelays(trace_inst_t *);
void warpScheduler();
void fetch();
void decode();
void scheduler();
void execute_unit();
void load_store();
void writeback();
void step();
void printStats() const;
Word id() const {
return id_;
}
Warp& warp(int i) {
return warps_[i];
}
Decoder& decoder() {
return decoder_;
}
MemoryUnit& mem() {
return mem_;
}
const ArchDef& arch() const {
return arch_;
}
Word interruptEntry() const {
return interruptEntry_;
}
unsigned long num_instructions() const {
return num_instructions_;
}
unsigned long num_steps() const {
return steps_;
}
private:
bool renameTable_[32][32];
bool vecRenameTable_[32];
bool stalled_warps_[32];
bool foundSchedule_;
Word id_;
const ArchDef &arch_;
Decoder &decoder_;
MemoryUnit &mem_;
std::vector<Warp> warps_;
std::unordered_map<Word, std::set<Warp *>> barriers_;
int schedule_w_;
uint64_t steps_;
uint64_t num_instructions_;
Word interruptEntry_;
bool release_warp_;
int release_warp_num_;
trace_inst_t inst_in_fetch_;
trace_inst_t inst_in_decode_;
trace_inst_t inst_in_scheduler_;
trace_inst_t inst_in_exe_;
trace_inst_t inst_in_lsu_;
trace_inst_t inst_in_wb_;
};
} // namespace vortex

42
simX/debug.h Normal file
View File

@@ -0,0 +1,42 @@
#pragma once
//#define USE_DEBUG 9
#ifdef USE_DEBUG
#include <iostream>
#include <iomanip>
#define DX(x) x
#define D(lvl, x) do { \
if ((lvl) <= USE_DEBUG) { \
std::cout << "DEBUG " << __FILE__ << ':' << std::dec << __LINE__ << ": " << x << std::endl; \
} \
} while(0)
#define DPH(lvl, x) do { \
if ((lvl) <= USE_DEBUG) { \
std::cout << "DEBUG " << __FILE__ << ':' << std::dec << __LINE__ << ": " << x; \
} \
} while(0)
#define DPN(lvl, x) do { \
if ((lvl) <= USE_DEBUG) { \
std::cout << x; \
} \
} while(0)
#define D_RAW(x) do { \
std::cout << x; \
} while (0)
#else
#define DX(x)
#define D(lvl, x) do {} while(0)
#define DPH(lvl, x) do {} while(0)
#define DPN(lvl, x) do {} while(0)
#define D_RAW(x) do {} while(0)
#endif

293
simX/decode.cpp Normal file
View File

@@ -0,0 +1,293 @@
#include <iostream>
#include <string>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <vector>
#include <unordered_map>
#include "debug.h"
#include "types.h"
#include "util.h"
#include "decode.h"
#include "archdef.h"
#include "instr.h"
#include "trace.h"
using namespace vortex;
struct InstTableEntry_t {
const char *opString;
bool controlFlow;
InstType iType;
};
static const std::unordered_map<int, struct InstTableEntry_t> sc_instTable = {
{Opcode::NOP, {"nop" , false, InstType::N_TYPE}},
{Opcode::R_INST, {"r_type", false, InstType::R_TYPE}},
{Opcode::L_INST, {"load" , false, InstType::I_TYPE}},
{Opcode::I_INST, {"i_type", false, InstType::I_TYPE}},
{Opcode::S_INST, {"store" , false, InstType::S_TYPE}},
{Opcode::B_INST, {"branch", true , InstType::B_TYPE}},
{Opcode::LUI_INST, {"lui" , false, InstType::U_TYPE}},
{Opcode::AUIPC_INST, {"auipc" , false, InstType::U_TYPE}},
{Opcode::JAL_INST, {"jal" , true , InstType::J_TYPE}},
{Opcode::JALR_INST, {"jalr" , true , InstType::I_TYPE}},
{Opcode::SYS_INST, {"SYS" , true , InstType::I_TYPE}},
{Opcode::FENCE, {"fence" , true , InstType::I_TYPE}},
{Opcode::PJ_INST, {"pred j", true , InstType::R_TYPE}},
{Opcode::GPGPU, {"gpgpu" , false, InstType::R_TYPE}},
{Opcode::VSET_ARITH, {"vsetvl", false, InstType::V_TYPE}},
{Opcode::VL, {"vl" , false, InstType::V_TYPE}},
{Opcode::VS, {"vs" , false, InstType::V_TYPE}}
};
std::ostream &vortex::operator<<(std::ostream &os, Instr &instr) {
os << std::dec << sc_instTable.at(instr.opcode_).opString;
return os;
}
Decoder::Decoder(const ArchDef &arch) {
inst_s_ = arch.getWordSize() * 8;
opcode_s_ = 7;
reg_s_ = 5;
func3_s_ = 3;
mop_s_ = 3;
vmask_s_ = 1;
shift_opcode_ = 0;
shift_rd_ = opcode_s_;
shift_func3_ = opcode_s_ + reg_s_;
shift_rs1_ = opcode_s_ + reg_s_ + func3_s_;
shift_rs2_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_;
shift_func7_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_ + reg_s_;
shift_j_u_immed_ = opcode_s_ + reg_s_;
shift_s_b_immed_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_ + reg_s_;
shift_i_immed_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_;
shift_vset_immed_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_;
shift_vmask_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_ + reg_s_;
shift_vmop_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_ + reg_s_ + vmask_s_;
shift_vnf_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_ + reg_s_ + vmask_s_ + mop_s_;
shift_func6_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_ + reg_s_ + 1;
shift_vset_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_ + reg_s_ + 6;
reg_mask_ = 0x1f;
func3_mask_ = 0x7;
func6_mask_ = 0x3f;
func7_mask_ = 0x7f;
opcode_mask_ = 0x7f;
i_imm_mask_ = 0xfff;
s_imm_mask_ = 0xfff;
b_imm_mask_ = 0x1fff;
u_imm_mask_ = 0xfffff;
j_imm_mask_ = 0xfffff;
v_imm_mask_ = 0x7ff;
}
std::shared_ptr<Instr> Decoder::decode(const std::vector<Byte> &v, Size &idx, trace_inst_t *trace_inst) {
Word code(readWord(v, idx, inst_s_ / 8));
// std::cout << "code: " << (int) code << " v: " << v << " indx: " << idx << "\n";
auto instr = std::make_shared<Instr>();
Opcode op = (Opcode)((code >> shift_opcode_) & opcode_mask_);
// std::cout << "opcode: " << op << "\n";
instr->setOpcode(op);
Word imeed, dest_bits, imm_bits, bit_11, bits_4_1, bit_10_5,
bit_12, bits_19_12, bits_10_1, bit_20, unordered, func3;
// std::cout << "op: " << std::hex << op << " what " << sc_instTable[op].iType << "\n";
switch (sc_instTable.at(op).iType) {
case InstType::N_TYPE:
break;
case InstType::R_TYPE:
instr->setPred((code >> shift_rs1_) & reg_mask_);
instr->setDestReg((code >> shift_rd_) & reg_mask_);
instr->setSrcReg((code >> shift_rs1_) & reg_mask_);
instr->setSrcReg((code >> shift_rs2_) & reg_mask_);
instr->setFunc3((code >> shift_func3_) & func3_mask_);
instr->setFunc7((code >> shift_func7_) & func7_mask_);
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code >> shift_rs1_) & reg_mask_);
trace_inst->rs2 = ((code >> shift_rs2_) & reg_mask_);
trace_inst->rd = ((code >> shift_rd_) & reg_mask_);
break;
case InstType::I_TYPE:
instr->setDestReg((code >> shift_rd_) & reg_mask_);
instr->setSrcReg((code >> shift_rs1_) & reg_mask_);
instr->setFunc7((code >> shift_func7_) & func7_mask_);
func3 = (code >> shift_func3_) & func3_mask_;
instr->setFunc3(func3);
if ((func3 == 5) && (op != L_INST)) {
// std::cout << "func7: " << func7 << "\n";
instr->setSrcImm(signExt(((code >> shift_rs2_) & reg_mask_), 5, reg_mask_));
} else {
instr->setSrcImm(signExt(code >> shift_i_immed_, 12, i_imm_mask_));
}
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code >> shift_rs1_) & reg_mask_);
trace_inst->rd = ((code >> shift_rd_) & reg_mask_);
break;
case InstType::S_TYPE:
// std::cout << "************STORE\n";
instr->setSrcReg((code >> shift_rs1_) & reg_mask_);
instr->setSrcReg((code >> shift_rs2_) & reg_mask_);
instr->setFunc3((code >> shift_func3_) & func3_mask_);
dest_bits = (code >> shift_rd_) & reg_mask_;
imm_bits = (code >> shift_s_b_immed_ & func7_mask_);
imeed = (imm_bits << reg_s_) | dest_bits;
// std::cout << "ENC: store imeed: " << imeed << "\n";
instr->setSrcImm(signExt(imeed, 12, s_imm_mask_));
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code >> shift_rs1_) & reg_mask_);
trace_inst->rs2 = ((code >> shift_rs2_) & reg_mask_);
break;
case InstType::B_TYPE:
instr->setSrcReg((code >> shift_rs1_) & reg_mask_);
instr->setSrcReg((code >> shift_rs2_) & reg_mask_);
instr->setFunc3((code >> shift_func3_) & func3_mask_);
dest_bits = (code >> shift_rd_) & reg_mask_;
imm_bits = (code >> shift_s_b_immed_ & func7_mask_);
bit_11 = dest_bits & 0x1;
bits_4_1 = dest_bits >> 1;
bit_10_5 = imm_bits & 0x3f;
bit_12 = imm_bits >> 6;
imeed = 0 | (bits_4_1 << 1) | (bit_10_5 << 5) | (bit_11 << 11) | (bit_12 << 12);
instr->setSrcImm(signExt(imeed, 13, b_imm_mask_));
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code >> shift_rs1_) & reg_mask_);
trace_inst->rs2 = ((code >> shift_rs2_) & reg_mask_);
break;
case InstType::U_TYPE:
instr->setDestReg((code >> shift_rd_) & reg_mask_);
instr->setSrcImm(signExt(code >> shift_j_u_immed_, 20, u_imm_mask_));
trace_inst->valid_inst = true;
trace_inst->rd = ((code >> shift_rd_) & reg_mask_);
break;
case InstType::J_TYPE:
instr->setDestReg((code >> shift_rd_) & reg_mask_);
// [20 | 10:1 | 11 | 19:12]
unordered = code >> shift_j_u_immed_;
bits_19_12 = unordered & 0xff;
bit_11 = (unordered >> 8) & 0x1;
bits_10_1 = (unordered >> 9) & 0x3ff;
bit_20 = (unordered >> 19) & 0x1;
imeed = 0 | (bits_10_1 << 1) | (bit_11 << 11) | (bits_19_12 << 12) | (bit_20 << 20);
if (bit_20) {
imeed |= ~j_imm_mask_;
}
instr->setSrcImm(imeed);
trace_inst->valid_inst = true;
trace_inst->rd = ((code >> shift_rd_) & reg_mask_);
break;
case InstType::V_TYPE:
D(3, "Entered here: instr type = vector" << op);
switch (op) {
case Opcode::VSET_ARITH: //TODO: arithmetic ops
instr->setDestReg((code >> shift_rd_) & reg_mask_);
instr->setSrcReg((code >> shift_rs1_) & reg_mask_);
func3 = (code >> shift_func3_) & func3_mask_;
instr->setFunc3(func3);
D(3, "Entered here: instr type = vector");
if (func3 == 7) {
D(3, "Entered here: imm instr");
instr->setVsetImm(!(code >> shift_vset_));
if (instr->getVsetImm()) {
Word immed = (code >> shift_rs2_) & v_imm_mask_;
D(3, "immed" << immed);
instr->setSrcImm(immed); //TODO
instr->setVlmul(immed & 0x3);
D(3, "lmul " << (immed & 0x3));
instr->setVediv((immed >> 4) & 0x3);
D(3, "ediv " << ((immed >> 4) & 0x3));
instr->setVsew((immed >> 2) & 0x3);
D(3, "sew " << ((immed >> 2) & 0x3));
} else {
instr->setSrcReg((code >> shift_rs2_) & reg_mask_);
trace_inst->rs2 = ((code >> shift_rs2_) & reg_mask_);
}
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code >> shift_rs1_) & reg_mask_);
trace_inst->rd = ((code >> shift_rd_) & reg_mask_);
} else {
instr->setSrcReg((code >> shift_rs2_) & reg_mask_);
instr->setVmask((code >> shift_vmask_) & 0x1);
instr->setFunc6((code >> shift_func6_) & func6_mask_);
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code >> shift_rs1_) & reg_mask_);
trace_inst->rs2 = ((code >> shift_rs2_) & reg_mask_);
trace_inst->rd = ((code >> shift_rd_) & reg_mask_);
}
break;
case Opcode::VL:
D(3, "vector load instr");
instr->setDestReg((code >> shift_rd_) & reg_mask_);
instr->setSrcReg((code >> shift_rs1_) & reg_mask_);
instr->setVlsWidth((code >> shift_func3_) & func3_mask_);
instr->setSrcReg((code >> shift_rs2_) & reg_mask_);
instr->setVmask((code >> shift_vmask_));
instr->setVmop((code >> shift_vmop_) & func3_mask_);
instr->setVnf((code >> shift_vnf_) & func3_mask_);
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code >> shift_rs1_) & reg_mask_);
trace_inst->vd = ((code >> shift_rd_) & reg_mask_);
//trace_inst->vs2 = ((code>>shift_rs2_) & reg_mask_);
break;
case Opcode::VS:
instr->setVs3((code >> shift_rd_) & reg_mask_);
instr->setSrcReg((code >> shift_rs1_) & reg_mask_);
instr->setVlsWidth((code >> shift_func3_) & func3_mask_);
instr->setSrcReg((code >> shift_rs2_) & reg_mask_);
instr->setVmask((code >> shift_vmask_));
instr->setVmop((code >> shift_vmop_) & func3_mask_);
instr->setVnf((code >> shift_vnf_) & func3_mask_);
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code >> shift_rs1_) & reg_mask_);
//trace_inst->vd = ((code>>shift_rd_) & reg_mask_);
trace_inst->vs1 = ((code >> shift_rd_) & reg_mask_); //vs3
break;
default:
std::cout << "Inavlid opcode.\n";
std::abort();
}
break;
default:
std::cout << "Unrecognized argument class in word decoder.\n";
std::abort();
}
D(2, "Decoded instr 0x" << std::hex << code << " into: " << instr << std::flush);
return instr;
}

58
simX/decode.h Normal file
View File

@@ -0,0 +1,58 @@
#pragma once
#include <vector>
#include <memory>
#include "util.h"
namespace vortex {
class ArchDef;
class Instr;
class trace_inst_t;
class Decoder {
public:
Decoder(const ArchDef &);
virtual std::shared_ptr<Instr> decode(const std::vector<Byte> &v, Size &n, trace_inst_t * trace_inst);
private:
Word inst_s_;
Word opcode_s_;
Word reg_s_;
Word func3_s_;
Word shift_opcode_;
Word shift_rd_;
Word shift_rs1_;
Word shift_rs2_;
Word shift_func3_;
Word shift_func7_;
Word shift_j_u_immed_;
Word shift_s_b_immed_;
Word shift_i_immed_;
Word reg_mask_;
Word func3_mask_;
Word func6_mask_;
Word func7_mask_;
Word opcode_mask_;
Word i_imm_mask_;
Word s_imm_mask_;
Word b_imm_mask_;
Word u_imm_mask_;
Word j_imm_mask_;
Word v_imm_mask_;
//Vector
Word shift_vset_;
Word shift_vset_immed_;
Word shift_vmask_;
Word shift_vmop_;
Word shift_vnf_;
Word shift_func6_;
Word vmask_s_;
Word mop_s_;
};
}

View File

@@ -1,328 +0,0 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#include <iostream>
#include <string>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <vector>
#include "include/debug.h"
#include "include/types.h"
#include "include/util.h"
#include "include/enc.h"
#include "include/archdef.h"
#include "include/instruction.h"
using namespace std;
using namespace Harp;
// ByteDecoder::ByteDecoder(const ArchDef &ad) {
// wordSize = ad.getWordSize();
// }
/*static void decodeError(string msg) {
cout << "Instruction decoder error: " << msg << '\n';
std::abort();
}*/
/*static unsigned ceilLog2(RegNum x) {
unsigned z = 0;
bool nonZeroInnerValues(false);
if (x == 0) return 0;
while (x != 1) {
z++;
if (x&1) nonZeroInnerValues = true;
x >>= 1;
}
if (nonZeroInnerValues) z++;
return z;
}*/
WordDecoder::WordDecoder(const ArchDef &arch) {
inst_s = arch.getWordSize() * 8;
opcode_s = 7;
reg_s = 5;
func3_s = 3;
mop_s = 3;
vmask_s = 1;
shift_opcode = 0;
shift_rd = opcode_s;
shift_func3 = opcode_s + reg_s;
shift_rs1 = opcode_s + reg_s + func3_s;
shift_rs2 = opcode_s + reg_s + func3_s + reg_s;
shift_func7 = opcode_s + reg_s + func3_s + reg_s + reg_s;
shift_j_u_immed = opcode_s + reg_s;
shift_s_b_immed = opcode_s + reg_s + func3_s + reg_s + reg_s;
shift_i_immed = opcode_s + reg_s + func3_s + reg_s;
shift_vset_immed = opcode_s + reg_s + func3_s + reg_s;
shift_vmask = opcode_s + reg_s + func3_s + reg_s + reg_s;
shift_vmop = opcode_s + reg_s + func3_s + reg_s + reg_s + vmask_s;
shift_vnf = opcode_s + reg_s + func3_s + reg_s + reg_s + vmask_s + mop_s;
shift_func6 = opcode_s + reg_s + func3_s + reg_s + reg_s + 1;
shift_vset = opcode_s + reg_s + func3_s + reg_s + reg_s + 6;
reg_mask = 0x1f;
func3_mask = 0x7;
func7_mask = 0x7f;
opcode_mask = 0x7f;
i_immed_mask = 0xfff;
s_immed_mask = 0xfff;
b_immed_mask = 0x1fff;
u_immed_mask = 0xfffff;
j_immed_mask = 0xfffff;
v_immed_mask = 0x7ff;
func6_mask = 0x3f;
}
static Word signExt(Word w, Size bit, Word mask) {
if (w>>(bit-1)) w |= ~mask;
return w;
}
Instruction *WordDecoder::decode(const std::vector<Byte> &v, Size &idx, trace_inst_t * trace_inst) {
Word code(readWord(v, idx, inst_s/8));
// std::cout << "code: " << (int) code << " v: " << v << " indx: " << idx << "\n";
Instruction &inst = * new Instruction();
// bool predicated = (code>>(n-1));
bool predicated = false;
if (predicated) { inst.setPred((code>>(inst_s-p-1))&pMask); }
Opcode op = (Opcode)((code>>shift_opcode)&opcode_mask);
// std::cout << "opcode: " << op << "\n";
inst.setOpcode(op);
bool usedImm(false);
Word imeed, dest_bits, imm_bits, bit_11, bits_4_1, bit_10_5,
bit_12, bits_19_12, bits_10_1, bit_20, unordered, func3;
// std::cout << "op: " << std::hex << op << " what " << instTable[op].iType << "\n";
switch(instTable[op].iType)
{
case InstType::N_TYPE:
break;
case InstType::R_TYPE:
inst.setPred((code>>shift_rs1) & reg_mask);
inst.setDestReg((code>>shift_rd) & reg_mask);
inst.setSrcReg((code>>shift_rs1) & reg_mask);
inst.setSrcReg((code>>shift_rs2) & reg_mask);
inst.setFunc3 ((code>>shift_func3) & func3_mask);
inst.setFunc7 ((code>>shift_func7) & func7_mask);
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code>>shift_rs1) & reg_mask);
trace_inst->rs2 = ((code>>shift_rs2) & reg_mask);
trace_inst->rd = ((code>>shift_rd) & reg_mask);
break;
case InstType::I_TYPE:
inst.setDestReg((code>>shift_rd) & reg_mask);
inst.setSrcReg((code>>shift_rs1) & reg_mask);
inst.setFunc7 ((code>>shift_func7) & func7_mask);
func3 = (code>>shift_func3) & func3_mask;
inst.setFunc3 (func3);
if ((func3 == 5) && (op != L_INST))
{
// std::cout << "func7: " << func7 << "\n";
inst.setSrcImm(signExt(((code>>shift_rs2)&reg_mask), 5, reg_mask));
}
else
{
inst.setSrcImm(signExt(code>>shift_i_immed, 12, i_immed_mask));
}
usedImm = true;
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code>>shift_rs1) & reg_mask);
trace_inst->rd = ((code>>shift_rd) & reg_mask);
break;
case InstType::S_TYPE:
// std::cout << "************STORE\n";
inst.setSrcReg((code>>shift_rs1) & reg_mask);
inst.setSrcReg((code>>shift_rs2) & reg_mask);
inst.setFunc3 ((code>>shift_func3) & func3_mask);
dest_bits = (code>>shift_rd) & reg_mask;
imm_bits = (code>>shift_s_b_immed & func7_mask);
imeed = (imm_bits << reg_s) | dest_bits;
// std::cout << "ENC: store imeed: " << imeed << "\n";
inst.setSrcImm(signExt(imeed, 12, s_immed_mask));
usedImm = true;
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code>>shift_rs1) & reg_mask);
trace_inst->rs2 = ((code>>shift_rs2) & reg_mask);
break;
case InstType::B_TYPE:
inst.setSrcReg((code>>shift_rs1) & reg_mask);
inst.setSrcReg((code>>shift_rs2) & reg_mask);
inst.setFunc3 ((code>>shift_func3) & func3_mask);
dest_bits = (code>>shift_rd) & reg_mask;
imm_bits = (code>>shift_s_b_immed & func7_mask);
bit_11 = dest_bits & 0x1;
bits_4_1 = dest_bits >> 1;
bit_10_5 = imm_bits & 0x3f;
bit_12 = imm_bits >> 6;
imeed = 0 | (bits_4_1 << 1) | (bit_10_5 << 5) | (bit_11 << 11) | (bit_12 << 12);
inst.setSrcImm(signExt(imeed, 13, b_immed_mask));
usedImm = true;
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code>>shift_rs1) & reg_mask);
trace_inst->rs2 = ((code>>shift_rs2) & reg_mask);
break;
case InstType::U_TYPE:
inst.setDestReg((code>>shift_rd) & reg_mask);
inst.setSrcImm(signExt(code>>shift_j_u_immed, 20, u_immed_mask));
usedImm = true;
trace_inst->valid_inst = true;
trace_inst->rd = ((code>>shift_rd) & reg_mask);
break;
case InstType::J_TYPE:
inst.setDestReg((code>>shift_rd) & reg_mask);
// [20 | 10:1 | 11 | 19:12]
unordered = code>>shift_j_u_immed;
bits_19_12 = unordered & 0xff;
bit_11 = (unordered>>8) & 0x1;
bits_10_1 = (unordered >> 9) & 0x3ff;
bit_20 = (unordered>>19) & 0x1;
imeed = 0 | (bits_10_1 << 1) | (bit_11 << 11) | (bits_19_12 << 12) | (bit_20 << 20);
if (bit_20)
{
imeed |= ~j_immed_mask;
}
// inst.setSrcImm(signExt(imeed, 20, j_immed_mask));
inst.setSrcImm(imeed);
usedImm = true;
trace_inst->valid_inst = true;
trace_inst->rd = ((code>>shift_rd) & reg_mask);
break;
case InstType::V_TYPE:
D(3, "Entered here: instr type = vector" << op);
switch (op) {
case Opcode::VSET_ARITH: //TODO: arithmetic ops
inst.setDestReg((code>>shift_rd) & reg_mask);
inst.setSrcReg((code>>shift_rs1) & reg_mask);
func3 = (code>>shift_func3) & func3_mask;
inst.setFunc3 (func3);
D(3, "Entered here: instr type = vector");
if(func3 == 7) {
D(3, "Entered here: imm instr");
inst.setVsetImm(!(code>>shift_vset));
if(inst.getVsetImm()) {
Word immed = (code>>shift_rs2) & v_immed_mask;
D(3, "immed" << immed);
inst.setSrcImm(immed); //TODO
inst.setvlmul(immed & 0x3);
D(3, "lmul " << (immed & 0x3));
inst.setvediv((immed>>4) & 0x3);
D(3, "ediv " << ((immed>>4) & 0x3));
inst.setvsew((immed>>2) & 0x3);
D(3, "sew " << ((immed>>2) & 0x3));
}
else {
inst.setSrcReg((code>>shift_rs2) & reg_mask);
trace_inst->rs2 = ((code>>shift_rs2) & reg_mask);
}
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code>>shift_rs1) & reg_mask);
trace_inst->rd = ((code>>shift_rd) & reg_mask);
} else {
inst.setSrcReg((code>>shift_rs2) & reg_mask);
inst.setVmask((code>>shift_vmask) & 0x1);
inst.setFunc6((code>>shift_func6) & func6_mask);
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code>>shift_rs1) & reg_mask);
trace_inst->rs2 = ((code>>shift_rs2) & reg_mask);
trace_inst->rd = ((code>>shift_rd) & reg_mask);
}
break;
case Opcode::VL:
D(3, "vector load instr");
inst.setDestReg((code>>shift_rd) & reg_mask);
inst.setSrcReg((code>>shift_rs1) & reg_mask);
inst.setVlsWidth((code>>shift_func3) & func3_mask);
inst.setSrcReg((code>>shift_rs2) & reg_mask);
inst.setVmask((code>>shift_vmask));
inst.setVmop((code>>shift_vmop) & func3_mask);
inst.setVnf((code>>shift_vnf) & func3_mask);
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code>>shift_rs1) & reg_mask);
trace_inst->vd = ((code>>shift_rd) & reg_mask);
//trace_inst->vs2 = ((code>>shift_rs2) & reg_mask);
break;
case Opcode::VS:
inst.setVs3((code>>shift_rd) & reg_mask);
inst.setSrcReg((code>>shift_rs1) & reg_mask);
inst.setVlsWidth((code>>shift_func3) & func3_mask);
inst.setSrcReg((code>>shift_rs2) & reg_mask);
inst.setVmask((code>>shift_vmask));
inst.setVmop((code>>shift_vmop) & func3_mask);
inst.setVnf((code>>shift_vnf) & func3_mask);
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code>>shift_rs1) & reg_mask);
//trace_inst->vd = ((code>>shift_rd) & reg_mask);
trace_inst->vs1 = ((code>>shift_rd) & reg_mask); //vs3
break;
default:
cout << "Inavlid opcode.\n";
std::abort();
}
break;
default:
cout << "Unrecognized argument class in word decoder.\n";
std::abort();
}
if (haveRefs && usedImm && refMap.find(idx-n/8) != refMap.end()) {
Ref *srcRef = refMap[idx-n/8];
/* Create a new ref tied to this instruction. */
// Ref *r = new SimpleRef(srcRef->name, *(Addr*)inst.setSrcImm(),
// inst.hasRelImm());
// inst.setImmRef(*r);
}
D(2, "Decoded instr 0x" << hex << code << " into: " << inst);
return &inst;
}

1950
simX/execute.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,121 +0,0 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#ifndef __ARCHDEF_H
#define __ARCHDEF_H
#include <string>
#include <sstream>
#include <cstdlib>
#include <stdio.h>
#include "types.h"
namespace Harp {
class ArchDef {
public:
struct Undefined {};
ArchDef(const std::string &s, int num_warps = 32, int num_threads = 32) {
std::istringstream iss(s.c_str());
wordSize = 4;
encChar = 'w';
nRegs = 32;
nPRegs = 0;
nWarps = num_warps;
nThds = num_threads;
extent = EXT_WARPS;
// if (!iss) { extent = EXT_NULL; return; }
// iss >> encChar;
// if (!iss) { extent = EXT_WORDSIZE; return; }
// iss >> nRegs;
// if (!iss) { extent = EXT_ENC; return; }
// char sep;
// iss >> sep >> nPRegs;
// if (!iss || sep != '/') { extent = EXT_REGS; return; }
// iss >> sep >> nThds;
// if (!iss || sep != '/') { extent = EXT_PREGS; return; }
// iss >> sep >> nWarps;
// if (!iss || sep != '/') { extent = EXT_THDS; return; }
// extent = EXT_WARPS;
}
operator std::string () const {
if (extent == EXT_NULL) return "";
std::ostringstream oss;
if (extent >= EXT_WORDSIZE) oss << wordSize;
if (extent >= EXT_ENC ) oss << encChar;
if (extent >= EXT_REGS ) oss << nRegs;
if (extent >= EXT_PREGS ) oss << '/' << nPRegs;
if (extent >= EXT_THDS ) oss << '/' << nThds;
if (extent >= EXT_WARPS ) oss << '/' << nWarps;
return oss.str();
}
bool operator==(const ArchDef &r) const {
Extent minExtent(r.extent > extent ? extent : r.extent);
// Can't be equal if we can't specify a binary encoding at all.
if (minExtent < EXT_PREGS) return false;
if (minExtent >= EXT_WORDSIZE) { if (wordSize!=r.wordSize) return false; }
if (minExtent >= EXT_ENC ) { if (encChar != r.encChar) return false; }
if (minExtent >= EXT_REGS ) { if (nRegs != r.nRegs) return false; }
if (minExtent >= EXT_PREGS ) { if (nPRegs != r.nPRegs) return false; }
if (minExtent >= EXT_THDS ) { if (nThds != r.nThds) return false; }
if (minExtent >= EXT_WARPS ) { if (nWarps != r.nWarps) return false; }
return true;
}
bool operator!=(const ArchDef &r) const { return !(*this == r); }
Size getWordSize() const {
if (extent < EXT_WORDSIZE) throw Undefined(); else return wordSize;
}
char getEncChar() const {
if (extent<EXT_ENC||encChar=='x') throw Undefined(); else return encChar;
}
RegNum getNRegs() const {
if (extent < EXT_REGS) throw Undefined(); else return nRegs;
}
RegNum getNPRegs() const {
if (extent < EXT_PREGS) throw Undefined(); else return nPRegs;
}
ThdNum getNThds() const {
if (extent < EXT_THDS) throw Undefined(); else return nThds;
}
ThdNum getNWarps() const {
if (extent < EXT_WARPS) throw Undefined(); else return nWarps;
}
bool is_cpu_mode() const {
return cpu_mode_;
}
private:
enum Extent {
EXT_NULL, EXT_WORDSIZE, EXT_ENC, EXT_REGS, EXT_PREGS, EXT_THDS, EXT_WARPS
};
Extent extent;
Size wordSize;
ThdNum nThds, nWarps;
RegNum nRegs, nPRegs;
char encChar;
bool cpu_mode_;
};
}
#endif

View File

@@ -1,61 +0,0 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#ifndef __ARGS_H
#define __ARGS_H
#include <iostream>
#include <string>
#include <sstream>
#include <map>
namespace HarpTools {
struct BadArg { BadArg(std::string s) : arg(s) {} std::string arg; };
class CommandLineArg {
public:
CommandLineArg(std::string s, std::string l, const char *helpText);
CommandLineArg(std::string l, const char *helpText);
virtual int read(int argc, char** argv) = 0;
static void readArgs(int argc, char **argv);
static void clearArgs();
static void showHelp(std::ostream &os);
private:
static std::string helpString;
static std::map<std::string, CommandLineArg *> longArgs;
static std::map<std::string, CommandLineArg *> shortArgs;
};
template <typename T> class CommandLineArgSetter : public CommandLineArg {
public:
CommandLineArgSetter(std::string s, std::string l, const char *ht, T &x) :
CommandLineArg(s, l, ht), x(x) {}
CommandLineArgSetter(std::string l, const char *ht, T &x) :
CommandLineArg(l, ht), x(x) {}
int read(int argc, char **argv) {
std::istringstream iss(argv[1]);
iss >> x;
return 1;
}
private:
T &x;
};
class CommandLineArgFlag : public CommandLineArg {
public:
CommandLineArgFlag(std::string s, std::string l, const char *ht, bool &x) :
CommandLineArg(s, l, ht), x(x) { x = false; }
CommandLineArgFlag(std::string l, const char *ht, bool &x) :
CommandLineArg(l, ht), x(x) { x = false; }
int read(int argc, char **argv) { x = true; return 0; }
private:
bool &x;
};
}
#endif

View File

@@ -1,16 +0,0 @@
#ifndef HARPTOOL_ASM_TOKENS
#define HARPTOOL_ASM_TOKENS
namespace HarpTools {
enum AsmTokens {
ASM_T_DIR_DEF = 1, ASM_T_DIR_PERM, ASM_T_DIR_BYTE, ASM_T_DIR_WORD,
ASM_T_DIR_SPACE, ASM_T_DIR_STRING, ASM_T_DIR_ALIGN, ASM_T_DIR_ENTRY,
ASM_T_DIR_GLOBAL, ASM_T_DIR_ARG_NUM, ASM_T_DIR_ARG_STRING,
ASM_T_DIR_ARG_SYM, ASM_T_DIR_ARG_R, ASM_T_DIR_ARG_W, ASM_T_DIR_ARG_X,
ASM_T_DIR_END, ASM_T_LABEL, ASM_T_PRED, ASM_T_INST,
ASM_T_PREG, ASM_T_REG, ASM_T_REG_RA, ASM_T_REG_SP,
ASM_T_REG_FP, ASM_T_LIT, ASM_T_SYM, ASM_T_PEXP
};
}
#endif

View File

@@ -1,206 +0,0 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#ifndef __CORE_H
#define __CORE_H
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include "types.h"
#include "archdef.h"
#include "enc.h"
#include "mem.h"
#include "debug.h"
#include "Vcache_simX.h"
#include "verilated.h"
#ifdef VCD_OUTPUT
#include <verilated_vcd_c.h>
#endif
#include "trace.h"
namespace Harp {
#ifdef EMU_INSTRUMENTATION
void reg_doWrite(Word cpuId, Word regNum);
void reg_doRead(Word cpuId, Word regNum);
#endif
template <typename T> class Reg {
public:
Reg(): val(0), cpuId(0), regNum(0) {}
Reg(Word c, Word n): val(0), cpuId(c), regNum(n) {}
Reg(Word c, Word n, T v): val(v), cpuId(c), regNum(n) {}
Reg &operator=(T r) { if (regNum) {val = r; doWrite();} return *this; }
operator T() const { doRead(); return val; }
void trunc(Size s) {
Word mask((~0ull >> (sizeof(Word)-s)*8));
val &= mask;
}
T val;
private:
Word cpuId, regNum;
// T val;
#ifdef EMU_INSTRUMENTATION
/* Access size here is 8, representing the register size of 64-bit cores. */
void doWrite() const { reg_doWrite(cpuId, regNum); }
void doRead() const { reg_doRead(cpuId, regNum); }
#else
void doWrite() const {}
void doRead() const {}
#endif
};
// Entry in the IPDOM Stack
struct DomStackEntry {
DomStackEntry(
unsigned p, const std::vector<std::vector<Reg<Word> > >& m,
std::vector<bool> &tm, Word pc
): pc(pc), fallThrough(false), uni(false)
{
std::cout << "DomStackEntry TMASK: ";
for (unsigned i = 0; i < m.size(); ++i)
{
std::cout << " " << (!bool(m[i][p]) && tm[i]);
tmask.push_back(!bool(m[i][p]) && tm[i]);
}
std::cout << "\n";
}
DomStackEntry(const std::vector<bool> &tmask):
tmask(tmask), fallThrough(true), uni(false) {}
std::vector<bool> tmask;
Word pc;
bool fallThrough;
bool uni;
};
struct vtype
{
int vill;
int vediv;
int vsew;
int vlmul;
};
class Warp;
class Core {
public:
Core(const ArchDef &a, Decoder &d, MemoryUnit &mem, Word id=0);
Vcache_simX * cache_simulator;
VerilatedVcdC * m_trace;
bool renameTable[32][32];
bool vecRenameTable[32];
bool stallWarp[32];
bool foundSchedule;
trace_inst_t inst_in_fetch;
trace_inst_t inst_in_decode;
trace_inst_t inst_in_scheduler;
trace_inst_t inst_in_exe;
trace_inst_t inst_in_lsu;
trace_inst_t inst_in_wb;
bool release_warp;
int release_warp_num;
bool interrupt(Word r0);
bool running() const;
void getCacheDelays(trace_inst_t *);
void warpScheduler();
void fetch();
void decode();
void scheduler();
void execute_unit();
void load_store();
void writeback();
void step();
void printStats() const;
const ArchDef &a;
Decoder &iDec;
MemoryUnit &mem;
Word interruptEntry;
unsigned long steps;
unsigned long num_cycles;
unsigned long num_instructions;
std::vector<Warp> w;
std::map<Word, std::set<Warp *> > b; // Barriers
int schedule_w;
};
class Warp {
public:
Warp(Core *c, Word id=0);
void step(trace_inst_t *);
bool interrupt(Word r0);
bool running() const { return activeThreads; }
#ifdef EMU_INSTRUMENTATION
bool getSupervisorMode() const { return supervisorMode; }
#endif
void printStats() const;
struct MemAccess {
MemAccess(bool w, Word a): wr(w), addr(a) {}
bool wr;
Word addr;
};
std::vector<MemAccess> memAccesses;
// private:
Core *core;
Word pc, shadowPc, id;
Size activeThreads, shadowActiveThreads;
std::vector<std::vector<Reg<Word> > > reg;
std::vector<std::vector<Reg<bool> > > pred;
std::vector<Reg<uint16_t> > csr;
std::vector<bool> tmask, shadowTmask;
std::stack<DomStackEntry> domStack;
std::vector<Word> shadowReg;
std::vector<bool> shadowPReg;
//Vector CSR
struct vtype vtype; //both of them are XLEN WIDE
int vl; //both of them are XLEN WIDE
Word VLEN; //Total vector length
std::vector<std::vector<Reg<char*>>> vreg; // 32 vector registers
bool interruptEnable, shadowInterruptEnable;
bool supervisorMode, shadowSupervisorMode;
bool spawned;
unsigned long steps, insts, loads, stores;
friend class Instruction;
};
}
#endif

View File

@@ -1,47 +0,0 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Spring 2013
*******************************************************************************/
#ifndef __DEBUG_H
#define __DEBUG_H
//#define USE_DEBUG 9
#ifdef USE_DEBUG
#include <iostream>
#define D(lvl, x) do { \
using namespace std; \
if ((lvl) <= USE_DEBUG) { \
cout << "DEBUG " << __FILE__ << ':' << dec << __LINE__ << ": " \
<< x << endl; \
} \
} while(0)
#define DPH(lvl, x) do { \
using namespace std; \
if ((lvl) <= USE_DEBUG) { \
cout << "DEBUG " << __FILE__ << ':' << dec << __LINE__ << ": " \
<< x; \
} \
} while(0)
#define DPN(lvl, x) do { \
using namespace std; \
if ((lvl) <= USE_DEBUG) { \
cout << x; \
} \
} while(0)
#define D_RAW(x) do { \
std::cout << x; \
} while (0)
#else
#define D(lvl, x) do {} while(0)
#define DPH(lvl, x) do {} while(0)
#define DPN(lvl, x) do {} while(0)
#define D_RAW(x) do {} while(0)
#endif
#endif

View File

@@ -1,80 +0,0 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#ifndef __ENC_H
#define __ENC_H
#include <map>
#include "types.h"
#include "instruction.h"
#include "obj.h"
#include "trace.h"
// } trace_inst_t;
namespace Harp {
class DataChunk;
class TextChunk;
class Ref;
class Encoder {
public:
Encoder() {}
virtual ~Encoder() {}
virtual Size encode(Ref *&ref, std::vector<Byte> &v, Size n,
Instruction &i) = 0;
void encodeChunk(DataChunk &dest, const TextChunk &src);
};
class Decoder {
public:
Decoder() : haveRefs(false) {}
Decoder(const std::vector<Ref*> &refVec) : haveRefs(true) {
setRefs(refVec);
}
virtual ~Decoder() {}
void setRefs(const std::vector<Ref*> &);
void clearRefs() { refMap.clear(); }
virtual Instruction *decode(const std::vector<Byte> &v, Size &n, trace_inst_t * trace_inst) = 0;
virtual Instruction *decode(const std::vector<Byte> &v, Size &n) = 0;
void decodeChunk(TextChunk &dest, const DataChunk &src);
protected:
bool haveRefs;
std::map <Size, Ref*> refMap;
};
class WordDecoder : public Decoder {
public:
WordDecoder(const ArchDef &);
virtual Instruction *decode(const std::vector<Byte> &v, Size &n, trace_inst_t * trace_inst);
virtual Instruction *decode(const std::vector<Byte> &v, Size &n) {
printf("Not implemented\n");
return nullptr;
}
private:
Size n, o, r, p, i1, i2, i3;
Word oMask, rMask, pMask, i1Mask, i2Mask, i3Mask;
// FARES
Size inst_s, opcode_s, reg_s, func3_s;
Size shift_opcode, shift_rd, shift_rs1, shift_rs2, shift_func3, shift_func7;
Size shift_j_u_immed, shift_s_b_immed, shift_i_immed;
//Vector
Size shift_vset, shift_vset_immed, shift_vmask, shift_vmop, shift_vnf, shift_func6;
Size vmask_s, mop_s;
Word reg_mask, func3_mask, func7_mask, opcode_mask, i_immed_mask,
s_immed_mask, b_immed_mask, u_immed_mask, j_immed_mask, v_immed_mask, func6_mask;
};
}
#endif

View File

@@ -1,123 +0,0 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#include <math.h>
#include <stdlib.h>
#include "types.h"
#ifdef DEBUG
#include <iostream>
#define DEBUGMSG(x) do { \
std::cout << __FILE__ << ':' <<__LINE__ << ": " << x << '\n'; \
} while(0)
#else
#define DEBUGMSG(x) do { } while(0)
#endif
namespace Harp {
// This class serves to handle the strange-precision floating point that can
// crop up in HARP.
class Float {
public:
Float(Word_u bin, Size n): sz(n) {
DEBUGMSG("Float(0x" << std::hex << bin << ", " << std::dec << n << ')');
bool sign(bin >> (n*8 - 1));
Size expSz;
if (n < 4) {
expSz = 5;
} else if (n < 8) {
expSz = 8;
} else {
expSz = 11;
}
Size sigSz = n*8 - expSz - 1;
DEBUGMSG(" exp: " << std::dec << expSz <<
" bits, sig: " << std::dec << sigSz << " bits.");
int exp = (bin >> sigSz) & ((1<<expSz) - 1);
Word_u sig = bin & ((1llu<<sigSz) - 1);
DEBUGMSG(" sig=" << std::dec << sig << " exp=" << exp);
if (exp == 0) {
// Subnormal
d = sig / pow(2, ((1<<(expSz-1))-2)) / pow(2, sigSz);
DEBUGMSG(" Denorm.");
} else if (exp == ((1<<expSz) - 1)) {
// Infinity
d = HUGE_VAL;
DEBUGMSG(" Inf.");
} else {
// Normalized, implied 1.
exp -= (1<<(expSz - 1)) - 1;
d = pow(2.0, exp - int(sigSz)) * double((1ll << sigSz) + sig);
DEBUGMSG(" Norm, exp=" << exp);
}
if (sign) d = -d;
DEBUGMSG("Set to " << d);
}
Float(double d, Size n): d(d), sz(n) { DEBUGMSG("Float(double, size)"); }
operator Word_u() {
DEBUGMSG("Float -> Word_u: " << d);
Size expSz;
if (sz < 4) {
expSz = 5;
} else if (sz < 8) {
expSz = 8;
} else {
expSz = 11;
}
Size sigSz = 8*sz - expSz - 1;
bool sign(d < 0);
bool inf(std::isinf(d)), zero(d == 0.0);
int exp;
if (!inf && !zero) exp = floor(log2(fabs(d)));
Word_u rval;
if (inf) {
// Infinity
DEBUGMSG(" Inf.");
rval = ((1llu<<expSz)-1llu)<<sigSz;
} else if (!zero && abs(exp) < (1<<(expSz-1)) - 1) {
// Normalized with implied 1.
Word_u sig = (fabs(d) * pow(2.0, -exp) - 1.0) * pow(2.0, sigSz);
DEBUGMSG(" Norm, exp=" << exp << ", sig=" << sig);
rval = ((((exp + ((1llu<<(expSz-1)) - 1llu))
&((1llu<<expSz)-1llu)))<<sigSz) | sig;
} else if (!zero && exp > -(1<<(expSz-1)) - sigSz) {
// Subnormal number.
Word_u sig = round(fabs(d)*pow(2.0,((1<<(expSz-1))-2))*pow(2.0, sigSz));
DEBUGMSG(" Denorm, exp=" << exp << ", sig=" << sig);
rval = sig;
} else {
// Zero.
rval = 0;
}
if (sign) rval |= 1llu<<(sz*8 - 1);
DEBUGMSG(" Returning 0x" << std::hex << rval);
return rval;
}
operator double() { DEBUGMSG("Float->double " << d); return d; }
private:
double d;
Size sz;
};
}

View File

@@ -1,37 +0,0 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#ifndef __HELP_H
#define __HELP_H
/* Help messages. */
namespace HarpTools {
namespace Help {
const char *mainHelp =
"--help, -h, no arguments\n"
" Print this message.\n"
"-E, --emu; -A, --asm; -L, --ld; -D, --disasm\n"
" Invoke the emulator, assembler, linker, and disassembler, "
"respectively.\n"
"<mode> --help\n"
" Display contextual help.\n",
*emuHelp = "HARP Emulator command line arguments:\n"
" -c, --core <filename> RAM image\n"
" -a, --arch <arch string> Architecture string\n"
" -s, --stats Print stats on exit.\n"
" -b, --basic Disable virtual memory.\n"
" -i, --batch Disable console input.\n",
*asmHelp = "HARP Assembler command line arguments:\n"
" -a, --arch <arch string>\n"
" -o, --output <filename>\n",
*ldHelp = "HARP Linker command line arguments:\n"
" -o, --output <filename>\n"
" -a, --arch <filename>\n"
" -f, --format <foramt string>\n"
" --offset <bytes>\n",
*disasmHelp = "HARP Disassembler command line arguments:\n"
" -a, --arch <arch string> Architecture string.\n"
" -o, --output <filename> Output filename.\n";
}
}
#endif

View File

@@ -1,175 +0,0 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#ifndef __INSTRUCTION_H
#define __INSTRUCTION_H
#include <map>
#include <iostream>
#include <math.h>
#include "types.h"
#include "trace.h"
namespace Harp {
class Warp;
class Ref;
enum Opcode
{
NOP = 0,
R_INST = 51,
L_INST = 3,
I_INST = 19,
S_INST = 35,
B_INST = 99,
LUI_INST = 55,
AUIPC_INST = 23,
JAL_INST = 111,
JALR_INST = 103,
SYS_INST = 115,
TRAP = 0x7f,
FENCE = 0x0f,
PJ_INST = 0x7b,
GPGPU = 0x6b,
VSET_ARITH = 0x57,
VL = 0x7,
VS = 0x27,
};
enum InstType { N_TYPE, R_TYPE, I_TYPE, S_TYPE, B_TYPE, U_TYPE, J_TYPE, V_TYPE};
// We build a table of instruction information out of this.
struct InstTableEntry_t {
const char *opString;
bool controlFlow, relAddress, allSrcArgs, privileged;
InstType iType;
};
static std::map<int, struct InstTableEntry_t> instTable =
{
{Opcode::NOP, {"nop" , false, false, false, false, InstType::N_TYPE }},
{Opcode::R_INST, {"r_type", false, false, false, false, InstType::R_TYPE }},
{Opcode::L_INST, {"load" , false, false, false, false, InstType::I_TYPE }},
{Opcode::I_INST, {"i_type", false, false, false, false, InstType::I_TYPE }},
{Opcode::S_INST, {"store" , false, false, false, false, InstType::S_TYPE }},
{Opcode::B_INST, {"branch", true , false, false, false, InstType::B_TYPE }},
{Opcode::LUI_INST, {"lui" , false, false, false, false, InstType::U_TYPE }},
{Opcode::AUIPC_INST, {"auipc" , false, false, false, false, InstType::U_TYPE }},
{Opcode::JAL_INST, {"jal" , true , false, false, false, InstType::J_TYPE }},
{Opcode::JALR_INST, {"jalr" , true , false, false, false, InstType::I_TYPE }},
{Opcode::SYS_INST, {"SYS" , true , false, false, false, InstType::I_TYPE }},
{Opcode::TRAP, {"TRAP" , true , false, false, false, InstType::I_TYPE }},
{Opcode::FENCE, {"fence" , true , false, false, false, InstType::I_TYPE }},
{Opcode::PJ_INST, {"pred j", true , false, false, false, InstType::R_TYPE }},
{Opcode::GPGPU, {"gpgpu" , false, false, false, false, InstType::R_TYPE }},
{Opcode::VSET_ARITH, {"vsetvl" , false, false, false, false, InstType::V_TYPE }},
{Opcode::VL, {"vl" , false, false, false, false, InstType::V_TYPE }},
{Opcode::VS, {"vs" , false, false, false, false, InstType::V_TYPE }}
};
static const Size MAX_REG_SOURCES(3);
static const Size MAX_PRED_SOURCES(2);
class Instruction;
struct DivergentBranchException {};
struct DomainException {};
std::ostream &operator<<(std::ostream &, Instruction &);
class Instruction {
public:
Instruction() :
predicated(false), nRsrc(0), nPsrc(0), immsrcPresent(false),
rdestPresent(false), pdestPresent(false), refLiteral(NULL)
{
}
void executeOn(Warp &warp, trace_inst_t *);
friend std::ostream &operator<<(std::ostream &, Instruction &);
/* Setters used to "craft" the instruction. */
void setOpcode (Opcode opc) { op = opc; }
void setPred (RegNum pReg) { predicated = true; pred = pReg; }
void setDestReg (RegNum destReg) { rdestPresent = true; rdest = destReg; }
void setSrcReg (RegNum srcReg) { rsrc[nRsrc++] = srcReg; }
void setFunc3 (Word func3) { this->func3 = func3; }
void setFunc7 (Word func7) { this->func7 = func7; }
void setDestPReg(RegNum dPReg) { pdestPresent = true; pdest = dPReg; }
void setSrcPReg (RegNum srcPReg) { psrc[nPsrc++] = srcPReg; }
Word *setSrcImm () { immsrcPresent = true; immsrc = 0xa5; return &immsrc;}
void setSrcImm (Word srcImm) { immsrcPresent = true; immsrc = srcImm; }
void setImmRef (Ref &r) { refLiteral = &r; }
void setVsetImm (Word vset_imm) { if(vset_imm) vsetImm = true; else vsetImm = false; }
void setVlsWidth (Word width) { vlsWidth = width; }
void setVmop( Word mop) { vMop = mop; }
void setVnf(Word nf) { vNf = nf; }
void setVmask(Word mask) { vmask = mask; }
void setVs3(Word vs) { vs3 = vs; }
void setvlmul(Word lmul) { vlmul = pow(2, lmul); }
void setvsew(Word sew) { vsew = pow(2, 3+sew); }
void setvediv(Word ediv) { vediv = pow(2,ediv); }
void setFunc6(Word func6) { this->func6 = func6; }
/* Getters used by encoders. */
Opcode getOpcode() const { return op; }
bool hasPred() const { return predicated; }
RegNum getPred() const { return pred; }
RegNum getNRSrc() const { return nRsrc; }
RegNum getRSrc(RegNum i) const { return rsrc[i]; }
RegNum getNPSrc() const { return nPsrc; }
RegNum getPSrc(RegNum i) const { return psrc[i]; }
bool hasRDest() const { return rdestPresent; }
RegNum getRDest() const { return rdest; }
bool hasPDest() const { return pdestPresent; }
RegNum getPDest() const { return pdest; }
bool hasImm() const { return immsrcPresent; }
Word getImm() const { return immsrc; }
bool hasRefLiteral() const { return refLiteral != NULL; }
Ref *getRefLiteral() const { return refLiteral; }
bool getVsetImm() const { return vsetImm; }
Word getVlsWidth() const { return vlsWidth; }
Word getVmop() const { return vMop; }
Word getvNf() const { return vNf; }
bool getVmask() const { return vmask; }
Word getVs3() const { return vs3; }
Word getvlmul() const { return vlmul; }
Word getvsew() const { return vsew; }
Word getvediv() const { return vediv; }
/* Getters used as table lookup. */
bool hasRelImm() const { return (*(instTable.find(op))).second.relAddress; }
private:
bool predicated;
RegNum pred;
Opcode op;
int nRsrc, nPsrc;
RegNum rsrc[MAX_REG_SOURCES], psrc[MAX_PRED_SOURCES];
bool immsrcPresent;
Word immsrc;
Word func3;
Word func7;
bool rdestPresent, pdestPresent;
RegNum rdest, pdest;
Ref *refLiteral;
//Vector
bool vsetImm, vmask;
Word vlsWidth, vMop, vNf, vs3, vlmul, vsew, vediv, func6;
public:
};
}
#endif
// static struct InstTableEntry {
// const char *opString;
// bool controlFlow, relAddress, allSrcArgs, privileged;
// InstType iType;
// };

View File

@@ -1,210 +0,0 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#ifndef __OBJ_H
#define __OBJ_H
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <stdlib.h>
#include "types.h"
#include "archdef.h"
#include "instruction.h"
#include "enc.h"
#include "asm-tokens.h"
namespace Harp {
class Decoder;
class Encoder;
class Ref {
public:
std::string name;
Ref(const std::string &n, bool r, Size ib = 0):
name(n), bound(false), relative(r), ibase(ib) { }
virtual ~Ref() { }
virtual void bind(Addr addr, Addr base = 0) = 0;
virtual Addr getAddr() const = 0;
bool bound, relative;
Size ibase;
};
/* Used in not-yet-encoded code objects, plain old data. */
class SimpleRef : public Ref {
public:
SimpleRef(const std::string &name, Addr &addr, bool rel = false) :
Ref(name, rel), addr(addr) { }
virtual void bind(Addr addr, Addr base = 0) {
std::cout << "Attempted to bind a SimpleRef.\n";
std::abort();
}
virtual Addr getAddr() const { return this->addr; }
Byte *getAddrPtr() { return (Byte*)&addr; }
private:
Addr &addr;
};
// /* Used in already-encoded code objects. */
// class OffsetRef : public Ref {
// public:
// OffsetRef(
// const std::string &name, std::vector<Byte> &v, Size offset, Size bits,
// Size ws, bool rel = false, Size ibase = 0
// ) : Ref(name, rel, ibase), data(v), offset(offset), bits(bits), wordSize(ws)
// {}
// virtual void bind(Addr addr, Addr base = 0) {
// Size bytes(bits/8), remainder(bits%8);
// if (relative) {
// addr = addr - base;
// Word_s addr_s(addr);
// if ((addr_s >> bits) != ~0ull && (addr_s >> bits) != 0) goto noFit;
// } else {
// Addr mask = (1ull<<bits)-1;
// if (addr > mask) goto noFit;
// }
// { Byte mask((1ull<<remainder) - 1);
// Size i;
// for (i = 0; i < bytes; i++) {
// data[offset+i] = addr & 0xff;
// addr >>= 8;
// }
// data[offset+i] &= ~mask;
// data[offset+i] |= (addr&mask);
// bound = true;
// }
// return;
// noFit:
// std::cout << "Attempt to bind a " << bits << "-bit "
// << (relative?"":"non-") << "relative symbol to an address"
// " it cannot reach.\n";
// std::abort();
// }
// virtual Addr getAddr() const {
// Size bytes = bits/8, remainder = bits%8;
// Byte mask((1<<remainder)-1);
// Addr a(data[offset]&mask);
// for (Size i = 0; i < bytes-1; i++) {
// a |= data[offset + bytes - i - 1];
// a <<= 8;
// }
// return a;
// }
// Size getOffset() const { return offset; }
// Size getBits() const { return bits; }
// private:
// std::vector<Byte> &data;
// Size offset, bits, wordSize;
// };
// class Chunk {
// public:
// Chunk(std::string n, Size a = 0, Word f = 0) :
// name(n), alignment(a), bound(false), flags(f), global(false) {}
// virtual ~Chunk() { for (Size i = 0; i < refs.size(); i++) delete refs[i]; }
// void bind(Addr a) { address = a; bound = true; }
// void setGlobal() { global = true; }
// bool isGlobal() const { return global; }
// std::string name;
// Size alignment;
// bool bound, global;
// Addr address;
// Word flags;
// std::vector<Ref*> refs;
// };
// class TextChunk : public Chunk {
// public:
// TextChunk(std::string n, Size a = 0, Word f = 0)
// : Chunk(n, a, f), instructions() {}
// ~TextChunk() {
// for (Size i = 0; i < instructions.size(); i++) delete instructions[i];
// }
// std::vector<Instruction*> instructions;
// };
// class DataChunk : public Chunk {
// public:
// DataChunk(std::string n, Size a = 0, Word f = 0)
// : Chunk(n, a, f), size(0), contents() {}
// Size size;
// std::vector<Byte> contents; /* 0 to size bytes in length. */
// };
// class Obj {
// public:
// ~Obj() { for (Size i = 0; i < chunks.size(); i++) delete chunks[i]; }
// std::vector<Chunk*> chunks;
// Size entry;
// };
// class DynObj : public Obj {
// public:
// std::vector<std::string> deps;
// };
// class ObjReader {
// public:
// virtual Obj *read(std::istream &input) = 0;
// private:
// };
// class ObjWriter {
// public:
// virtual void write(std::ostream &output, const Obj &o) = 0;
// private:
// };
// class AsmReader : public ObjReader {
// public:
// AsmReader(ArchDef arch) :
// wordSize(arch.getWordSize()), nRegs(arch.getNRegs()) {}
// virtual Obj *read(std::istream &input);
// private:
// Size wordSize, nRegs;
// // Operand type sequences indexed by argument class
// enum ArgType {AT_END, AT_REG, AT_PREG, AT_LIT};
// static ArgType operandtype_table[][4]; // ArgClass -> ArgType[arg_idx]
// };
// class HOFReader : public ObjReader {
// public:
// HOFReader(ArchDef &arch) : arch(arch) {}
// Obj *read(std::istream &input);
// private:
// const ArchDef &arch;
// };
// class AsmWriter : public ObjWriter {
// public:
// AsmWriter(ArchDef arch): wordSize(arch.getWordSize()) {}
// virtual void write(std::ostream &output, const Obj &obj);
// private:
// Size wordSize;
// };
// class HOFWriter : public ObjWriter {
// public:
// HOFWriter(ArchDef &arch) : arch(arch) {}
// virtual void write(std::ostream &output, const Obj &obj);
// private:
// const ArchDef &arch;
// };
}
#endif

View File

@@ -1,169 +0,0 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#ifndef EMU_INSTRUMENTATION
#define EMU_INSTRUMENTATION
#endif
#ifndef __QSIM_HARP_H
#define __QSIM_HARP_H
#include "types.h"
#include "core.h"
#include "enc.h"
#include "instruction.h"
#include "mem.h"
#include "obj.h"
#include "archdef.h"
#include <stdint.h>
#include <iostream>
#include <vector>
#include <string>
#include <qsim.h>
namespace Harp {
class OSDomain {
public:
OSDomain(Harp::ArchDef &arch, std::string imgFile);
bool idle(unsigned i) const { return cpus[i].idle(); }
int get_tid(unsigned i) const { return cpus[i].get_tid(); }
bool get_prot(unsigned i) const { return cpus[i].get_prot(); }
int get_n() const { return cpus.size(); }
uint64_t run(unsigned i, uint64_t n) { return cpus[i].run(n); }
void connect_console(std::ostream &s);
void timer_interrupt() { /* TODO: timer convention */ }
void interrupt(unsigned i, int vec) { cpus[i].interrupt(vec); }
bool booted(unsigned i) const { return cpus[i].booted(); }
void save_state(const char* state_file);
template <typename T>
void set_atomic_cb
(T *p, typename Qsim::OSDomain::atomic_cb_obj<T>::atomic_cb_t f)
{
atomic_cbs.push_back(new Qsim::OSDomain::atomic_cb_obj<T>(p, f));
}
template <typename T>
void set_inst_cb
(T* p, typename Qsim::OSDomain::inst_cb_obj<T>::inst_cb_t f)
{
inst_cbs.push_back(new Qsim::OSDomain::inst_cb_obj<T>(p, f));
}
template <typename T>
void set_int_cb
(T *p, typename Qsim::OSDomain::int_cb_obj<T>::int_cb_t f)
{
int_cbs.push_back(new Qsim::OSDomain::int_cb_obj<T>(p, f));
}
template <typename T>
void set_mem_cb
(T *p, typename Qsim::OSDomain::mem_cb_obj<T>::mem_cb_t f)
{
mem_cbs.push_back(new Qsim::OSDomain::mem_cb_obj<T>(p, f));
}
template <typename T>
void set_magic_cb
(T *p, typename Qsim::OSDomain::magic_cb_obj<T>::magic_cb_t f)
{
magic_cbs.push_back(new Qsim::OSDomain::magic_cb_obj<T>(p, f));
}
template <typename T>
void set_io_cb
(T *p, typename Qsim::OSDomain::io_cb_obj<T>::io_cb_t f)
{ /* Do nothing. We have no separate IO address space. */ }
template <typename T>
void set_reg_cb
(T *p, typename Qsim::OSDomain::reg_cb_obj<T>::reg_cb_t f)
{
reg_cbs.push_back(new Qsim::OSDomain::reg_cb_obj<T>(p, f));
}
template <typename T> void mem_rd(T& d, uint64_t paddr);
template <typename T> void mem_rd_virt(unsigned i, T& d, uint64_t vaddr);
template <typename T> void mem_wr(T& d, uint64_t paddr);
template <typename T> void mem_wr_virt(unsigned i, T& d, uint64_t vaddr);
static OSDomain *osDomain;
bool do_atomic(unsigned c) {
bool rval(false);
for (unsigned i = 0; i < atomic_cbs.size(); ++i)
if ((*atomic_cbs[i])(c)) rval = true;
return rval;
}
void do_inst(unsigned c, uint64_t va, uint64_t pa, uint8_t l,
const uint8_t *b, enum inst_type t)
{
for (unsigned i = 0; i < inst_cbs.size(); ++i)
(*inst_cbs[i])(c, va, pa, l, b, t);
}
void do_int(unsigned c, int v) {
for (unsigned i = 0; i < int_cbs.size(); ++i)
(*int_cbs[i])(c, v);
}
void do_mem(unsigned c, uint64_t va, uint64_t pa, uint8_t s, bool w) {
for (unsigned i = 0; i < mem_cbs.size(); ++i)
(*mem_cbs[i])(c, va, pa, s, w);
}
bool do_magic(unsigned c, uint64_t r0) {
bool rval(false);
for (unsigned i = 0; i < magic_cbs.size(); ++i)
if ((*magic_cbs[i])(c, r0)) rval = true;
return rval;
}
void do_reg(unsigned c, int r, uint8_t s, bool w) {
for (unsigned i = 0; i < reg_cbs.size(); ++i)
(*reg_cbs[i])(c, r, s, w);
}
private:
class Cpu {
public:
Cpu(Harp::OSDomain &osd);
Cpu(): dec(NULL), core(NULL) {}
~Cpu() { if (dec) delete dec; if (core) delete core; }
bool idle() const { return false; }
int get_tid() const { return 0; }
bool get_prot() const { return core->getSupervisorMode(); }
uint64_t run(uint64_t n);
void interrupt(int vec) { core->interrupt(vec); }
bool booted() const { return core->running(); }
Harp::OSDomain *osd;
Harp::Decoder *dec;
Harp::Core *core;
};
Harp::ArchDef arch;
Harp::MemoryUnit mu;
Harp::RamMemDevice ram;
Harp::ConsoleMemDevice *console;
std::vector <Harp::OSDomain::Cpu> cpus;
std::vector <Qsim::OSDomain::atomic_cb_obj_base*> atomic_cbs;
std::vector <Qsim::OSDomain::inst_cb_obj_base*> inst_cbs;
std::vector <Qsim::OSDomain::int_cb_obj_base*> int_cbs;
std::vector <Qsim::OSDomain::mem_cb_obj_base*> mem_cbs;
std::vector <Qsim::OSDomain::magic_cb_obj_base*> magic_cbs;
std::vector <Qsim::OSDomain::reg_cb_obj_base*> reg_cbs;
};
};
#endif

View File

@@ -1,25 +0,0 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#ifndef __TYPES_H
#define __TYPES_H
#include <stdint.h>
namespace Harp {
typedef uint8_t Byte;
typedef uint32_t Word;
typedef uint32_t Word_u;
typedef int32_t Word_s;
typedef Word_u Addr;
typedef Word_u Size;
typedef unsigned RegNum;
typedef unsigned ThdNum;
enum MemFlags {RD_USR = 1, WR_USR = 2, EX_USR = 4,
RD_SUP = 8, WR_SUP = 16, EX_SUP = 32};
}
#endif

View File

@@ -1,24 +0,0 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#ifndef __UTIL_H
#define __UTIL_H
#include <vector>
#include "types.h"
namespace Harp {
Word_u bytesToWord(const Byte *b, Size wordSize);
void wordToBytes(Byte *b, Word_u w, Size wordSize);
Word_u flagsToWord(bool r, bool w, bool x);
void wordToFlags(bool &r, bool &w, bool &x, Word_u f);
class OutOfBytes {};
Byte readByte(const std::vector<Byte> &b, Size &n);
Word_u readWord(const std::vector<Byte> &b, Size &n, Size wordSize);
void writeByte(std::vector<Byte> &p, Size &n, Byte b);
void writeWord(std::vector<Byte> &p, Size &n, Size wordSize, Word w);
}
#endif

23
simX/instr.cpp Normal file
View File

@@ -0,0 +1,23 @@
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "instr.h"
using namespace vortex;
void Instr::setVlmul(Word lmul) {
vlmul_ = std::pow(2, lmul);
}
void Instr::setVsew(Word sew) {
vsew_ = std::pow(2, 3+sew);
}
void Instr::setVediv(Word ediv) {
vediv_ = std::pow(2,ediv);
}

137
simX/instr.h Normal file
View File

@@ -0,0 +1,137 @@
#pragma once
#include "types.h"
#include "trace.h"
namespace vortex {
class Warp;
enum Opcode {
NOP = 0,
R_INST = 0x33,
L_INST = 0x3,
I_INST = 0x13,
S_INST = 0x23,
B_INST = 0x63,
LUI_INST = 0x37,
AUIPC_INST= 0x17,
JAL_INST = 0x6f,
JALR_INST = 0x67,
SYS_INST = 0x73,
FENCE = 0x0f,
PJ_INST = 0x7b,
GPGPU = 0x6b,
VSET_ARITH= 0x57,
VL = 0x7,
VS = 0x27,
};
enum InstType {
N_TYPE,
R_TYPE,
I_TYPE,
S_TYPE,
B_TYPE,
U_TYPE,
J_TYPE,
V_TYPE
};
class Instr {
public:
Instr()
: predicated_(false)
, nRsrc_(0)
, nPsrc_(0)
, hasImmSrc_(false)
, hasRDest_(false)
, hasPDest_(false)
{}
friend std::ostream &operator<<(std::ostream &, Instr &);
/* Setters used to "craft" the instruction. */
void setOpcode(Opcode opcode) { opcode_ = opcode; }
void setPred(RegNum pReg) { predicated_ = true; pred_ = pReg; }
void setDestReg(RegNum destReg) { hasRDest_ = true; rdest_ = destReg; }
void setSrcReg(RegNum srcReg) { rsrc_[nRsrc_++] = srcReg; }
void setFunc3(Word func3) { func3_ = func3; }
void setFunc7(Word func7) { func7_ = func7; }
void setSrcImm(Word srcImm) { hasImmSrc_ = true; immsrc_ = srcImm; }
void setVsetImm(Word vset_imm) { if(vset_imm) vsetImm_ = true; else vsetImm_ = false; }
void setVlsWidth(Word width) { vlsWidth_ = width; }
void setVmop(Word mop) { vMop_ = mop; }
void setVnf(Word nf) { vNf_ = nf; }
void setVmask(Word mask) { vmask_ = mask; }
void setVs3(Word vs) { vs3_ = vs; }
void setVlmul(Word lmul);
void setVsew(Word sew);
void setVediv(Word ediv);
void setFunc6(Word func6) { func6_ = func6; }
void setPrivileged(bool privileged) { privileged_ = privileged; }
/* Getters used by encoders. */
Opcode getOpcode() const { return opcode_; }
Word getFunc3() const { return func3_; }
Word getFunc6() const { return func6_; }
Word getFunc7() const { return func7_; }
RegNum getNRSrc() const { return nRsrc_; }
RegNum getRSrc(RegNum i) const { return rsrc_[i]; }
bool hasRDest() const { return hasRDest_; }
RegNum getRDest() const { return rdest_; }
bool hasPDest() const { return hasPDest_; }
RegNum getPDest() const { return pdest_; }
bool hasPred() const { return predicated_; }
RegNum getPred() const { return pred_; }
bool hasImm() const { return hasImmSrc_; }
Word getImm() const { return immsrc_; }
bool getVsetImm() const { return vsetImm_; }
Word getVlsWidth() const { return vlsWidth_; }
Word getVmop() const { return vMop_; }
Word getvNf() const { return vNf_; }
bool getVmask() const { return vmask_; }
Word getVs3() const { return vs3_; }
Word getVlmul() const { return vlmul_; }
Word getVsew() const { return vsew_; }
Word getVediv() const { return vediv_; }
bool getPrivileged() const { return privileged_; }
private:
enum {
MAX_REG_SOURCES = 3
};
Opcode opcode_;
bool predicated_;
RegNum pred_;
int nRsrc_;
int nPsrc_;
RegNum rsrc_[MAX_REG_SOURCES];
bool hasImmSrc_;
Word immsrc_;
Word func3_;
Word func7_;
bool hasRDest_;
bool hasPDest_;
RegNum rdest_;
RegNum pdest_;
bool privileged_;
//Vector
bool vsetImm_;
bool vmask_;
Word vlsWidth_;
Word vMop_;
Word vNf_;
Word vs3_;
Word vlmul_;
Word vsew_;
Word vediv_;
Word func6_;
};
std::ostream &operator<<(std::ostream &, Instr &);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,168 +1,147 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <stdlib.h>
// #include <pthread.h>
#include "include/debug.h"
#include "include/types.h"
#include "include/util.h"
#include "include/mem.h"
#include "include/core.h"
#include "debug.h"
#include "types.h"
#include "util.h"
#include "mem.h"
#include "core.h"
using namespace std;
using namespace Harp;
using namespace vortex;
RamMemDevice::RamMemDevice(const char *filename, Size wordSize) :
wordSize(wordSize), contents()
{
ifstream input(filename);
RamMemDevice::RamMemDevice(const char *filename, Size wordSize)
: wordSize(wordSize), contents() {
std::ifstream input(filename);
if (!input) {
cout << "Error reading file \"" << filename << "\" into RamMemDevice.\n";
std::cout << "Error reading file \"" << filename << "\" into RamMemDevice.\n";
std::abort();
}
do { contents.push_back(input.get()); } while (input);
do {
contents.push_back(input.get());
} while (input);
while (contents.size() % wordSize) contents.push_back(0x00);
while (contents.size() % wordSize)
contents.push_back(0x00);
}
RamMemDevice::RamMemDevice(Size size, Size wordSize) :
wordSize(wordSize), contents(size) {}
RamMemDevice::RamMemDevice(Size size, Size wordSize)
: wordSize(wordSize), contents(size) {}
void RomMemDevice::write(Addr, Word) {
cout << "Attempt to write to ROM.\n";
std::cout << "Attempt to write to ROM.\n";
std::abort();
}
Word RamMemDevice::read(Addr addr) {
D(2, "RAM read, addr=0x" << hex << addr);
Word w = readWord(contents, addr, wordSize - addr%wordSize);
D(2, "RAM read, addr=0x" << std::hex << addr);
Word w = readWord(contents, addr, wordSize - addr % wordSize);
return w;
}
void RamMemDevice::write(Addr addr, Word w) {
D(2, "RAM write, addr=0x" << hex << addr);
writeWord(contents, addr, wordSize - addr%wordSize, w);
D(2, "RAM write, addr=0x" << std::hex << addr);
writeWord(contents, addr, wordSize - addr % wordSize, w);
}
MemDevice &MemoryUnit::ADecoder::doLookup(Addr a, Size &bit) {
if (range == 0 || (a&((1ll<<bit)-1)) >= range) {
ADecoder *p(((a>>bit)&1)?oneChild:zeroChild);
if (p) { bit--; return p->doLookup(a, bit); }
else {cout << "lookup of 0x" << hex << a << " failed.\n";
throw BadAddress();}
if (range == 0 || (a & ((1ll << bit) - 1)) >= range) {
ADecoder *p(((a >> bit) & 1) ? oneChild : zeroChild);
if (p) {
bit--;
return p->doLookup(a, bit);
} else {
std::cout << "lookup of 0x" << std::hex << a << " failed.\n";
throw BadAddress();
}
} else {
return *md;
}
}
void MemoryUnit::ADecoder::map(Addr a, MemDevice &m, Size r, Size bit)
{
void MemoryUnit::ADecoder::map(Addr a, MemDevice &m, Size r, Size bit) {
if ((1llu << bit) <= r) {
md = &m;
range = m.size();
} else {
ADecoder *&child(((a>>bit)&1)?oneChild:zeroChild);
if (!child) child = new ADecoder();
child->map(a, m, r, bit-1);
ADecoder *&child(((a >> bit) & 1) ? oneChild : zeroChild);
if (!child)
child = new ADecoder();
child->map(a, m, r, bit - 1);
}
}
Byte *MemoryUnit::ADecoder::getPtr(Addr a, Size sz, Size wordSize) {
Size bit = wordSize - 1;
MemDevice &m(doLookup(a, bit));
a &= (2<<bit)-1;
if (a + sz <= m.size()) return m.base() + a;
a &= (2 << bit) - 1;
if (a + sz <= m.size())
return m.base() + a;
return NULL;
}
Word MemoryUnit::ADecoder::read(Addr a, bool sup, Size wordSize) {
Word MemoryUnit::ADecoder::read(Addr a, bool /*sup*/, Size wordSize) {
Size bit = wordSize - 1;
MemDevice &m(doLookup(a, bit));
a &= (2<<bit)-1;
// std::cout << std::hex << "ADecoder::read(Addr " << a << ", sup " << sup << ", wordSize " << wordSize << " -> ";
// std::cout << "Data: " << m.read(a) << "\n";
a &= (2 << bit) - 1;
return m.read(a);
}
void MemoryUnit::ADecoder::write(Addr a, Word w, bool sup, Size wordSize) {
void MemoryUnit::ADecoder::write(Addr a, Word w, bool /*sup*/, Size wordSize) {
Size bit = wordSize - 1;
MemDevice &m(doLookup(a, bit));
RAM & r = (RAM &) m;
// a &= (2<<bit)-1;
// std::cout << std::hex << "ADecoder::write(Addr " << a << ", w " << w << ", sup " << sup << ", wordSize " << wordSize << "\n";
Word before = m.read(a);
Word new_word = w;
RAM &r = (RAM &)m;
// if (a == 0x00010000)
// {
// fprintf(stderr, "%c", w);
// }
if (wordSize == 8)
{
if (wordSize == 8) {
r.writeByte(a, &w);
}
else if (wordSize == 16)
{
} else if (wordSize == 16) {
r.writeHalf(a, &w);
}
else
{
} else {
r.writeWord(a, &w);
}
// m.write(a, new_word);
}
Byte *MemoryUnit::getPtr(Addr a, Size s) {
return ad.getPtr(a, s, addrBytes*8);
return ad.getPtr(a, s, addrBytes * 8);
}
void MemoryUnit::attach(MemDevice &m, Addr base) {
ad.map(base, m, m.size(), addrBytes*8 - 1);
ad.map(base, m, m.size(), addrBytes * 8 - 1);
}
MemoryUnit::TLBEntry MemoryUnit::tlbLookup(Addr vAddr, Word flagMask) {
map<Addr, MemoryUnit::TLBEntry>::iterator i;
if ((i = tlb.find(vAddr/pageSize)) != tlb.end()) {
std::unordered_map<Addr, MemoryUnit::TLBEntry>::iterator i;
if ((i = tlb.find(vAddr / pageSize)) != tlb.end()) {
TLBEntry &t = i->second;
if (t.flags & flagMask) return t;
if (t.flags & flagMask)
return t;
else {
D(2, "Page fault on addr 0x" << hex << vAddr << "(bad flags)");
D(2, "Page fault on addr 0x" << std::hex << vAddr << "(bad flags)");
throw PageFault(vAddr, false);
}
} else {
D(2, "Page fault on addr 0x" << hex << vAddr << "(not in TLB)");
D(2, "Page fault on addr 0x" << std::hex << vAddr << "(not in TLB)");
throw PageFault(vAddr, true);
}
}
#ifdef EMU_INSTRUMENTATION
Addr MemoryUnit::virtToPhys(Addr vAddr) {
TLBEntry t = tlbLookup(vAddr, 077);
return t.pfn*pageSize + vAddr%pageSize;
}
#endif
Word MemoryUnit::read(Addr vAddr, bool sup) {
Addr pAddr;
if (disableVm) {
pAddr = vAddr;
} else {
Word flagMask = sup?8:1;
Word flagMask = sup ? 8 : 1;
TLBEntry t = tlbLookup(vAddr, flagMask);
pAddr = t.pfn*pageSize + vAddr%pageSize;
pAddr = t.pfn * pageSize + vAddr % pageSize;
}
// std::cout << "MU::write: About to read: " << std::hex << pAddr << " = " << (ad.read(pAddr, sup, 8*addrBytes)) << " with " << std::dec << (8*addrBytes) << "\n";
return ad.read(pAddr, sup, 8*addrBytes);
return ad.read(pAddr, sup, 8 * addrBytes);
}
Word MemoryUnit::fetch(Addr vAddr, bool sup) {
@@ -171,12 +150,12 @@ Word MemoryUnit::fetch(Addr vAddr, bool sup) {
if (disableVm) {
pAddr = vAddr;
} else {
Word flagMask = sup?32:4;
Word flagMask = sup ? 32 : 4;
TLBEntry t = tlbLookup(vAddr, flagMask);
pAddr = t.pfn*pageSize + vAddr%pageSize;
pAddr = t.pfn * pageSize + vAddr % pageSize;
}
Word instruction = ad.read(pAddr, sup, 8*addrBytes);
Word instruction = ad.read(pAddr, sup, 8 * addrBytes);
return instruction;
}
@@ -187,25 +166,26 @@ void MemoryUnit::write(Addr vAddr, Word w, bool sup, Size bytes) {
if (disableVm) {
pAddr = vAddr;
} else {
Word flagMask = sup?16:2;
Word flagMask = sup ? 16 : 2;
TLBEntry t = tlbLookup(vAddr, flagMask);
pAddr = t.pfn*pageSize + vAddr%pageSize;
pAddr = t.pfn * pageSize + vAddr % pageSize;
}
// std::cout << "MU::write: About to write: " << std::hex << pAddr << " = " << w << " with " << std::dec << 8*bytes << "\n";
ad.write(pAddr, w, sup, 8*bytes);
ad.write(pAddr, w, sup, 8 * bytes);
// std::cout << std::hex << "reading same address: " << (this->read(vAddr, sup)) << "\n";
}
void MemoryUnit::tlbAdd(Addr virt, Addr phys, Word flags) {
D(1, "tlbAdd(0x" << hex << virt << ", 0x" << phys << ", 0x" << flags << ')');
tlb[virt/pageSize] = TLBEntry(phys/pageSize, flags);
D(1, "tlbAdd(0x" << std::hex << virt << ", 0x" << phys << ", 0x" << flags << ')');
tlb[virt / pageSize] = TLBEntry(phys / pageSize, flags);
}
void MemoryUnit::tlbRm(Addr va) {
if (tlb.find(va/pageSize) != tlb.end()) tlb.erase(tlb.find(va/pageSize));
if (tlb.find(va / pageSize) != tlb.end())
tlb.erase(tlb.find(va / pageSize));
}
void *Harp::consoleInputThread(void* arg_vp) {
void *vortex::consoleInputThread(void */*arg_vp*/) {
// ConsoleMemDevice *arg = (ConsoleMemDevice *)arg_vp;
// char c;
// while (cin) {
@@ -219,181 +199,175 @@ void *Harp::consoleInputThread(void* arg_vp) {
return nullptr;
}
// ConsoleMemDevice::ConsoleMemDevice(Size wS, std::ostream &o, Core &core,
// bool batch) :
// wordSize(wS), output(o), core(core), cBuf()
// {
// // Create a console input thread if we are running in interactive mode.
// if (!batch) {
// pthread_t *thread = new pthread_t;
// pthread_create(thread, NULL, consoleInputThread, (void*)this);
// }
// pthread_mutex_init(&cBufLock, NULL);
// }
// void ConsoleMemDevice::poll() {
// pthread_mutex_lock(&cBufLock);
// if (!cBuf.empty()) core.interrupt(8);
// pthread_mutex_unlock(&cBufLock);
// }
Word DiskControllerMemDevice::read(Addr a) {
switch (a/8) {
case 0: return curDisk;
case 1: return curBlock;
case 2: return disks[curDisk].blocks * blockSize;
case 3: return physAddr;
case 4: return command;
case 5: return status;
default:
cout << "Attempt to read invalid disk controller register.\n";
std::abort();
switch (a / 8) {
case 0:
return curDisk;
case 1:
return curBlock;
case 2:
return disks[curDisk].blocks * blockSize;
case 3:
return physAddr;
case 4:
return command;
case 5:
return status;
default:
std::cout << "Attempt to read invalid disk controller register.\n";
std::abort();
}
}
void DiskControllerMemDevice::write(Addr a, Word w) {
switch (a/8) {
case 0: if (w <= disks.size()) {
curDisk = w;
status = OK;
} else {
status = INVALID_DISK;
}
break;
case 1: if (w < disks[curDisk].blocks) {
curBlock = w;
} else {
status = INVALID_BLOCK;
}
break;
case 2: nBlocks = w >= disks[curDisk].blocks?disks[curDisk].blocks - 1 : w;
status = OK;
break;
case 3: physAddr = w;
status = OK;
break;
case 4: if (w == 0) {
} else {
}
cout << "TODO: Implement disk read and write!\n";
break;
switch (a / 8) {
case 0:
if (w <= disks.size()) {
curDisk = w;
status = OK;
} else {
status = INVALID_DISK;
}
break;
case 1:
if (w < disks[curDisk].blocks) {
curBlock = w;
} else {
status = INVALID_BLOCK;
}
break;
case 2:
nBlocks = w >= disks[curDisk].blocks ? disks[curDisk].blocks - 1 : w;
status = OK;
break;
case 3:
physAddr = w;
status = OK;
break;
case 4:
if (w == 0) {
} else {
}
std::cout << "TODO: Implement disk read and write!\n";
break;
}
}
static uint32_t hti_old(char c) {
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
return c - '0';
}
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
return c - '0';
}
static uint32_t hToI_old(char *c, uint32_t size) {
uint32_t value = 0;
for (uint32_t i = 0; i < size; i++) {
value += hti_old(c[i]) << ((size - i - 1) * 4);
}
return value;
uint32_t value = 0;
for (uint32_t i = 0; i < size; i++) {
value += hti_old(c[i]) << ((size - i - 1) * 4);
}
return value;
}
void RAM::loadHexImpl(std::string path) {
this->clear();
FILE *fp = fopen(&path[0], "r");
if(fp == 0){
std::cout << path << " not found" << std::endl;
}
this->clear();
FILE *fp = fopen(&path[0], "r");
if (fp == 0) {
std::cout << path << " not found" << std::endl;
}
//Preload 0x0 <-> 0x80000000 jumps
((uint32_t*)this->get(0))[0] = 0xf1401073;
((uint32_t*)this->get(0))[1] = 0xf1401073;
((uint32_t*)this->get(0))[2] = 0x30101073;
((uint32_t*)this->get(0))[3] = 0x800000b7;
((uint32_t*)this->get(0))[4] = 0x000080e7;
((uint32_t*)this->get(0x80000000))[0] = 0x00000097;
//Preload 0x0 <-> 0x80000000 jumps
((uint32_t *)this->get(0))[0] = 0xf1401073;
((uint32_t *)this->get(0))[1] = 0xf1401073;
((uint32_t *)this->get(0))[2] = 0x30101073;
((uint32_t *)this->get(0))[3] = 0x800000b7;
((uint32_t *)this->get(0))[4] = 0x000080e7;
((uint32_t*)this->get(0xb0000000))[0] = 0x01C02023;
((uint32_t*)this->get(0xf00fff10))[0] = 0x12345678;
((uint32_t *)this->get(0x80000000))[0] = 0x00000097;
((uint32_t*)this->get(0x70000000))[0] = 0x00008067;
((uint32_t *)this->get(0xb0000000))[0] = 0x01C02023;
{
uint32_t init_addr = 0x70000004;
for (int off = 0; off < 1024; off+=4) {
uint32_t new_addr = init_addr+off;
((uint32_t*)this->get(new_addr))[0] = 0x00000000;
((uint32_t *)this->get(0xf00fff10))[0] = 0x12345678;
((uint32_t *)this->get(0x70000000))[0] = 0x00008067;
{
uint32_t init_addr = 0x70000004;
for (int off = 0; off < 1024; off += 4) {
uint32_t new_addr = init_addr + off;
((uint32_t *)this->get(new_addr))[0] = 0x00000000;
}
}
{
uint32_t init_addr = 0x71000000;
for (int off = 0; off < 1024; off += 4) {
uint32_t new_addr = init_addr + off;
((uint32_t *)this->get(new_addr))[0] = 0x00000000;
}
}
{
uint32_t init_addr = 0x72000000;
for (int off = 0; off < 1024; off += 4) {
uint32_t new_addr = init_addr + off;
((uint32_t *)this->get(new_addr))[0] = 0x00000000;
}
}
fseek(fp, 0, SEEK_END);
uint32_t size = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *content = new char[size];
int x = fread(content, 1, size, fp);
if (!x) {
std::cout << "COULD NOT READ FILE\n";
std::abort();
}
int offset = 0;
char *line = content;
// std::cout << "WHTA\n";
while (1) {
if (line[0] == ':') {
uint32_t byteCount = hToI_old(line + 1, 2);
uint32_t nextAddr = hToI_old(line + 3, 4) + offset;
uint32_t key = hToI_old(line + 7, 2);
switch (key) {
case 0:
for (uint32_t i = 0; i < byteCount; i++) {
unsigned add = nextAddr + i;
*(this->get(add)) = hToI_old(line + 9 + i * 2, 2);
// std::cout << "lhi: Address: " << std::hex <<(add) << "\tValue: " << std::hex << hToI_old(line + 9 + i * 2, 2) << std::endl;
}
break;
case 2:
// cout << offset << std::endl;
offset = hToI_old(line + 9, 4) << 4;
break;
case 4:
// cout << offset << std::endl;
offset = hToI_old(line + 9, 4) << 16;
break;
default:
// cout << "??? " << key << std::endl;
break;
}
}
{
uint32_t init_addr = 0x71000000;
for (int off = 0; off < 1024; off+=4) {
uint32_t new_addr = init_addr+off;
((uint32_t*)this->get(new_addr))[0] = 0x00000000;
}
}
while (*line != '\n' && size != 0) {
line++;
size--;
}
{
uint32_t init_addr = 0x72000000;
for (int off = 0; off < 1024; off+=4) {
uint32_t new_addr = init_addr+off;
((uint32_t*)this->get(new_addr))[0] = 0x00000000;
}
}
if (size <= 1)
break;
fseek(fp, 0, SEEK_END);
uint32_t size = ftell(fp);
fseek(fp, 0, SEEK_SET);
char* content = new char[size];
int x = fread(content, 1, size, fp);
line++;
size--;
}
if (!x) {
std::cout << "COULD NOT READ FILE\n"; std::abort();
}
int offset = 0;
char* line = content;
// std::cout << "WHTA\n";
while (1) {
if (line[0] == ':') {
uint32_t byteCount = hToI_old(line + 1, 2);
uint32_t nextAddr = hToI_old(line + 3, 4) + offset;
uint32_t key = hToI_old(line + 7, 2);
switch (key) {
case 0:
for (uint32_t i = 0; i < byteCount; i++) {
unsigned add = nextAddr + i;
*(this->get(add)) = hToI_old(line + 9 + i * 2, 2);
// std::cout << "lhi: Address: " << std::hex <<(add) << "\tValue: " << std::hex << hToI_old(line + 9 + i * 2, 2) << std::endl;
}
break;
case 2:
// cout << offset << endl;
offset = hToI_old(line + 9, 4) << 4;
break;
case 4:
// cout << offset << endl;
offset = hToI_old(line + 9, 4) << 16;
break;
default:
// cout << "??? " << key << endl;
break;
}
}
while (*line != '\n' && size != 0) {
line++;
size--;
}
if (size <= 1)
break;
line++;
size--;
}
if (content)
delete[] content;
}
if (content)
delete[] content;
}

View File

@@ -1,18 +1,14 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#ifndef __MEM_H
#define __MEM_H
#pragma once
#include <ostream>
#include <vector>
#include <queue>
#include <map>
#include <unordered_map>
// #include <pthread.h>
#include "types.h"
namespace Harp {
namespace vortex {
void *consoleInputThread(void *);
struct BadAddress {};
@@ -53,32 +49,6 @@ namespace Harp {
};
class Core;
// class ConsoleMemDevice : public MemDevice {
// public:
// ConsoleMemDevice(Size wS, std::ostream &o, Core &core, bool batch = false);
// ~ConsoleMemDevice() {}
// //virtual Size wordSize() const { return wordSize; }
// virtual Size size() const { return wordSize; }
// virtual Word read(Addr) { pthread_mutex_lock(&cBufLock);
// char c = cBuf.front();
// cBuf.pop();
// pthread_mutex_unlock(&cBufLock);
// return Word(c); }
// virtual void write(Addr a, Word w) { output << char(w); }
// void poll();
// friend void *Harp::consoleInputThread(void *);
// private:
// std::ostream &output;
// Size wordSize;
// Core &core;
// std::queue<char> cBuf;
// pthread_mutex_t cBufLock;
// };
class DiskControllerMemDevice : public MemDevice {
public:
@@ -130,10 +100,6 @@ namespace Harp {
void tlbRm(Addr va);
void tlbFlush() { tlb.clear(); }
#ifdef EMU_INSTRUMENTATION
Addr virtToPhys(Addr va);
#endif
private:
class ADecoder {
public:
@@ -162,7 +128,7 @@ namespace Harp {
ADecoder ad;
std::map<Addr, TLBEntry> tlb;
std::unordered_map<Addr, TLBEntry> tlb;
TLBEntry tlbLookup(Addr vAddr, Word flagMask);
bool disableVm;
@@ -330,7 +296,4 @@ namespace Harp {
void loadHexImpl(std::string path);
};
}
#endif
}

View File

@@ -1,176 +1,78 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <fstream>
#include <stdlib.h>
#include "include/debug.h"
#include "include/types.h"
#include "include/core.h"
#include "include/enc.h"
#include "include/instruction.h"
#include "include/mem.h"
#include "include/obj.h"
#include "include/archdef.h"
#include "include/args.h"
#include "include/help.h"
#include <VX_config.h>
#include <sys/stat.h>
//////////////
/////////////
#include "debug.h"
#include "types.h"
#include "core.h"
#include "args.h"
using namespace Harp;
using namespace HarpTools;
using namespace std;
using namespace vortex;
enum HarpToolMode { HARPTOOL_MODE_ASM, HARPTOOL_MODE_DISASM, HARPTOOL_MODE_EMU,
HARPTOOL_MODE_LD, HARPTOOL_MODE_HELP };
int main(int argc, char **argv) {
HarpToolMode findMode(int argc, char** argv) {
bool mode_asm, mode_disasm, mode_emu, mode_ld, mode_help;
std::string archString("rv32i");
int num_cores(1);
int num_warps(NUM_WARPS);
int num_threads(NUM_THREADS);
std::string imgFileName;
bool showHelp(false);
bool showStats(false);
if (argc == 0) return HARPTOOL_MODE_HELP;
/* Read the command line arguments. */
CommandLineArgFlag fh("-h", "--help", "", showHelp);
CommandLineArgSetter<std::string> fa("-a", "--arch", "", archString);
CommandLineArgSetter<std::string> fi("-i", "--image", "", imgFileName);
CommandLineArgSetter<int> fc("-c", "--cores", "", num_cores);
CommandLineArgSetter<int> fw("-w", "--warps", "", num_warps);
CommandLineArgSetter<int> ft("-t", "--threads", "", num_threads);
CommandLineArgFlag fs("-s", "--stats", "", showStats);
CommandLineArgFlag fh("--help", "-h", "", mode_help);
CommandLineArgFlag fa("-A", "--asm", "", mode_asm);
CommandLineArgFlag fd("-D", "--disasm", "", mode_disasm);
CommandLineArgFlag fe("-E", "--emu", "", mode_emu);
CommandLineArgFlag fl("-L", "--ld", "", mode_ld);
CommandLineArg::readArgs(argc - 1, argv + 1);
CommandLineArg::readArgs((argc == 0?0:1), argv);
CommandLineArg::clearArgs();
if (mode_asm) return HARPTOOL_MODE_ASM;
if (mode_disasm) return HARPTOOL_MODE_DISASM;
if (mode_emu) return HARPTOOL_MODE_EMU;
if (mode_ld) return HARPTOOL_MODE_LD;
return HARPTOOL_MODE_HELP;
}
int emu_main(int argc, char **argv) {
string archString("rv32i");
string imgFileName("a.dsfsdout.bin");
bool showHelp(false), showStats(false), basicMachine(true);
int max_warps(NUM_WARPS);
int max_threads(NUM_THREADS);
/* Read the command line arguments. */
CommandLineArgFlag fh("-h", "--help", "", showHelp);
CommandLineArgSetter<string>fc("-c", "--core", "", imgFileName);
CommandLineArgSetter<string>fa("-a", "--arch", "", archString);
CommandLineArgFlag fs("-s", "--stats", "", showStats);
CommandLineArgFlag fb("-b", "--basic", "", basicMachine);
CommandLineArgSetter<int> fw("-w", "--warps", "", max_warps);
CommandLineArgSetter<int> ft("-t", "--threads", "", max_threads);
CommandLineArg::readArgs(argc, argv);
if (showHelp) {
cout << Help::emuHelp;
return 0;
}
/* Instantiate a Core, RAM, and console output. */
ArchDef arch(archString, max_warps, max_threads);
Decoder *dec;
switch (arch.getEncChar()) {
case 'b': dec = new WordDecoder(arch); break;
case 'w': dec = new WordDecoder(arch); break;
case 'r': dec = new WordDecoder(arch); break;
default:
cout << "Unrecognized decoder type: '" << arch.getEncChar() << "'.\n";
return 1;
}
// std::cout << "TESTING: " << tests[t] << "\n";
MemoryUnit mu(4096, arch.getWordSize(), basicMachine);
Core core(arch, *dec, mu/*, ID in multicore implementations*/);
// RamMemDevice mem(imgFileName.c_str(), arch.getWordSize());
RAM old_ram;
old_ram.loadHexImpl(imgFileName.c_str());
// old_ram.loadHexImpl(tests[t]);
// MemDevice * memory = &old_ram;
// ConsoleMemDevice console(arch.getWordSize(), cout, core, batch);
mu.attach(old_ram, 0);
// mu.attach(console, 1ll<<(arch.getWordSize()*8 - 1));
// mu.attach(console, 0xf0000000);
// core.w[0].pc = 0x8000007c; // If I want to start at a specific location
// std::cout << "ABOUT TO START\n";
// bool count_down = false;
// int cycles_left;
// while (!count_down || (count_down && (cycles_left == 0)))
// {
// if (count_down)
// {
// cycles_left--;
// }
// console.poll();
// core.step();
// bool run = core.running();
// if (!run)
// {
// count_down = true;
// }
// }
struct stat hello;
fstat(0, &hello);
while (core.running()) {core.step(); }
if (showStats) core.printStats();
std::cout << "\n";
return 0;
}
int main(int argc, char** argv) {
Verilated::commandArgs(argc, argv);
Verilated::traceEverOn(true);
try {
switch (findMode(argc - 1, argv + 1)) {
case HARPTOOL_MODE_ASM:
cout << "ASM not supported\n";
return -1;
case HARPTOOL_MODE_DISASM:
cout << "DISASM not supported\n";
return -1;
case HARPTOOL_MODE_EMU:
return emu_main(argc - 2, argv + 2);
case HARPTOOL_MODE_LD:
cout << "LD not supported\n";
return -1;
case HARPTOOL_MODE_HELP:
[[fallthrough]];
default:
cout << "Usage:\n" << Help::mainHelp;
return 0;
}
} catch (BadArg ba) {
cout << "Unrecognized argument \"" << ba.arg << "\".\n";
return 1;
if (showHelp || imgFileName.empty()) {
std::cout << "Vortex emulator command line arguments:\n"
" -i, --image <filename> Program RAM image\n"
" -c, --cores <num> Number of cores\n"
" -w, --warps <num> Number of warps\n"
" -t, --threads <num> Number of threads\n"
" -a, --arch <arch string> Architecture string\n"
" -s, --stats Print stats on exit.\n";
return 0;
}
ArchDef arch(archString, num_cores, num_warps, num_threads);
Decoder decoder(arch);
MemoryUnit mu(4096, arch.getWordSize(), true);
RAM old_ram;
old_ram.loadHexImpl(imgFileName.c_str());
mu.attach(old_ram, 0);
struct stat hello;
fstat(0, &hello);
std::vector<std::shared_ptr<Core>> cores(num_cores);
for (int i = 0; i < num_cores; ++i) {
cores[i] = std::make_shared<Core>(arch, decoder, mu);
}
bool running;
do {
running = false;
for (int i = 0; i < num_cores; ++i) {
if (!cores[i]->running())
continue;
running = true;
cores[i]->step();
}
} while (running);
return 0;
}

View File

@@ -4,6 +4,6 @@ echo start > results.txt
make
printf "Fasten your seatbelts ladies and gentelmen!!\n\n\n\n"
#cd obj_dir && ./Vcache_simX -E -a rv32i --core ../benchmarks/vector/vecadd/vx_vec_vecadd.hex -s -b 1> emulator.debug
#cd obj_dir && ./Vcache_simX -E -a rv32i --core ../benchmarks/vector/saxpy/vx_vec_saxpy.hex -s -b 1> emulator.debug
cd obj_dir && ./Vcache_simX -E -a rv32i --core ../benchmarks/vector/sgemm_nn/vx_vec_sgemm_nn.hex -s -b 1> emulator.debug
#./simX -a rv32i -i ../benchmarks/vector/vecadd/vx_vec_vecadd.hex -s 1> emulator.debug
#./simX -a rv32i -i ../benchmarks/vector/saxpy/vx_vec_saxpy.hex -s 1> emulator.debug
./simX -a rv32i -i ../benchmarks/vector/sgemm_nn/vx_vec_sgemm_nn.hex -s 1> emulator.debug

View File

@@ -1,143 +1,142 @@
#!/bin/bash
make
cd obj_dir
echo start > results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-add.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-add.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-add.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-add.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-addi.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-addi.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-addi.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-addi.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-and.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-and.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-and.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-and.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-andi.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-andi.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-andi.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-andi.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-auipc.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-auipc.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-auipc.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-auipc.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-beq.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-beq.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-beq.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-beq.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-bge.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-bge.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-bge.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-bge.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-bgeu.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-bgeu.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-bgeu.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-bgeu.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-blt.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-blt.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-blt.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-blt.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-bltu.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-bltu.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-bltu.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-bltu.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-bne.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-bne.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-bne.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-bne.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-jal.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-jal.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-jal.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-jal.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-jalr.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-jalr.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-jalr.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-jalr.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-lb.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-lb.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-lb.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-lb.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-lbu.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-lbu.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-lbu.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-lbu.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-lh.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-lh.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-lh.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-lh.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-lhu.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-lhu.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-lhu.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-lhu.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-lui.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-lui.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-lui.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-lui.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-lw.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-lw.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-lw.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-lw.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-or.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-or.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-or.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-or.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-ori.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-ori.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-ori.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-ori.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-sb.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-sb.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-sb.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-sb.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-sh.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-sh.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-sh.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-sh.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-simple.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-simple.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-simple.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-simple.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-sll.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-sll.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-sll.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-sll.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-slli.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-slli.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-slli.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-slli.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-slt.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-slt.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-slt.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-slt.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-slti.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-slti.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-slti.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-slti.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-sltiu.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-sltiu.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-sltiu.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-sltiu.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-sltu.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-sltu.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-sltu.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-sltu.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-sra.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-sra.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-sra.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-sra.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-srai.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-srai.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-srai.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-srai.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-srl.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-srl.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-srl.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-srl.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-srli.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-srli.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-srli.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-srli.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-sub.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-sub.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-sub.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-sub.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-sw.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-sw.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-sw.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-sw.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-xor.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-xor.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-xor.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-xor.hex -s >> results.txt
echo ./../benchmarks/riscv_tests/rv32ui-p-xori.hex >> results.txt
./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32ui-p-xori.hex -s -b >> results.txt
echo ./../benchmarks/isa/riscv_tests/rv32ui-p-xori.hex >> results.txt
./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32ui-p-xori.hex -s >> results.txt
# echo ./../benchmarks/riscv_tests/rv32um-p-div.hex >> results.txt
# ./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32um-p-div.hex -s -b >> results.txt
# echo ./../benchmarks/isa/riscv_tests/rv32um-p-div.hex >> results.txt
# ./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32um-p-div.hex -s >> results.txt
# echo ./../benchmarks/riscv_tests/rv32um-p-divu.hex >> results.txt
# ./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32um-p-divu.hex -s -b >> results.txt
# echo ./../benchmarks/isa/riscv_tests/rv32um-p-divu.hex >> results.txt
# ./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32um-p-divu.hex -s >> results.txt
# echo ./../benchmarks/riscv_tests/rv32um-p-mul.hex >> results.txt
# ./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32um-p-mul.hex -s -b >> results.txt
# echo ./../benchmarks/isa/riscv_tests/rv32um-p-mul.hex >> results.txt
# ./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32um-p-mul.hex -s >> results.txt
# echo ./../benchmarks/riscv_tests/rv32um-p-mulh.hex >> results.txt
# ./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32um-p-mulh.hex -s -b >> results.txt
# echo ./../benchmarks/isa/riscv_tests/rv32um-p-mulh.hex >> results.txt
# ./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32um-p-mulh.hex -s >> results.txt
# echo ./../benchmarks/riscv_tests/rv32um-p-mulhsu.hex >> results.txt
# ./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32um-p-mulhsu.hex -s -b >> results.txt
# echo ./../benchmarks/isa/riscv_tests/rv32um-p-mulhsu.hex >> results.txt
# ./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32um-p-mulhsu.hex -s >> results.txt
# echo ./../benchmarks/riscv_tests/rv32um-p-mulhu.hex >> results.txt
# ./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32um-p-mulhu.hex -s -b >> results.txt
# echo ./../benchmarks/isa/riscv_tests/rv32um-p-mulhu.hex >> results.txt
# ./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32um-p-mulhu.hex -s >> results.txt
# echo ./../benchmarks/riscv_tests/rv32um-p-rem.hex >> results.txt
# ./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32um-p-rem.hex -s -b >> results.txt
# echo ./../benchmarks/isa/riscv_tests/rv32um-p-rem.hex >> results.txt
# ./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32um-p-rem.hex -s >> results.txt
# echo ./../benchmarks/riscv_tests/rv32um-p-remu.hex >> results.txt
# ./Vcache_simX -E -a rv32i --core ../benchmarks/riscv_tests/rv32um-p-remu.hex -s -b >> results.txt
# echo ./../benchmarks/isa/riscv_tests/rv32um-p-remu.hex >> results.txt
# ./simX -a rv32i -i ../benchmarks/isa/riscv_tests/rv32um-p-remu.hex -s >> results.txt

View File

@@ -3,17 +3,14 @@
make
make -C ../runtime/tests/dev
make -C ../runtime/tests/hello
make -C ../runtime/tests/nativevecadd
make -C ../runtime/tests/nlTest
make -C ../runtime/tests/simple
make -C ../runtime/tests/vecadd
cd obj_dir
echo start > results.txt
printf "Fasten your seatbelts ladies and gentelmen!!\n\n\n\n"
#./Vcache_simX -E -a rv32i --core ../runtime/tests/dev/vx_dev_main.hex -s -b 1> emulator.debug
#./Vcache_simX -E -a rv32i --core ../runtime/tests/hello/hello.hex -s -b 1> emulator.debug
./Vcache_simX -E -a rv32i --core ../runtime/tests/nativevecadd/vx_pocl_main.hex -s -b 1> emulator.debug
./Vcache_simX -E -a rv32i --core ../runtime/tests/simple/vx_simple_main.hex -s -b 1> emulator.debug
./Vcache_simX -E -a rv32i --core ../runtime/tests/vecadd/vx_pocl_main.hex -s -b 1> emulator.debug
#./simX -a rv32i -i ../runtime/tests/dev/vx_dev_main.hex -s 1> emulator.debug
#./simX -a rv32i -i ../runtime/tests/hello/hello.hex -s 1> emulator.debug
./simX -a rv32i -i ../runtime/tests/nlTest/vx_nl_main.hex -s 1> emulator.debug
./simX -a rv32i -i ../runtime/tests/simple/vx_simple_main.hex -s 1> emulator.debug

View File

@@ -5,4 +5,4 @@ echo start > results.txt
# echo ../kernel/vortex_test.hex
make
printf "Fasten your seatbelts ladies and gentelmen!!\n\n\n\n"
cd obj_dir && ./Vcache_simX -E -a rv32i --core ../rvvector/basic/vx_vector_main.hex -s -b 1> emulator.debug
./Vcache_simX -a rv32i -i ../rvvector/basic/vx_vector_main.hex -s 1> emulator.debug

View File

@@ -1,10 +1,9 @@
#pragma once
namespace Harp {
namespace vortex {
typedef struct
{
struct trace_inst_t {
// Warp step
bool valid_inst;
unsigned pc;
@@ -28,14 +27,13 @@ namespace Harp {
unsigned * mem_addresses;
// dmem interface
int mem_stall_cycles;
int fetch_stall_cycles;
unsigned long mem_stall_cycles;
unsigned long fetch_stall_cycles;
// Instruction execute
bool stall_warp;
bool wspawn;
bool stalled;
} trace_inst_t;
};
}

28
simX/types.h Normal file
View File

@@ -0,0 +1,28 @@
#pragma once
#include <stdint.h>
#include <VX_config.h>
namespace vortex {
typedef uint8_t Byte;
typedef uint32_t Word;
typedef uint32_t Word_u;
typedef int32_t Word_s;
typedef Word_u Addr;
typedef Word_u Size;
typedef unsigned RegNum;
typedef unsigned ThdNum;
enum MemFlags {
RD_USR = 1,
WR_USR = 2,
EX_USR = 4,
RD_SUP = 8,
WR_SUP = 16,
EX_SUP = 32
};
}

View File

@@ -1,28 +1,25 @@
/*******************************************************************************
HARPtools by Chad D. Kersey, Summer 2011
*******************************************************************************/
#include <vector>
#include "include/types.h"
#include "include/util.h"
#include <iostream>
#include <stdexcept>
#include "types.h"
#include "util.h"
using namespace Harp;
using namespace std;
using namespace vortex;
// Make it easy for autotools-based build systems to detect this library.
extern "C" {
int harplib_present = 1;
Word vortex::signExt(Word w, Size bit, Word mask) {
if (w >> (bit - 1))
w |= ~mask;
return w;
}
void Harp::wordToBytes(Byte *b, Word_u w, Size wordSize) {
void vortex::wordToBytes(Byte *b, Word_u w, Size wordSize) {
while (wordSize--) {
*(b++) = w & 0xff;
w >>= 8;
}
}
Word_u Harp::bytesToWord(const Byte *b, Size wordSize) {
Word_u vortex::bytesToWord(const Byte *b, Size wordSize) {
Word_u w = 0;
b += wordSize-1;
while (wordSize--) {
@@ -32,7 +29,7 @@ Word_u Harp::bytesToWord(const Byte *b, Size wordSize) {
return w;
}
Word_u Harp::flagsToWord(bool r, bool w, bool x) {
Word_u vortex::flagsToWord(bool r, bool w, bool x) {
Word_u word = 0;
if (r) word |= RD_USR;
if (w) word |= WR_USR;
@@ -40,19 +37,21 @@ Word_u Harp::flagsToWord(bool r, bool w, bool x) {
return word;
}
void Harp::wordToFlags(bool &r, bool &w, bool &x, Word_u f) {
void vortex::wordToFlags(bool &r, bool &w, bool &x, Word_u f) {
r = f & RD_USR;
w = f & WR_USR;
x = f & EX_USR;
}
Byte Harp::readByte(const vector<Byte> &b, Size &n) {
if (b.size() <= n) throw OutOfBytes();
Byte vortex::readByte(const std::vector<Byte> &b, Size &n) {
if (b.size() <= n)
throw std::out_of_range("out of range");
return b[n++];
}
Word_u Harp::readWord(const vector<Byte> &b, Size &n, Size wordSize) {
// if (b.size() - n < wordSize) throw OutOfBytes();
Word_u vortex::readWord(const std::vector<Byte> &b, Size &n, Size wordSize) {
if (b.size() - n < wordSize)
throw std::out_of_range("out of range");
Word_u w(0);
n += wordSize;
// std::cout << "wordSize: " << wordSize << "\n";
@@ -62,16 +61,15 @@ Word_u Harp::readWord(const vector<Byte> &b, Size &n, Size wordSize) {
w |= b[n - i - 1];
}
// cout << "b[0]" << std::hex << w << "\n";
// throw OutOfBytes();
return w;
}
void Harp::writeByte(vector<Byte> &p, Size &n, Byte b) {
void vortex::writeByte(std::vector<Byte> &p, Size &n, Byte b) {
if (p.size() <= n) p.resize(n+1);
p[n++] = b;
}
void Harp::writeWord(vector<Byte> &p, Size &n, Size wordSize, Word w) {
void vortex::writeWord(std::vector<Byte> &p, Size &n, Size wordSize, Word w) {
if (p.size() < (n+wordSize)) p.resize(n+wordSize);
while (wordSize--) {
p[n++] = w & 0xff;

25
simX/util.h Normal file
View File

@@ -0,0 +1,25 @@
#pragma once
#include <vector>
#include "types.h"
namespace vortex {
template <typename... Args>
void unused(Args&&...) {}
#define __unused(...) unused(__VA_ARGS__)
Word signExt(Word w, Size bit, Word mask);
Word_u bytesToWord(const Byte *b, Size wordSize);
void wordToBytes(Byte *b, Word_u w, Size wordSize);
Word_u flagsToWord(bool r, bool w, bool x);
void wordToFlags(bool &r, bool &w, bool &x, Word_u f);
Byte readByte(const std::vector<Byte> &b, Size &n);
Word_u readWord(const std::vector<Byte> &b, Size &n, Size wordSize);
void writeByte(std::vector<Byte> &p, Size &n, Byte b);
void writeWord(std::vector<Byte> &p, Size &n, Size wordSize, Word w);
}

133
simX/warp.cpp Normal file
View File

@@ -0,0 +1,133 @@
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include "util.h"
#include "instr.h"
#include "core.h"
using namespace vortex;
Warp::Warp(Core *core, Word id)
: id_(id)
, core_(core)
, pc_(0x80000000)
, shadowPc_(0)
, activeThreads_(0)
, shadowActiveThreads_(0)
, shadowReg_(core_->arch().getNumRegs())
, VLEN_(1024)
, interruptEnable_(true)
, shadowInterruptEnable_(false)
, supervisorMode_(true)
, shadowSupervisorMode_(false)
, spawned_(false)
, steps_(0)
, insts_(0)
, loads_(0)
, stores_(0) {
D(3, "Creating a new thread with PC: " << std::hex << pc_);
/* Build the register file. */
Word regNum(0);
for (Word j = 0; j < core_->arch().getNumThreads(); ++j) {
regFile_.push_back(std::vector<Reg<Word>>(0));
for (Word i = 0; i < core_->arch().getNumRegs(); ++i) {
regFile_[j].push_back(Reg<Word>(id, regNum++));
}
bool act = false;
if (j == 0)
act = true;
tmask_.push_back(act);
shadowTmask_.push_back(act);
}
for (Word i = 0; i < (1 << 12); i++) {
csrs_.push_back(Reg<uint16_t>(id, regNum++));
}
/* Set initial register contents. */
regFile_[0][0] = (core_->arch().getNumThreads() << (core_->arch().getWordSize() * 8 / 2)) | id;
}
void Warp::step(trace_inst_t *trace_inst) {
Size fetchPos(0);
Size decPos;
Size wordSize(core_->arch().getWordSize());
std::vector<Byte> fetchBuffer(wordSize);
if (activeThreads_ == 0)
return;
++steps_;
D(3, "current PC=0x" << std::hex << pc_);
// std::cout << "pc: " << std::hex << pc << "\n";
trace_inst->pc = pc_;
/* Fetch and decode. */
if (wordSize < sizeof(pc_))
pc_ &= ((1ll << (wordSize * 8)) - 1);
unsigned fetchSize = 4;
fetchBuffer.resize(fetchSize);
Word fetched = core_->mem().fetch(pc_ + fetchPos, supervisorMode_);
writeWord(fetchBuffer, fetchPos, fetchSize, fetched);
decPos = 0;
std::shared_ptr<Instr> instr = core_->decoder().decode(fetchBuffer, decPos, trace_inst);
// Update pc
pc_ += decPos;
// Execute
this->execute(*instr, trace_inst);
// At Debug Level 3, print debug info after each instruction.
D(3, "Register state:");
for (unsigned i = 0; i < regFile_[0].size(); ++i) {
D_RAW(" %r" << std::setfill('0') << std::setw(2) << std::dec << i << ':');
for (unsigned j = 0; j < (activeThreads_); ++j)
D_RAW(' ' << std::setfill('0') << std::setw(8) << std::hex << regFile_[j][i] << std::setfill(' ') << ' ');
D_RAW('(' << shadowReg_[i] << ')' << std::endl);
}
DPH(3, "Thread mask:");
for (unsigned i = 0; i < tmask_.size(); ++i)
DPN(3, " " << tmask_[i]);
DPN(3, "\n");
}
bool Warp::interrupt(Word r0) {
if (!interruptEnable_)
return false;
shadowActiveThreads_ = activeThreads_;
shadowTmask_ = tmask_;
shadowInterruptEnable_ = interruptEnable_; /* For traps. */
shadowSupervisorMode_ = supervisorMode_;
for (Word i = 0; i < regFile_[0].size(); ++i)
shadowReg_[i] = regFile_[0][i];
for (Word i = 0; i < regFile_.size(); ++i)
tmask_[i] = 1;
shadowPc_ = pc_;
activeThreads_ = 1;
interruptEnable_ = false;
supervisorMode_ = true;
regFile_[0][0] = r0;
pc_ = core_->interruptEntry();
return true;
}
void Warp::printStats() const {
std::cout << "Steps : " << steps_ << std::endl
<< "Insts : " << insts_ << std::endl
<< "Loads : " << loads_ << std::endl
<< "Stores: " << stores_ << std::endl;
}

188
simX/warp.h Normal file
View File

@@ -0,0 +1,188 @@
#ifndef __WARP_H
#define __WARP_H
#include <vector>
#include <stack>
#include "types.h"
namespace vortex {
template <typename T>
class Reg {
public:
Reg()
: value_(0), cpuId_(0), regNum_(0) {}
Reg(Word c, Word n)
: value_(0), cpuId_(c), regNum_(n) {}
Reg(Word c, Word n, T v)
: value_(v), cpuId_(c), regNum_(n) {}
const T &value() const {
return value_;
}
Reg &operator=(T r) {
if (regNum_) {
value_ = r;
doWrite();
}
return *this;
}
operator T() const {
doRead();
return value_;
}
void trunc(Size s) {
Word mask((~0ull >> (sizeof(Word) - s) * 8));
value_ &= mask;
}
private:
T value_;
Word cpuId_, regNum_;
void doWrite() const {}
void doRead() const {}
};
///////////////////////////////////////////////////////////////////////////////
struct DomStackEntry {
DomStackEntry(
unsigned p,
const std::vector<std::vector<Reg<Word>>> &m,
std::vector<bool> &tm,
Word pc
) : pc(pc)
, fallThrough(false)
, uni(false) {
for (unsigned i = 0; i < m.size(); ++i) {
tmask.push_back(!bool(m[i][p]) && tm[i]);
}
}
DomStackEntry(const std::vector<bool> &tmask)
: tmask(tmask), fallThrough(true), uni(false) {}
std::vector<bool> tmask;
Word pc;
bool fallThrough;
bool uni;
};
struct vtype {
int vill;
int vediv;
int vsew;
int vlmul;
};
class Core;
class Instr;
class trace_inst_t;
class Warp {
public:
Warp(Core *core, Word id = 0);
void step(trace_inst_t *);
bool interrupt(Word r0);
bool running() const {
return (activeThreads_ != 0);
}
void printStats() const;
Core *core() {
return core_;
}
Word id() const {
return id_;
}
Word get_pc() const {
return pc_;
}
void set_pc(Word pc) {
pc_ = pc;
}
void setActiveThreads(Size activeThreads) {
activeThreads_ = activeThreads;
}
Size getActiveThreads() const {
return activeThreads_;
}
void setSpawned(bool spawned) {
spawned_ = spawned;
}
void setSupervisorMode(bool supervisorMode) {
supervisorMode_ = supervisorMode;
}
bool getSupervisorMode() const {
return supervisorMode_;
}
void setTmask(size_t index, bool value) {
tmask_[index] = value;
}
private:
void execute(Instr &instr, trace_inst_t *);
struct MemAccess {
MemAccess(bool w, Word a)
: wr(w), addr(a) {}
bool wr;
Word addr;
};
std::vector<MemAccess> memAccesses_;
Word id_;
Core *core_;
Word pc_;
Word shadowPc_;
Size activeThreads_;
Size shadowActiveThreads_;
std::vector<std::vector<Reg<Word>>> regFile_;
std::vector<Reg<uint16_t>> csrs_;
std::vector<bool> tmask_;
std::vector<bool> shadowTmask_;
std::stack<DomStackEntry> domStack_;
std::vector<Word> shadowReg_;
struct vtype vtype_; // both of them are XLEN WIDE
int vl_; // both of them are XLEN WIDE
Word VLEN_; // total vector length
std::vector<std::vector<Reg<char *>>> vregFile_; // 32 vector registers
bool interruptEnable_;
bool shadowInterruptEnable_;
bool supervisorMode_;
bool shadowSupervisorMode_;
bool spawned_;
unsigned long steps_;
unsigned long insts_;
unsigned long loads_;
unsigned long stores_;
};
}
#endif