📄 multi_producer1.uc
字号:
;------------------------------------------------------------------------------------
;
; I N T E L P R O P R I E T A R Y
;
; COPYRIGHT (c) 2001 BY INTEL CORPORATION. ALL RIGHTS
; RESERVED. NO PART OF THIS PROGRAM OR PUBLICATION MAY
; BE REPRODUCED, TRANSMITTED, TRANSCRIBED, STORED IN A
; RETRIEVAL SYSTEM, OR TRANSLATED INTO ANY LANGUAGE OR COMPUTER
; LANGUAGE IN ANY FORM OR BY ANY MEANS, ELECTRONIC, MECHANICAL,
; MAGNETIC, OPTICAL, CHEMICAL, MANUAL, OR OTHERWISE, WITHOUT
; THE PRIOR WRITTEN PERMISSION OF :
;
; INTEL CORPORATION
;
; 2200 MISSION COLLEGE BLVD
;
; SANTA CLARA, CALIFORNIA 95052-8119
;
;------------------------------------------------------------------------------------
// File : multi_producer1.uc
//
// Description : (see multi_producer.uc for an overall description)
//
// This file contains code for ME1. ME1 along with ME0 is the producer.
//
// 1. wait for signal (from previous thread) (of prev ME, for thread 0)
//
// 2. If ring is full, stall
// 3. Produce on the ring (ring put) (this is a length operation, will take some time to complete)
// 4. Signal next thread.
// 5 Can do anything else here.
// 6. wait for ring put to complete and a signal from prev. thread
// 7. go back to producing (step 2)
//
//
// Note: Step 3 and Step 4. Even though Step 4 take sometime to complete, we do not wait
// to signal the next thread. (we can right away signal the next thread to start producing
// a word)
#include "scratchring.h"
#include "sig_macros.uc"
// register and signal declarations
.reg $wdata, ring, @data
.sig scr_put ; signal for scratch put,
.sig volatile wake_thrd ; signal for waking threads
// We use manual allocation for these signals because we have problems
// using "visible" (.sig visible wake_thrd in multi_producer) and "remote" in this file
// Until it is solved, we'll have to use this manual allocation.
.addr wake_thrd SIG_WAKE_THRD
// Code for thread 0
.if (ctx() == 0)
immed[@data, 1] ; shared data across all threads in this ME
.endif
// All other Threads Start here
common_code#:
alu_shf[ring, --, b, RING_NUMBER, <<2] ; ring number in a register
ctx_arb [wake_thrd] ; Wait for signal 1 from previous thread
; For Thread 0, the signal will come from Thread 7 of ME0
poll#:
// Produce on the ring, only if the ring is not full.
br_inp_state[RING_FULL, Full#] ; Check if ring is full and stall
alu[$wdata, --, b, @data]
scratch[put, $wdata, 0, ring, 1], sig_done[scr_put] ; Produce one word on the ring
alu[@data, @data, +, 1] ; Increment next value to be put
// signal next thread when done
//.if (ctx() != 7)
br=ctx[7, thread_7#] ; Special case for thread 7.
signal_next_ctx[wake_thrd] ; Signal the next thread
br[wait#]
//.else
thread_7#:
// In thread 7, signal thread 0 of previous ME, when done.
signal_prev_me[wake_thrd] ; Signal the first thread (in prev me)
//.endif
wait#:
ctx_arb[wake_thrd, scr_put] ; wait for scartch put and prev thread
br[poll#] ; Keep producing on the ring.
// The ring is full. We come here, instead of directly branching
// to poll# to enable setting breakpoint here, so that we know
// that the ring infact gets full. The fact that two MEs produce and
// only one ME consumes make sure we hit this condition soon.
Full#:
// It takes about 1600 cycles to hit ring full condition
nop ; set breakpoint here to see ring gets filled.
br[poll#] ; go back and check if ring is full
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -