Browse Source

testing a2onode

pd
openpowerwtf 8 months ago
parent
commit
bc0e3204b7
  1. 193
      dev/sim/coco/A2L2.py
  2. 124
      dev/sim/coco/A2O.py
  3. 21
      dev/sim/coco/OPEnv.py
  4. 331
      dev/sim/coco/tb-node.py
  5. 14
      dev/sim/coco/tb.py

193
dev/sim/coco/A2L2.py

@ -181,11 +181,8 @@ class A2L2Trans(DotMap): @@ -181,11 +181,8 @@ class A2L2Trans(DotMap):
mask = 0xFFFF00FF
else:
mask = 0xFFFFFF00
print(word, mask, dataStart, byte)
word = (word & mask) | (int(self.data[dataStart:dataStart+2], 16) << ((3-byte)*8))
self.sim.mem.write(addr, word)
print(addr,word)
#quit()

elif self.len == 2:
word = self.sim.mem.read(addr)
@ -253,81 +250,81 @@ class A2L2Trans(DotMap): @@ -253,81 +250,81 @@ class A2L2Trans(DotMap):
# ------------------------------------------------------------------------------------------------
# Tasks

transTypes = {
'00': 'IFETCH',
'08': 'LOAD',
'20': 'STORE'
}

async def A2L2Driver(dut, sim):
"""A2L2 node interface"""

transTypes = {
'00': 'IFETCH',
'08': 'LOAD',
'20': 'STORE'
}

ok = True
readPending = []
countReads = 0
mem = {}
sim.msg('A2L2 Driver: started.')

dut.an_ac_flh2l2_gate.value = 0
sim.a2o.root.an_ac_flh2l2_gate.value = 0

while ok and not sim.done:

await RisingEdge(dut.clk_1x)

dut.an_ac_req_ld_pop.value = 0
dut.an_ac_req_st_pop.value = 0
dut.an_ac_req_st_gather.value = 0
sim.a2o.root.an_ac_req_ld_pop.value = 0
sim.a2o.root.an_ac_req_st_pop.value = 0
sim.a2o.root.an_ac_req_st_gather.value = 0

dut.an_ac_reld_data_coming.value = 0
dut.an_ac_reld_data_vld.value = 0
dut.an_ac_reld_ecc_err.value = 0
dut.an_ac_reld_ecc_err_ue.value = 0
dut.an_ac_reld_ditc.value = 0
dut.an_ac_reld_l1_dump.value = 0
dut.an_ac_req_spare_ctrl_a1.value = 0
sim.a2o.root.an_ac_reld_data_coming.value = 0
sim.a2o.root.an_ac_reld_data_vld.value = 0
sim.a2o.root.an_ac_reld_ecc_err.value = 0
sim.a2o.root.an_ac_reld_ecc_err_ue.value = 0
sim.a2o.root.an_ac_reld_ditc.value = 0
sim.a2o.root.an_ac_reld_l1_dump.value = 0
sim.a2o.root.an_ac_req_spare_ctrl_a1.value = 0

if sim.threads == 1:
dut.an_ac_reservation_vld.value = 0
dut.an_ac_stcx_complete.value = 0
dut.an_ac_stcx_pass.value = 0
sim.a2o.root.an_ac_reservation_vld.value = 0
sim.a2o.root.an_ac_stcx_complete.value = 0
sim.a2o.root.an_ac_stcx_pass.value = 0
else:
for i in range(sim.threads):
dut.an_ac_reservation_vld[i].value = 0
dut.an_ac_stcx_complete[i].value = 0
dut.an_ac_stcx_pass[i].value = 0
sim.a2o.root.an_ac_reservation_vld[i].value = 0
sim.a2o.root.an_ac_stcx_complete[i].value = 0
sim.a2o.root.an_ac_stcx_pass[i].value = 0

dut.an_ac_sync_ack.value = 0
dut.an_ac_icbi_ack.value = 0
dut.an_ac_back_inv.value = 0
sim.a2o.root.an_ac_sync_ack.value = 0
sim.a2o.root.an_ac_icbi_ack.value = 0
sim.a2o.root.an_ac_back_inv.value = 0

# bummer IndexError: Slice indexing is not supported
#dut.an_ac_reld_data[0:31].value = 0x48000000
#dut.an_ac_reld_data[32:63].value = 0x48000000
#dut.an_ac_reld_data[64:95].value = 0x48000000
#dut.an_ac_reld_data[96:127].value = 0x48000000
#sim.a2o.root.an_ac_reld_data[0:31].value = 0x48000000
#sim.a2o.root.an_ac_reld_data[32:63].value = 0x48000000
#sim.a2o.root.an_ac_reld_data[64:95].value = 0x48000000
#sim.a2o.root.an_ac_reld_data[96:127].value = 0x48000000
# bummer TypeError: Unsupported type for value assignment: <class 'str'> ('48000000480000004800000048000000')
#dut.an_ac_reld_data.value = '48000000480000004800000048000000'
#sim.a2o.root.an_ac_reld_data.value = '48000000480000004800000048000000'
#v = 0x48000000
# bummer TypeError: Unsupported type for value assignment: <class 'str'> ('01001000000000000000000000000000010010000000000000000000000000000100100000000000000000000000000001001000000000000000000000000000')
#dut.an_ac_reld_data.value = f'{v:0>32b}{v:0>32b}{v:0>32b}{v:0>32b}'
#sim.a2o.root.an_ac_reld_data.value = f'{v:0>32b}{v:0>32b}{v:0>32b}{v:0>32b}'
# otay!
#v1 = cocotb.binary.BinaryValue()
#v1.assign(f'{v:0>32b}{v:0>32b}{v:0>32b}{v:0>32b}')
#dut.an_ac_reld_data.value = v1.value
#sim.a2o.root.an_ac_reld_data.value = v1.value

if dut.ac_an_req.value: # should first check ac_an_req_pwr_token prev cyc
if sim.a2o.root.ac_an_req.value: # should first check ac_an_req_pwr_token prev cyc

tt = hex(dut.ac_an_req_ttype, 2)
tt = hex(sim.a2o.root.ac_an_req_ttype, 2)
transType = transTypes[tt]
tid = hex(dut.ac_an_req_thread)
ra = hex(dut.ac_an_req_ra, 8)
tag = hex(dut.ac_an_req_ld_core_tag, 2)
lenEnc = hex(dut.ac_an_req_ld_xfr_len)
le = 'LE ' if dut.ac_an_req_endian.value else ''
wimg_w = dut.ac_an_req_wimg_w.value
wimg_i = dut.ac_an_req_wimg_i.value
wimg_m = dut.ac_an_req_wimg_m.value
wimg_g = dut.ac_an_req_wimg_g.value
tid = hex(sim.a2o.root.ac_an_req_thread)
ra = hex(sim.a2o.root.ac_an_req_ra, 8)
tag = hex(sim.a2o.root.ac_an_req_ld_core_tag, 2)
lenEnc = hex(sim.a2o.root.ac_an_req_ld_xfr_len)
le = 'LE ' if sim.a2o.root.ac_an_req_endian.value else ''
wimg_w = sim.a2o.root.ac_an_req_wimg_w.value
wimg_i = sim.a2o.root.ac_an_req_wimg_i.value
wimg_m = sim.a2o.root.ac_an_req_wimg_m.value
wimg_g = sim.a2o.root.ac_an_req_wimg_g.value
wimg = 0
if wimg_w:
wimg += 8
@ -349,39 +346,39 @@ async def A2L2Driver(dut, sim): @@ -349,39 +346,39 @@ async def A2L2Driver(dut, sim):
sim.msg(f'T{tid} {transType} {ra} tag={tag} len={trans.len} {le}WIMG:{wimg:X} reld data:{trans.cycD}')
elif transType == 'STORE':
# should verify st_data_pwr_token prev cycle
be = hex(dut.ac_an_st_byte_enbl, 8)
data = hex(dut.ac_an_st_data, 64)
be = hex(sim.a2o.root.ac_an_st_byte_enbl, 8)
data = hex(sim.a2o.root.ac_an_st_data, 64)
trans = A2L2Trans(sim, tid, int(tt, 16), int(tag, 16), int(ra, 16), int(lenEnc, 16), wimg, None, be=be, data=data, le=le)
sim.msg(f'T{tid} {transType} {ra} tag={tag} len={trans.len} be={be} data={data} {le}WIMG:{wimg:X}')
trans.doStore()
dut.an_ac_req_st_pop.value = 1 #wtf can randomize, etc.
sim.a2o.root.an_ac_req_st_pop.value = 1 #wtf can randomize, etc.
#assert False, 'got a store'

# data early indicator (d-3)
dut.an_ac_reld_data_coming.value = 0
sim.a2o.root.an_ac_reld_data_coming.value = 0
for i in range(len(readPending)):
trans = readPending[i]
if trans.cycC == sim.cycle:
dut.an_ac_reld_data_coming.value = 1
sim.a2o.root.an_ac_reld_data_coming.value = 1
if trans.xferNum == 0 and trans.xfers == 4: # 4 beats b2b - need diff scheduling for all modes
trans.cycC += 2

# data valid indicator (d-2)
dut.an_ac_reld_data_vld.value = 0
dut.an_ac_reld_core_tag.value = 0x1F
dut.an_ac_reld_ditc.value = 1
dut.an_ac_reld_qw.value = 3
dut.an_ac_reld_crit_qw.value = 1
sim.a2o.root.an_ac_reld_data_vld.value = 0
sim.a2o.root.an_ac_reld_core_tag.value = 0x1F
sim.a2o.root.an_ac_reld_ditc.value = 1
sim.a2o.root.an_ac_reld_qw.value = 3
sim.a2o.root.an_ac_reld_crit_qw.value = 1

for i in range(len(readPending)):
trans = readPending[i]
if trans.cycV == sim.cycle:
trans.xferNum += 1
dut.an_ac_reld_data_vld.value = 1
dut.an_ac_reld_core_tag.value = trans.tag
dut.an_ac_reld_ditc.value = 1 if trans.ditc else 0
dut.an_ac_reld_qw.value = trans.xferNum - 1
dut.an_ac_reld_crit_qw.value = 1 if trans.xferNum == trans.xferCrit else 0
sim.a2o.root.an_ac_reld_data_vld.value = 1
sim.a2o.root.an_ac_reld_core_tag.value = trans.tag
sim.a2o.root.an_ac_reld_ditc.value = 1 if trans.ditc else 0
sim.a2o.root.an_ac_reld_qw.value = trans.xferNum - 1
sim.a2o.root.an_ac_reld_crit_qw.value = 1 if trans.xferNum == trans.xferCrit else 0
if trans.xferNum < 4 and trans.xfers == 4:
trans.cycV += 1

@ -393,7 +390,7 @@ async def A2L2Driver(dut, sim): @@ -393,7 +390,7 @@ async def A2L2Driver(dut, sim):

v1 = cocotb.binary.BinaryValue()
v1.assign(f'{w0:0>32b}{w1:0>32b}{w2:0>32b}{w3:0>32b}')
dut.an_ac_reld_data.value = v1.value
sim.a2o.root.an_ac_reld_data.value = v1.value

sim.msg(f'RELD tag={trans.tag:02X} {w0:08X}{w1:08X}{w2:08X}{w3:08X} {beatNum}of{trans.xfers}{" crit" if beatNum == trans.xferCrit else ""}')

@ -404,7 +401,7 @@ async def A2L2Driver(dut, sim): @@ -404,7 +401,7 @@ async def A2L2Driver(dut, sim):
readPending = []
else:
readPending = readPending[1:]
dut.an_ac_req_ld_pop.value = 1 #wtf can randomize, etc.
sim.a2o.root.an_ac_req_ld_pop.value = 1 #wtf can randomize, etc.


# A2L2 Checker
@ -423,23 +420,58 @@ async def A2L2Checker(dut, sim): @@ -423,23 +420,58 @@ async def A2L2Checker(dut, sim):
# A2L2 Monitor
# count transactions, etc.
# fail on bad addresses
async def A2L2Monitor(dut, sim):

# TRANS MONITORING NOT COMPLETE!
async def A2L2Monitor(dut, sim, watchTrans=False):
"""A2L2 interface monitor"""

me = 'A2L2 Monitor'
ok = True
start = len(sim.config.a2l2.badAddr) > 0
sim.msg(f'{me}: started.')
reqValid = []
rldValidCyc = []
dataValidCyc = []

while start and ok:

await RisingEdge(dut.clk_1x)

if dut.ac_an_req.value: # should first check ac_an_req_pwr_token prev cyc
if sim.a2o.root.ac_an_req.value: # should first check ac_an_req_pwr_token prev cyc

tt = hex(sim.a2o.root.ac_an_req_ttype, 2)
transType = transTypes[tt]
tid = hex(sim.a2o.root.ac_an_req_thread)
ra = hex(sim.a2o.root.ac_an_req_ra, 8)
tag = hex(sim.a2o.root.ac_an_req_ld_core_tag, 2)
lenEnc = hex(sim.a2o.root.ac_an_req_ld_xfr_len)
le = 'LE ' if sim.a2o.root.ac_an_req_endian.value else ''
wimg_w = sim.a2o.root.ac_an_req_wimg_w.value
wimg_i = sim.a2o.root.ac_an_req_wimg_i.value
wimg_m = sim.a2o.root.ac_an_req_wimg_m.value
wimg_g = sim.a2o.root.ac_an_req_wimg_g.value
wimg = 0
if wimg_w:
wimg += 8
if wimg_i:
wimg += 4
if wimg_m:
wimg += 2
if wimg_g:
wimg += 1

if transType == 'IFETCH' or transType == 'LOAD':
sim.msg(f'T{tid} {transType} {ra} tag={tag} len={lenEnc} {le}WIMG:{wimg:X}')
trans = A2L2Trans(sim, tid, int(tt, 16), int(tag, 16), int(ra, 16), int(lenEnc, 16), wimg, None, le=le)
reqValid.append(trans)
elif transType == 'STORE':
be = hex(sim.a2o.root.ac_an_st_byte_enbl, 8)
data = hex(sim.a2o.root.ac_an_st_data, 64)
trans = A2L2Trans(sim, tid, int(tt, 16), int(tag, 16), int(ra, 16), int(lenEnc, 16), wimg, None, be=be, data=data, le=le)
sim.msg(f'T{tid} {transType} {ra} tag={tag} len={lenEnc} be={be} data={data} {le}WIMG:{wimg:X}')

tt = hex(dut.ac_an_req_ttype, 2)
if tt == '00': #wtf someone should make this a enum/class
ra = dut.ac_an_req_ra.value.integer
ra = sim.a2o.root.ac_an_req_ra.value.integer
for i in range(len(sim.config.a2l2.badAddr)):
blk = sim.config.a2l2.badAddr[i]
if 'I' in blk[2].upper():
@ -447,7 +479,30 @@ async def A2L2Monitor(dut, sim): @@ -447,7 +479,30 @@ async def A2L2Monitor(dut, sim):
blkEnd = int(blk[1], 16)
if ra >= blkStart and ra <= blkEnd:
ok = False
assert False, (f'{me}: Bad IFetch @={ra:08X}') #wtf want this to end back in main code for summary
assert False, (f'{me}: Bad IFetch @={ra:08X}')

# coming (d-3_)
if sim.a2o.root.an_ac_reld_data_coming.value:
rldValidCyc.append(sim.cycle + 1)

# data valid indicator (d-2)
if len(rldValidCyc) > 0 and rldValidCyc[0] == sim.cycle:
if sim.a2o.root.an_ac_reld_data_vld.value:
#wtf append obj to rldValid!
tag = sim.a2o.root.an_ac_reld_core_tag.value
ditc = sim.a2o.root.an_ac_reld_ditc.value
qw = sim.a2o.root.an_ac_reld_qw.value
crit = sim.a2o.root.an_ac_reld_crit_qw.value
rldValidCyc = rldValidCyc[1:]
dataValidCyc.append(sim.cycle + 2)
else:
assert False, (f'{me}: Missing valid cycle')

# data beat (d-0)
if len(dataValidCyc) > 0 and dataValidCyc[0] == sim.cycle:
data = hex(sim.a2o.root.an_ac_reld_data, 32)
sim.msg(f'RELD tag={tag:02X} {data:32X}') #wtf need qw,crit
dataValidCyc = dataValidCyc[1:]

class A2L2:
driver = A2L2Driver

124
dev/sim/coco/A2O.py

@ -15,6 +15,78 @@ from OPEnv import * @@ -15,6 +15,78 @@ from OPEnv import *
# ------------------------------------------------------------------------------------------------
# Tasks

async def A2OConfig(dut, sim):
"""Configure A2O. """

# A2L2 load/store credits
creditsLd = sim.a2o.root.lq0.lsq.arb.load_cred_cnt_d # 8 max
creditsLdMax = sim.a2o.root.lq0.lsq.arb.ld_cred_max # hdw check
creditsSt = sim.a2o.root.lq0.lsq.arb.store_cred_cnt_d # 32 max
creditsStMax = sim.a2o.root.lq0.lsq.arb.st_cred_max # hdw check
creditsLdStSingle = sim.a2o.root.lq0.lsq.arb.spr_xucr0_cred_d # 1 total credit
#wtf this affects A2L2 - default=1
# sim.a2o.root.lq0.lsq.arb.spr_lsucr0_b2b_q # 0=crit first, every other 1=crit first, b2b **the a2l2 spec does not say crit must be first**
lsucr0_d = sim.a2o.root.lq0.ctl.spr.lq_spr_cspr.lsucr0_d
lsucr0_q = sim.a2o.root.lq0.ctl.spr.lq_spr_cspr.lsucr0_q
cpcr2_d = sim.a2o.root.iuq0.iuq_ifetch0.iuq_spr0.cpcr2_d
cpcr2_q = sim.a2o.root.iuq0.iuq_ifetch0.iuq_spr0.cpcr2_l2
cpcr2_act = sim.a2o.root.iuq0.iuq_ifetch0.iuq_spr0.cpcr2_wren
cpcr4_d = sim.a2o.root.iuq0.iuq_ifetch0.iuq_spr0.cpcr4_d
cpcr4_q = sim.a2o.root.iuq0.iuq_ifetch0.iuq_spr0.cpcr4_l2
cpcr4_act = sim.a2o.root.iuq0.iuq_ifetch0.iuq_spr0.cpcr4_wren

await RisingEdge(dut.clk_1x)

if sim.a2o.config.creditsLd is not None:
creditsLd.value = Force(sim.a2o.config.creditsLd)
creditsLdMax.value = Force(sim.a2o.config.creditsLd)
sim.msg(f'A2O: load credits changed from {creditsLd.value.integer} to {sim.a2o.config.creditsLd}.')
await RisingEdge(dut.clk_1x)
creditsLd.value = Release()

if sim.a2o.config.creditsSt is not None:
creditsSt.value = Force(sim.a2o.config.creditsSt)
creditsStMax.value = Force(sim.a2o.config.creditsSt)
sim.msg(f'A2O: store credits changed from {creditsSt.value.integer} to {sim.a2o.config.creditsSt}.')
await RisingEdge(dut.clk_1x)
creditsSt.value = Release()

if sim.a2o.config.creditsLdStSingle is not None:
v = 1 if sim.a2o.config.creditsLdStSingle else 0
creditsLdStSingle.value = Force(v)
sim.msg(f'A2O: only one load OR store allowed when credits=1/1.')
await RisingEdge(dut.clk_1x)
#creditsLdStSingle.value = Release() # to release have to set _q with xucr0_d[51] and xucr0_act

#wtf make a function - needs mask,thread
if sim.a2o.config.lsDataForward is not None:
v = 1 if sim.a2o.config.lsDataForward else 0
sim.msg(f'A2O: LSUCR0 = {hex(lsucr0_q.value), 8}')
sim.msg(f'A2O: Setting LSUCR0[DFWD] = {v}.')
v = v << 2
v = (lsucr0_q.value.integer & ~0x4) | v
lsucr0_d.value = Force(v)
await RisingEdge(dut.clk_1x)
lsucr0_d.value = Release()
sim.msg(f'A2O: LSUCR0 = {hex(lsucr0_q.value), 8}')

if sim.a2o.config.cpcr4_sq_cnt is not None:
v = sim.a2o.config.cpcr4_sq_cnt
sim.msg(f'A2O: CPCR4 = {hex(cpcr4_q[0], 8)}')
sim.msg(f'A2O: Setting CPCR4[SQ_CNT] = {v}.')
v = v << 0
v = (cpcr4_q[0].value.integer & ~0x1F) | v
await RisingEdge(dut.clk_1x) # need cuz of act?
cpcr4_d[0].value = Force(v)
cpcr4_act.value = Force(1)
await RisingEdge(dut.clk_1x)
await RisingEdge(dut.clk_1x) # need cuz of act?
cpcr4_d[0].value = Release()
cpcr4_act.value = Release()
sim.msg(f'A2O: CPCR4 = {hex(cpcr4_q[0], 8)}')

await RisingEdge(dut.clk_1x)

async def A2ODriver(dut, sim):
"""A2O Core Driver"""

@ -44,8 +116,8 @@ async def A2OChecker(dut, sim): @@ -44,8 +116,8 @@ async def A2OChecker(dut, sim):
sim.msg(f'{me}: started.')

# errors
creditsLdErr = dut.c0.lq0.lsq.arb.ld_cred_err_q
creditsStErr = dut.c0.lq0.lsq.arb.st_cred_err_q
creditsLdErr = sim.a2o.root.lq0.lsq.arb.ld_cred_err_q
creditsStErr = sim.a2o.root.lq0.lsq.arb.st_cred_err_q
errors = [
{'name': 'Load Credits', 'sig': creditsLdErr},
{'name': 'Store Credits', 'sig': creditsStErr},
@ -72,68 +144,68 @@ async def A2OMonitor(dut, sim): @@ -72,68 +144,68 @@ async def A2OMonitor(dut, sim):
sim.msg(f'{me}: started.')

# completions
iu0Comp = dut.c0.iu_lq_i0_completed
iu0CompIFAR = dut.c0.iuq0.iuq_cpl_top0.iuq_cpl0.cp2_i0_ifar
iu1Comp = dut.c0.iu_lq_i1_completed
iu1CompIFAR = dut.c0.iuq0.iuq_cpl_top0.iuq_cpl0.cp2_i1_ifar
iuCompFlushIFAR = dut.c0.cp_t0_flush_ifar
cp3NIA = dut.c0.iuq0.iuq_cpl_top0.iuq_cpl0.iuq_cpl_ctrl.cp3_nia_q # nia after last cycle's completions
iu0Comp = sim.a2o.root.iu_lq_i0_completed
iu0CompIFAR = sim.a2o.root.iuq0.iuq_cpl_top0.iuq_cpl0.cp2_i0_ifar
iu1Comp = sim.a2o.root.iu_lq_i1_completed
iu1CompIFAR = sim.a2o.root.iuq0.iuq_cpl_top0.iuq_cpl0.cp2_i1_ifar
iuCompFlushIFAR = sim.a2o.root.cp_t0_flush_ifar
cp3NIA = sim.a2o.root.iuq0.iuq_cpl_top0.iuq_cpl0.iuq_cpl_ctrl.cp3_nia_q # nia after last cycle's completions

# GPR ppol and arch map
gprCompMap = []
lastGprCompMap = []
#wtf check what 33:36 are!
for i in range(36):
gprCompMap.append(dut.c0.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.gpr_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout)
gprCompMap.append(sim.a2o.root.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.gpr_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout)
lastGprCompMap.append(i)

gpr = []
for i in range(144):
gpr.append(dut.c0.xu0.gpr.gpr0.loc[i].dat)
gpr.append(sim.a2o.root.xu0.gpr.gpr0.loc[i].dat)

# CR fields pool and arch map
crCompMap = []
lastCrCompMap = []
for i in range(8):
crCompMap.append(dut.c0.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.cr_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout)
crCompMap.append(sim.a2o.root.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.cr_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout)
lastCrCompMap.append(i)

cr = []
for i in range(24):
cr.append(dut.c0.xu0.cr.entry[i].reg_latch.dout)
cr.append(sim.a2o.root.xu0.cr.entry[i].reg_latch.dout)

# XER pool and arch map
xerCompMap = []
lastXerCompMap = []
for i in range(1):
xerCompMap.append(dut.c0.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.xer_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout)
xerCompMap.append(sim.a2o.root.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.xer_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout)
lastXerCompMap.append(i)

xer = []
for i in range(12):
xer.append(dut.c0.xu0.xer.entry[i].reg_latch.dout)
xer.append(sim.a2o.root.xu0.xer.entry[i].reg_latch.dout)

# CTR pool and arch map
ctrCompMap = []
lastCtrCompMap = []
for i in range(1):
ctrCompMap.append(dut.c0.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.ctr_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout)
ctrCompMap.append(sim.a2o.root.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.ctr_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout)
lastCtrCompMap.append(i)

ctr = []
for i in range(8):
ctr.append(dut.c0.xu0.ctr.entry[i].reg_latch.dout)
ctr.append(sim.a2o.root.xu0.ctr.entry[i].reg_latch.dout)

# LR pool and arch map
lrCompMap = []
lastLrCompMap = []
for i in range(1):
lrCompMap.append(dut.c0.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.lr_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout)
lrCompMap.append(sim.a2o.root.iuq0.iuq_slice_top0.slice0.rn_top0.fx_rn0.lr_rn_map.xhdl3.comp_map0[i].comp_map_latch.dout)
lastLrCompMap.append(i)

lr = []
for i in range(8):
lr.append(dut.c0.xu0.lr.entry[i].reg_latch.dout)
lr.append(sim.a2o.root.xu0.lr.entry[i].reg_latch.dout)

lastComp = ''
lastCompCount = 0
@ -231,6 +303,7 @@ async def A2OMonitor(dut, sim): @@ -231,6 +303,7 @@ async def A2OMonitor(dut, sim):
# Classes

class A2O:
config = A2OConfig
driver = A2ODriver
checker = A2OChecker
monitor = A2OMonitor
@ -239,10 +312,21 @@ class A2O: @@ -239,10 +312,21 @@ class A2O:
pass

class A2OCore(DotMap):
def __init__(self, sim):
def __init__(self, sim, root=None):
super().__init__()
self.sim = sim
if root is None:
self.root = sim.dut.c0
else:
self.root = root
self.traceFacUpdates = False
self.stopOnLoop = 0
self.iarPass = None
self.iarFail = None
self.iarFail = None
self.config = DotMap({
'creditsLd': None,
'creditsSt': None,
'creditsLdStSingle': None,
'lsDataForward' : None,
'cpcr4_sq_cnt' : None
})

21
dev/sim/coco/OPEnv.py

@ -127,7 +127,7 @@ class Memory(DotMap): @@ -127,7 +127,7 @@ class Memory(DotMap):
return self.default

# word-aligned byte address + data
def write(self, addr, data):
def write(self, addr, data, be=None):
try:
addr = addr + 0
except:
@ -136,6 +136,23 @@ class Memory(DotMap): @@ -136,6 +136,23 @@ class Memory(DotMap):
data = data + 0
except:
data = int(data, 16)

if be is not None:
try:
be = be + 0
except:
be = int(be, 2)
be = f'{be:04b}'
if be == '0000':
return

mask = 0
for i in range(4):
mask = mask << 8
if be[i]:
mask += 0xFF
data = (self.read(addr) & ~mask) | (data & mask)

if self.logStores:
if addr not in self.data:
self.sim.msg(f'Mem Update: @{addr:08X} XXXXXXXX->{data:08X}')
@ -164,6 +181,8 @@ class Memory(DotMap): @@ -164,6 +181,8 @@ class Memory(DotMap):
rowTransDict = {}
for i in range(32):
rowTransDict[i] = '.'
for i in range(127, 256):
rowTransDict[i] = '.'

# first line may be unaligned by row
zeros = True

331
dev/sim/coco/tb-node.py

@ -1,331 +0,0 @@ @@ -1,331 +0,0 @@
# a2o test tb
# uses a2owb with sim mem interface

import cocotb
from cocotb.clock import Clock
from cocotb.triggers import Timer
from cocotb.triggers import FallingEdge
from cocotb.handle import Force
from cocotb.handle import Release

import itertools
from dotmap import DotMap

from OPEnv import *
from A2O import *
from A2L2 import *

# ------------------------------------------------------------------------------------------------
# Tasks

# get rid of z on anything that will be sampled here
# is there a func to get all inputs?
async def init(dut, sim):
"""Initialize inputs. """

dut.nclk.value = 0
dut.scan_in.value = 0
dut.an_ac_scan_type_dc.value = 0x0
dut.an_ac_chipid_dc.value = 0x0
dut.an_ac_coreid.value = 0x0
dut.an_ac_scom_sat_id.value = 0x0

dut.an_ac_lbist_ary_wrt_thru_dc.value = 0
dut.an_ac_gsd_test_enable_dc.value = 0
dut.an_ac_gsd_test_acmode_dc.value = 0
dut.an_ac_ccflush_dc.value = 0
dut.an_ac_ccenable_dc.value = 0
dut.an_ac_lbist_en_dc.value = 0
dut.an_ac_lbist_ip_dc.value = 0
dut.an_ac_lbist_ac_mode_dc.value = 0
dut.an_ac_scan_diag_dc.value = 0
dut.an_ac_scan_dis_dc_b.value = 0

dut.an_ac_rtim_sl_thold_8.value = 0
dut.an_ac_func_sl_thold_8.value = 0
dut.an_ac_func_nsl_thold_8.value = 0
dut.an_ac_ary_nsl_thold_8.value = 0
dut.an_ac_sg_8.value = 0
dut.an_ac_fce_8.value = 0
dut.an_ac_abst_scan_in.value = 0

dut.an_ac_checkstop.value = 0

dut.an_ac_reset_1_complete.value = 0
dut.an_ac_reset_2_complete.value = 0
dut.an_ac_reset_3_complete.value = 0
dut.an_ac_reset_wd_complete.value = 0

dut.an_ac_pm_fetch_halt.value = 0
dut.an_ac_debug_stop.value = 0

dut.an_ac_tb_update_enable.value = 1
dut.an_ac_tb_update_pulse.value = 0 # tb clock if xucr0[tcs]=1 (must be <1/2 proc clk; tb pulse is 2x this clock)

# why is coco turning [0] into non-vector??? or is that gpi/vpi/icarus/???
if sim.threads == 1:
dut.an_ac_pm_thread_stop.value = 0x1
dut.an_ac_external_mchk.value = 0
dut.an_ac_sleep_en.value = 0
dut.an_ac_ext_interrupt.value = 0
dut.an_ac_crit_interrupt.value = 0
dut.an_ac_perf_interrupt.value = 0
dut.an_ac_hang_pulse.value = 0
dut.an_ac_uncond_dbg_event.value = 0
else:
for i in range(sim.threads):
dut.an_ac_pm_thread_stop[i].value = 0x1
dut.an_ac_external_mchk[i].value = 0
dut.an_ac_sleep_en[i].value = 0
dut.an_ac_ext_interrupt[i].value = 0
dut.an_ac_crit_interrupt[i].value = 0
dut.an_ac_perf_interrupt[i].value = 0
dut.an_ac_hang_pulse[i].value = 0
dut.an_ac_uncond_dbg_event[i].value = 0

await Timer(9, units='ns')

async def config(dut, sim):
"""Configure core, etc. """

#wtf make A2 module to do core-specific stuff
# A2L2 load/store credits
creditsLd = dut.c0.lq0.lsq.arb.load_cred_cnt_d # 8 max
creditsLdMax = dut.c0.lq0.lsq.arb.ld_cred_max # hdw check
creditsSt = dut.c0.lq0.lsq.arb.store_cred_cnt_d # 32 max
creditsStMax = dut.c0.lq0.lsq.arb.st_cred_max # hdw check
creditsLdStSingle = dut.c0.lq0.lsq.arb.spr_xucr0_cred_d # 1 total credit
#wtf this affects A2L2 - default=1
# dut.c0.lq0.lsq.arb.spr_lsucr0_b2b_q # 0=crit first, every other 1=crit first, b2b **the a2l2 spec does not say crit must be first**
lsucr0_d = dut.c0.lq0.ctl.spr.lq_spr_cspr.lsucr0_d
lsucr0_q = dut.c0.lq0.ctl.spr.lq_spr_cspr.lsucr0_q
cpcr2_d = dut.c0.iuq0.iuq_ifetch0.iuq_spr0.cpcr2_d
cpcr2_q = dut.c0.iuq0.iuq_ifetch0.iuq_spr0.cpcr2_l2
cpcr2_act = dut.c0.iuq0.iuq_ifetch0.iuq_spr0.cpcr2_wren
cpcr4_d = dut.c0.iuq0.iuq_ifetch0.iuq_spr0.cpcr4_d
cpcr4_q = dut.c0.iuq0.iuq_ifetch0.iuq_spr0.cpcr4_l2
cpcr4_act = dut.c0.iuq0.iuq_ifetch0.iuq_spr0.cpcr4_wren

await RisingEdge(dut.clk_1x)

if sim.config.core.creditsLd is not None:
creditsLd.value = Force(sim.config.core.creditsLd)
creditsLdMax.value = Force(sim.config.core.creditsLd)
sim.msg(f'A2L2: load credits changed from {creditsLd.value.integer} to {sim.config.core.creditsLd}.')
await RisingEdge(dut.clk_1x)
creditsLd.value = Release()

if sim.config.core.creditsSt is not None:
creditsSt.value = Force(sim.config.core.creditsSt)
creditsStMax.value = Force(sim.config.core.creditsSt)
sim.msg(f'A2L2: store credits changed from {creditsSt.value.integer} to {sim.config.core.creditsSt}.')
await RisingEdge(dut.clk_1x)
creditsSt.value = Release()

if sim.config.core.creditsLdStSingle is not None:
v = 1 if sim.config.core.creditsLdStSingle else 0
creditsLdStSingle.value = Force(v)
sim.msg(f'A2L2: only one load OR store allowed when credits=1/1.')
await RisingEdge(dut.clk_1x)
creditsLdStSingle.value = Release()

#wtf make a function - needs mask,thread
if sim.config.core.lsDataForward is not None:
v = 1 if sim.config.core.lsDataForward else 0
sim.msg(f'LSUCR0 = {hex(lsucr0_q.value), 8}')
sim.msg(f'Setting LSUCR0[DFWD] = {v}.')
v = v << 2
v = (lsucr0_q.value.integer & ~0x4) | v
lsucr0_d.value = Force(v)
await RisingEdge(dut.clk_1x)
lsucr0_d.value = Release()
sim.msg(f'LSUCR0 = {hex(lsucr0_q.value), 8}')

if sim.config.core.cpcr4_sq_cnt is not None:
v = sim.config.core.cpcr4_sq_cnt
sim.msg(f'CPCR4 = {hex(cpcr4_q[0], 8)}')
sim.msg(f'Setting CPCR4[SQ_CNT] = {v}.')
v = v << 0
v = (cpcr4_q[0].value.integer & ~0x1F) | v
await RisingEdge(dut.clk_1x) # need cuz of act?
cpcr4_d[0].value = Force(v)
cpcr4_act.value = Force(1)
await RisingEdge(dut.clk_1x)
await RisingEdge(dut.clk_1x) # need cuz of act?
cpcr4_d[0].value = Release()
cpcr4_act.value = Release()
sim.msg(f'CPCR4 = {hex(cpcr4_q[0], 8)}')

await RisingEdge(dut.clk_1x)

# trilib/tri.vh:`define NCLK_WIDTH 6 // 0 1xClk, 1 Reset, 2 2xClk, 3 4xClk, 4 Even .5xClk, 5 Odd .5xClk
async def genReset(dut, sim):
"""Generate reset. """

first = True
done = False

while not done:
await RisingEdge(dut.clk_1x)
if sim.cycle < sim.resetCycle:
if first:
dut._log.info(f'[{sim.cycle:08d}] Resetting...')
first = False
dut.nclk[1].value = 1
elif not done:
dut._log.info(f'[{sim.cycle:08d}] Releasing reset.')
dut.nclk[1].value = 0
done = True
sim.resetDone = True

async def genClocks(dut, sim):
"""Generate 1x, 2x, 4x clock pulses, depending on parms. """

if sim.clk2x and sim.clk4x:
sim.clk1x = Clock(dut.nclk[0], 8, 'ns')
await cocotb.start(sim.clk1x.start())
sim.clk2x = Clock(dut.nclk[2], 4, 'ns')
await cocotb.start(sim.clk2x.start())
sim.clk4x = Clock(dut.nclk[3], 2, 'ns')
await cocotb.start(sim.clk4x.start())
elif sim.clk2x:
sim.clk1x = Clock(dut.nclk[0], 8, 'ns')
await cocotb.start(sim.clk1x.start())
sim.clk2x = Clock(dut.nclk[2], 4, 'ns')
await cocotb.start(sim.clk2x.start())
else:
sim.clk1x = Clock(dut.nclk[0], 8, 'ns')
await cocotb.start(sim.clk1x.start())


for cycle in range(sim.maxCycles):

sim.cycle = cycle

if cycle % sim.hbCycles == 0:
dut._log.info(f'[{cycle:08d}] ...tick...')

await RisingEdge(dut.clk_1x)

dut._log.info(f'[{sim.cycle:08d}] Reached max cycle. Clocks stopped.')
sim.ok = False
sim.fail = 'Max cycle reached.'

# ------------------------------------------------------------------------------------------------
# Interfaces

# SCOM
async def scom(dut, sim):
"""scom interface"""

dut.an_ac_scom_dch.value = 0
dut.an_ac_scom_cch.value = 0


# ------------------------------------------------------------------------------------------------
# Do something

@cocotb.test()
async def tb(dut):
"""A Vulgar Display of OpenPower"""

sim = Sim(dut)
sim.mem = Memory(sim)
sim.maxCycles = 9000
# original fpga design needed 4 cred, no fwd (set in logic currently)
#sim.config.core.creditsSt = 32
#sim.config.core.lsDataForward = 0 # disable=1
#sim.config.core.cpcr4_sq_cnt = 0 # default=6

'''
# rom
sim.memFiles = ['../mem/boot.bin.hex'] #wtf cmdline parm

for i in range(len(sim.memFiles)): #wtf el should be object with name, format, etc.
sim.mem.loadFile(sim.memFiles[i])
'''

'''
# rom+test; should end at 700
sim.memFiles = [
{
'addr': 0x00000000,
'file' : '../mem/test1/rom.init'
},
{
'addr': 0x10000000,
'file' : '../mem/test1/test.init'
}
]
'''
'''
# rom+bios; should end at 7FC
sim.memFiles = [
{
'addr': 0x00000000,
'file' : '../mem/test2/rom.init'
}
]
'''


# rom+bios+arcitst
sim.memFiles = [
{
'addr': 0x00000000,
'file' : '../mem/test3/rom.init'
}
]

for i in range(len(sim.memFiles)): #wtf el should be object with name, format, etc.
sim.mem.loadFile(sim.memFiles[i]['file'], addr=sim.memFiles[i]['addr'])

if sim.resetAddr is not None and sim.mem.read(sim.resetAddr) == sim.mem.default:
sim.mem.write(sim.resetAddr, sim.resetOp)
sim.msg(f'Set reset fetch @{sim.resetAddr:08X} to {sim.resetOp:08X}.')

# init stuff
await init(dut, sim)

# start clocks,reset
await cocotb.start(genClocks(dut, sim))
await cocotb.start(genReset(dut, sim))

# start interfaces
await cocotb.start(scom(dut, sim))

sim.a2o = A2OCore(sim)
sim.a2o.traceFacUpdates = True
await cocotb.start(A2O.driver(dut, sim))
await cocotb.start(A2O.checker(dut, sim))
await cocotb.start(A2O.monitor(dut, sim))

await cocotb.start(A2L2.driver(dut, sim))
await cocotb.start(A2L2.checker(dut, sim))
await cocotb.start(A2L2.monitor(dut, sim))

await Timer((sim.resetCycle + 5)*8, units='ns')
if dut.nclk[1].value != 0:
sim.ok = False
sim.fail = 'Reset active too long!'

# config stuff
await config(dut, sim)

# monitor stuff
#await cocotb.start(coreMonitor(dut, sim))

# release thread(s)
dut.an_ac_pm_thread_stop.value = 0
await RisingEdge(dut.clk_1x)
dut._log.info(f'[{sim.cycle:08d}] Threads enabled.')

# should await sim.done
await Timer((sim.maxCycles+100)*8, units='ns')

if sim.ok:
dut._log.info(f'[{sim.cycle:08d}] You has opulence.')
else:
dut._log.info(f'[{sim.cycle:08d}] You are worthless and weak!')
dut._log.info(f'[{sim.cycle:08d}] {sim.fail}')
assert False

14
dev/sim/coco/tb.py

@ -231,7 +231,8 @@ async def tb(dut): @@ -231,7 +231,8 @@ async def tb(dut):

sim = Sim(dut)
sim.mem = Memory(sim)
sim.maxCycles = 20000
#sim.maxCycles = 2000000
sim.maxCycles = 300
# original fpga design needed 4 cred, no fwd (set in logic currently)
#sim.config.core.creditsSt = 32
#sim.config.core.lsDataForward = 0 # disable=1
@ -268,7 +269,7 @@ async def tb(dut): @@ -268,7 +269,7 @@ async def tb(dut):
]
'''


'''
# rom+bios+arcitst
sim.memFiles = [
{
@ -276,6 +277,15 @@ async def tb(dut): @@ -276,6 +277,15 @@ async def tb(dut):
'file' : '../mem/test3/rom.init'
}
]
'''

# rom+bios+dhrystone
sim.memFiles = [
{
'addr': 0x00000000,
'file' : '../mem/dhrystone/rom.init'
}
]

for i in range(len(sim.memFiles)): #wtf el should be object with name, format, etc.
sim.mem.loadFile(sim.memFiles[i]['file'], addr=sim.memFiles[i]['addr'])

Loading…
Cancel
Save