summaryrefslogtreecommitdiff
path: root/src/cuda-sim
diff options
context:
space:
mode:
authorsspenst <[email protected]>2016-08-04 13:09:41 -0700
committersspenst <[email protected]>2016-08-04 13:09:41 -0700
commitfeda07a5e0053ef2f2bfa382f5ba9a7a0b6c6bf5 (patch)
tree22be33d4b51a6d04dd32aac7ea8b199f213e0f17 /src/cuda-sim
parente08fc0294fe919a198477b771a414c5102430188 (diff)
A thread executing BSMAD is now able to access information from all threads in its warp
Diffstat (limited to 'src/cuda-sim')
-rw-r--r--src/cuda-sim/cuda-sim.cc14
-rw-r--r--src/cuda-sim/instructions.cc158
-rw-r--r--src/cuda-sim/opcodes.def3
-rw-r--r--src/cuda-sim/opcodes.h4
-rw-r--r--src/cuda-sim/ptx.l3
5 files changed, 181 insertions, 1 deletions
diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc
index e194a2a..059fbe2 100644
--- a/src/cuda-sim/cuda-sim.cc
+++ b/src/cuda-sim/cuda-sim.cc
@@ -849,8 +849,10 @@ void ptx_instruction::pre_decode()
switch ( get_opcode() ) {
#define OP_DEF(OP,FUNC,STR,DST,CLASSIFICATION) case OP: has_dst = (DST!=0); break;
+#define OP_W_DEF(OP,FUNC,STR,DST,CLASSIFICATION) case OP: has_dst = (DST!=0); break;
#include "opcodes.def"
#undef OP_DEF
+#undef OP_W_DEF
default:
printf( "Execution error: Invalid opcode (0x%x)\n", get_opcode() );
break;
@@ -1242,10 +1244,22 @@ void ptx_thread_info::ptx_exec_inst( warp_inst_t &inst, unsigned lane_id)
*((warp_inst_t*)pJ) = inst; // copy active mask information
pI = pJ;
}
+ /*const ptx_instruction **pA;
+ if( pI->get_opcode() == BSMAD_OP ) {
+ //pA = (const ptx_instruction**)malloc(get_core()->get_warp_size()*(sizeof(ptx_instruction*)));
+ pA = (const ptx_instruction**)malloc(8*(sizeof(ptx_instruction*)));
+ for (int i = 0; i < get_core()->get_warp_size() && inst.active(i); i++) {
+ //pA[i] = get_core()->get_thread_info()[inst.warp_id() * get_core()->get_warp_size() + i]->func_info()->get_instruction(pc+(i-lane_id)*(pI->inst_size()));
+ int tid = inst.warp_id() * get_core()->get_warp_size() + i;
+ pA[i] = get_core()->get_thread_info()[tid]->func_info()->get_instruction(pc);
+ }
+ }*/
switch ( pI->get_opcode() ) {
#define OP_DEF(OP,FUNC,STR,DST,CLASSIFICATION) case OP: FUNC(pI,this); op_classification = CLASSIFICATION; break;
+#define OP_W_DEF(OP,FUNC,STR,DST,CLASSIFICATION) case OP: FUNC(pI,get_core(),inst); op_classification = CLASSIFICATION; break;
#include "opcodes.def"
#undef OP_DEF
+#undef OP_W_DEF
default: printf( "Execution error: Invalid opcode (0x%x)\n", pI->get_opcode() ); break;
}
delete pJ;
diff --git a/src/cuda-sim/instructions.cc b/src/cuda-sim/instructions.cc
index b401bef..618add1 100644
--- a/src/cuda-sim/instructions.cc
+++ b/src/cuda-sim/instructions.cc
@@ -47,8 +47,10 @@ unsigned ptx_instruction::g_num_ptx_inst_uid=0;
const char *g_opcode_string[NUM_OPCODES] = {
#define OP_DEF(OP,FUNC,STR,DST,CLASSIFICATION) STR,
+#define OP_W_DEF(OP,FUNC,STR,DST,CLASSIFICATION) STR,
#include "opcodes.def"
#undef OP_DEF
+#undef OP_W_DEF
};
void inst_not_implemented( const ptx_instruction * pI ) ;
@@ -1456,6 +1458,162 @@ void breakaddr_impl( const ptx_instruction *pI, ptx_thread_info *thread )
void brev_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); }
void brkpt_impl( const ptx_instruction *pI, ptx_thread_info *thread ) { inst_not_implemented(pI); }
+void bsmad_impl( const ptx_instruction *pI, core_t *core, warp_inst_t inst )
+{
+ for (int i = 0; i < core->get_warp_size() && inst.active(i); i++) {
+ const operand_info &dst = pI->dst();
+ unsigned type = pI->get_type();
+
+ int tid = inst.warp_id() * core->get_warp_size() + i;
+ ptx_thread_info *thread = core->get_thread_info()[tid];
+ ptx_reg_t data = thread->get_operand_value(dst, dst, type, thread, 1);
+ printf("BSMAD - DATA FROM THREAD %d: %d\n", i, data.u32);
+ }
+ printf("\n");
+ /*const unsigned OPERANDS = 9;
+ // 0 = output
+ // 1 = input precision
+ // 2 = output precision
+ // 3 = buffer0
+ // 4 = buffer1
+ // 5 = buffer2
+ // 6 = buffer3
+ // 7 = synapse value
+ // 8 = output value
+ // as a temporary solution, let 0 be the base address of output, which is an array of shared memory
+ // that will be filled when the last thread completes the bsmad instruction
+ // maybe you can store the addresses of other ptx_instruction in sstarr memory and then update dst later?
+ // not sure if that works
+
+ //ptx_instruction * cpI = const_cast<ptx_instruction *>(pI);
+ const operand_info &src[OPERANDS];
+ ptx_reg_t src_data[OPERANDS];
+ unsigned type = pI->get_type();
+
+ for (int i = 0; i < OPERANDS; i++) {
+ src[i] = pI->operand_lookup(i);
+ src_data[i] = thread->get_operand_value(src[i], src[0], type, thread, 1);
+ }
+
+ memory_space_t space = pI->get_space();
+ memory_space *mem = NULL;
+ addr_t addr = thread->get_tid().x * 24; // 4 bytes per register * 6 registers per thread = 24 bytes
+
+ decode_space(space,thread,src[0],mem,addr);
+
+ size_t size;
+ int t;
+ type_info_key::type_decode(type,size,t);
+
+ // store src_data[1:4] in sstarr memory
+ for (int i = 0; i < 6; i++) {
+ mem->write(addr + i*4,size/8,&src_data[i+3].s64,thread,pI);
+ }
+
+ // sync threads
+ //cpI->set_bar_id(16); // use 16 for sst because bar uses an int from 0-15
+
+ thread->m_last_effective_address = addr;
+ thread->m_last_memory_space = space;
+ thread->m_last_dram_callback.function = bar_callback;
+ thread->m_last_dram_callback.instruction = cpI;
+
+ // the last thread that executes loads all of the data back from sstarr memory
+ ptx_cta_info *cta_info = thread->m_cta_info;((32/ip)*4)/(32/op)
+ const int NUM_THREADS = cta_info->num_threads();
+ cta_info->inc_bar_threads();
+ if (NUM_THREADS == cta_info->get_bar_threads()) {
+ // load all things from sstarr memory
+ addr = 0;
+ ptx_reg_t data;
+ unsigned sstarr_data[NUM_THREADS*6];
+ for (int i = 0; i < NUM_THREADS*6; i++) {
+ data.u64 = 0;
+ mem->read(addr+(i*4),size/8,&data.s64);
+ sstarr_data[i] = data.u32;
+ }
+
+ // unpack registers, add data from across threads
+ unsigned ip = src_data[1].u32;
+ unsigned op = src_data[2].u32;
+ unsigned unpacked_output[(32/ip)*4];
+
+ for (unsigned i = 0; i < (32/ip)*4; i++) {
+ unsigned buf = i/(32/ip);
+ unsigned pos = i%(32/ip);
+
+ unsigned mask = 0;
+ for (int b = 0; b < ip; b++) {
+ mask |= (1 << b);
+ }
+ mask <<= (pos*ip);
+
+ int sum = 0;
+ for (int j = 0; j < NUM_THREADS; j++) {
+ sum += mask & sstarr_data[j*6 + buf];
+ }
+ unpacked_output[i] = sum;
+ }
+
+ // truncate result, repack, store in shared mem
+ unsigned output_regs[((32/ip)*4)/(32/op) + (((32/ip)*4)%(32/op) != 0)];
+
+
+
+ unsigned offset = 0;
+ addr = 0;
+ ptx_reg_t data;
+ float sstarr_fdata[NUM_THREADS];
+ signed long long sstarr_ldata[NUM_THREADS];
+ // loop through all of the threads
+ for (int tid = 0; tid < NUM_THREADS; tid++) {
+ data.u64=0;
+ mem->read(addr+(tid*4),size/8,&data.s64);
+ sstarr_fdata[tid] = data.f32;
+ sstarr_ldata[tid] = data.s64;
+ }
+
+ // squeeze the zeros out of the array and store data back into original array
+ mem = NULL;
+ addr = src1_data.u32;
+ space.set_type(global_space);
+ decode_space(space,thread,src1,mem,addr);
+ // store nonzero entries and indices
+ for (int tid = 0; tid < NUM_THREADS; tid++) {
+ if (sstarr_fdata[tid] != 0) {
+ float ftid = (float)tid;
+ mem->write(addr+(offset*4),size/8,&sstarr_ldata[tid],thread,pI);
+ mem->write(addr+((NUM_THREADS+offset)*4),size/8,&ftid,thread,pI);
+ offset++;
+ }
+ }
+ // store the number of nonzero elements in the array
+ data = thread->get_op((32/ip)*4)/(32/op)erand_value(src1, dst, type, thread, 1);
+ data.s64 += 4*(offset-1);
+ thread->set_operand_value(dst, data, type, thread, pI);
+
+ // fill the rest of the array with zeros (dst should always have a 0 in it)
+ while (offset < NUM_THREADS) {
+ mem->write(addr+(offset*4),size/8,&dst_data.s64,thread,pI);
+ offset++;
+ }
+
+ cta_info->reset_bar_threads();
+ thread->m_last_effective_address = addr+(NUM_THREADS-1)*4;
+ thread->m_last_memory_space = space;
+ }*/
+}
+
+void bsmul_impl( const ptx_instruction *pI, ptx_thread_info *thread )
+{
+ printf("BSMUL instruction found.\n");
+}
+
+void buf_impl( const ptx_instruction *pI, ptx_thread_info *thread )
+{
+ printf("BUF instruction found.\n");
+}
+
void call_impl( const ptx_instruction *pI, ptx_thread_info *thread )
{
static unsigned call_uid_next = 1;
diff --git a/src/cuda-sim/opcodes.def b/src/cuda-sim/opcodes.def
index 1af04ea..d0e6f25 100644
--- a/src/cuda-sim/opcodes.def
+++ b/src/cuda-sim/opcodes.def
@@ -52,6 +52,9 @@ OP_DEF(BRA_OP,bra_impl,"bra",0,3)
OP_DEF(BRX_OP,brx_impl,"brx",0,3)
OP_DEF(BREV_OP,brev_impl,"brev",1,1)
OP_DEF(BRKPT_OP,brkpt_impl,"brkpt",1,9)
+OP_W_DEF(BSMAD_OP,bsmad_impl,"bsmad",0,1)
+OP_DEF(BSMUL_OP,bsmul_impl,"bsmul",1,1)
+OP_DEF(BUF_OP,buf_impl,"buf",0,5)
OP_DEF(CALL_OP,call_impl,"call",1,3)
OP_DEF(CALLP_OP,callp_impl,"callp",1,3)
OP_DEF(CLZ_OP,clz_impl,"clz",1,1)
diff --git a/src/cuda-sim/opcodes.h b/src/cuda-sim/opcodes.h
index 871091c..aa133da 100644
--- a/src/cuda-sim/opcodes.h
+++ b/src/cuda-sim/opcodes.h
@@ -30,9 +30,11 @@
enum opcode_t {
#define OP_DEF(OP,FUNC,STR,DST,CLASSIFICATION) OP,
+#define OP_W_DEF(OP,FUNC,STR,DST,CLASSIFICATION) OP,
#include "opcodes.def"
- NUM_OPCODES
+ NUM_OPCODES
#undef OP_DEF
+#undef OP_W_DEF
};
enum special_regs {
diff --git a/src/cuda-sim/ptx.l b/src/cuda-sim/ptx.l
index 69349a0..e0d7b9d 100644
--- a/src/cuda-sim/ptx.l
+++ b/src/cuda-sim/ptx.l
@@ -68,6 +68,9 @@ bra TC; ptx_lval.int_value = BRA_OP; return OPCODE;
brx TC; ptx_lval.int_value = BRX_OP; return OPCODE;
brev TC; ptx_lval.int_value = BREV_OP; return OPCODE;
brkpt TC; ptx_lval.int_value = BRKPT_OP; return OPCODE;
+bsmad TC; ptx_lval.int_value = BSMAD_OP; return OPCODE;
+bsmul TC; ptx_lval.int_value = BSMUL_OP; return OPCODE;
+buf TC; ptx_lval.int_value = BUF_OP; return OPCODE;
call TC; BEGIN(NOT_OPCODE); ptx_lval.int_value = CALL_OP; return OPCODE; // blocking opcode token in case the callee has the same name as an opcode
callp TC; BEGIN(NOT_OPCODE); ptx_lval.int_value = CALLP_OP; return OPCODE;
clz TC; ptx_lval.int_value = CLZ_OP; return OPCODE;