Last active
March 7, 2018 22:33
-
-
Save themperek/660ecfc40e7b7b3d32e8283a8aa2558a to your computer and use it in GitHub Desktop.
Data flow simulation model for Monopix chip
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
import random | |
import numba | |
@numba.njit | |
def monopix_sim(SIM_TIME = 1000000, LATENCY = 400, TRIGGER_RATE = 4.0/40, PIXEL_AREA = 36.0*40.0, READ_COL = 4, LOGIC_COLUMNS = 512/4, PIXEL_NO = 4*512, HIT_RATE_CM = 100*(10**6), MEAN_TOT = 15, READ_TRIGER_MEM = 1, TRIG_MEM_SIZE = 96, READ_OUTPUT_FIFO = 1, OUT_FIFO_SIZE = 128): | |
# Average hit rate L4: 0.021/mm2/BC | |
PIXEL_MAX_LATENCY = 63 #6-bit ToT | |
#LATENCY = 400 10us | |
#TRIGGER_RATE = 4.0/40 4MHz | |
#PIXEL_NO = 2*512 #512*512/LOGIC_COLUMNS #number of pixle per readout unit | |
# READ_TRIGER_MEM = 1 #1- 40 / 4 - 160MHz | |
# READ_OUTPUT_FIFO = 1 #40MHz @ 32bit | |
WAIT_FOR_TRIG_MEM = False #wait with in the array or read and losse | |
analog_pileup = 0.0 | |
digital_pileup = 0.0 | |
late_copy = 0.0 | |
total_hits = 0.0 | |
trig_mem_pileup = 0.0 | |
trig_count = 0 | |
pixel_hit_rate_bx = ((float(PIXEL_AREA)/(10000*10000)) * HIT_RATE_CM )/ (40*(10**6)) | |
pix_mem_tot = np.zeros((LOGIC_COLUMNS, PIXEL_NO) ,dtype=np.int32) | |
pix_mem_bx = np.zeros((LOGIC_COLUMNS, PIXEL_NO) ,dtype=np.int32) | |
trig_mem = np.zeros((LOGIC_COLUMNS, TRIG_MEM_SIZE) ,dtype=np.int32) | |
out_mem = np.zeros((OUT_FIFO_SIZE) ,dtype=np.int32) | |
out_mem_hist = np.zeros((OUT_FIFO_SIZE+1) ,dtype=np.uint) | |
trig_mem_hist = np.zeros((TRIG_MEM_SIZE+1) ,dtype=np.uint) | |
trig_mem_fill_mon = np.zeros((LOGIC_COLUMNS, SIM_TIME) ,dtype=np.uint) | |
out_mem_fill_mon = np.zeros((SIM_TIME) ,dtype=np.uint) | |
to_read_mon = np.zeros((SIM_TIME) ,dtype=np.uint) | |
col_ro_delay_hist = np.zeros((PIXEL_MAX_LATENCY+1), dtype=np.uint) | |
read_cnt = 0 | |
read_cnt_out = 0 | |
for bx in range(SIM_TIME): | |
#histogram | |
if len(np.nonzero(out_mem)[0]) != 0: #ignore the counts with fully empty output fifo | |
out_mem_hist[len(np.nonzero(out_mem)[0])] += 1 | |
#OUT_MEM_READ | |
if read_cnt_out >= READ_OUTPUT_FIFO-1: | |
out_mem_occ = np.where(out_mem==True)[0] #occupied output fifo | |
out_mem_fill_mon[bx] += len(out_mem_occ) | |
if len(out_mem_occ): | |
out_mem[out_mem_occ[:1]] = 0 #clear fist occupied output fifo | |
read_cnt_out = 0 | |
else: | |
read_cnt_out += 1 | |
#OUT_MEM_FILL | |
max_trig_latency = np.max(trig_mem) | |
to_read = np.where((trig_mem > LATENCY) & (trig_mem == max_trig_latency)) | |
to_read_len = len(to_read[0]) | |
to_read_mon[bx] = to_read_len | |
for read_trig_mem in range(to_read_len): | |
#print (bx, max_trig_latency, np.where((trig_mem > LATENCY) & (trig_mem == max_trig_latency)), read_trig_mem) | |
if read_trig_mem >= READ_TRIGER_MEM: | |
break | |
empty_out_mem = np.where(out_mem==0)[0] | |
#print (bx, empty_out_mem) | |
if len(empty_out_mem) > 0: | |
trig_mem[to_read[0][read_trig_mem],to_read[1][read_trig_mem]] = 0 #remove triggered data | |
out_mem[empty_out_mem[:1]] = 1 | |
#print out_mem | |
no_trigger = random.random() > TRIGGER_RATE | |
if no_trigger == False: trig_count += 1 | |
for col in range(LOGIC_COLUMNS): | |
#hit counter/tot | |
pix_mem_tot[col][pix_mem_tot[col]>0] -= 1 | |
#bx counter | |
pix_mem_bx[col][pix_mem_bx[col] > 0] += 1 | |
#remove hits after latency if no trigger | |
if no_trigger: | |
trig_mem[col][trig_mem[col] == LATENCY] = 0 | |
trig_mem[col][trig_mem[col] > 0] += 1 | |
late_copy += len(np.where(pix_mem_bx[col] == PIXEL_MAX_LATENCY)[0]) #Late copy | |
#histogram | |
trig_mem_occ = len(np.nonzero(trig_mem[col])[0]) | |
trig_mem_hist[trig_mem_occ] += 1 | |
trig_mem_fill_mon[col][bx] += trig_mem_occ | |
#process eoc | |
if read_cnt >= READ_COL-1: | |
max_bx_latency = np.max(pix_mem_bx[col]) | |
for read_pix in np.where((pix_mem_bx[col] > 0) & (pix_mem_tot[col]==0) & (pix_mem_bx[col]==max_bx_latency) )[0]: #something to read | |
#TODO:Read regions? | |
empty_mems = np.where(trig_mem[col] == 0)[0] | |
if len(empty_mems): | |
mem_loc = empty_mems[0] | |
val = pix_mem_bx[col][read_pix] % (PIXEL_MAX_LATENCY +1) | |
trig_mem[col][mem_loc] = val | |
col_ro_delay_hist[val] += 1 | |
if WAIT_FOR_TRIG_MEM == True: | |
pix_mem_bx[col][read_pix] = 0 #clear this pixel | |
read_cnt = 0 | |
else: | |
trig_mem_pileup += 1 | |
if WAIT_FOR_TRIG_MEM == False: | |
pix_mem_bx[col][read_pix] = 0 #clear this pixel | |
read_cnt = 0 | |
break | |
else: | |
read_cnt += 1 | |
#process hits | |
for pix in np.where(np.random.rand(pix_mem_bx[col].size) < pixel_hit_rate_bx)[0]: | |
total_hits += 1 | |
if pix_mem_tot[col][pix] > 0: | |
analog_pileup += 1 #Analog pielup | |
#pix_mem_tot[col][pix] += MEAN_TOT +1 #paralyzable deadtime | |
else: | |
pix_mem_tot[col][pix] = pix_mem_tot[col][pix] + MEAN_TOT +1 | |
if pix_mem_bx[col][pix] > 0: | |
digital_pileup += 1 #Digital pielup | |
elif pix_mem_bx[col][pix] == 0: #start bx_cnt | |
pix_mem_bx[col][pix] = 1 | |
return analog_pileup, digital_pileup, late_copy, trig_mem_pileup, total_hits, out_mem_hist, trig_mem_hist, trig_count, trig_mem_fill_mon, out_mem_fill_mon, to_read_mon, col_ro_delay_hist | |
if __name__ == "__main__": | |
#print (36.4*36.4*512*2)/(1000*1000) | |
hit_rate = 4.0 | |
attr = {'SIM_TIME': 1000000, | |
'LATENCY': 400, | |
'TRIGGER_RATE': 4.0/40, | |
'PIXEL_AREA': 36.0*40.0, | |
'READ_COL': 4, | |
'LOGIC_COLUMNS': 1, | |
'PIXEL_NO': 2*512, | |
'HIT_RATE_CM': hit_rate*100*(10**6), | |
'MEAN_TOT': 15, | |
'READ_TRIGER_MEM': 1, | |
'TRIG_MEM_SIZE': 96, | |
'READ_OUTPUT_FIFO': 1, | |
'OUT_FIFO_SIZE': 2048 | |
} | |
analog_pileup, digital_pileup, late_copy, trig_mem_pileup, total_hits, out_mem_hist, trig_mem_hist, trig_count, trig_mem_fill_mon, out_mem_fill_mon, to_read_mon, col_ro_delay_hist = monopix_sim(**attr) | |
print 'analog pileup @ %d*100MHz/cm2: '%hit_rate, (100*analog_pileup/total_hits) | |
print 'digital pileup @ %d*100MHz/cm2: '%hit_rate, (100*digital_pileup/total_hits) | |
print 'late copy @ %d*100MHz/cm2: '%hit_rate, (100*late_copy/total_hits) | |
print 'trig mem pileup @ %d*100MHz/cm2: '%hit_rate, (100*trig_mem_pileup/total_hits) | |
print 'total hits @ %d*100MHz/cm2: '%hit_rate, total_hits | |
print 'trig count @ %d*100MHz/cm2: '%hit_rate, trig_count |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment