pd
openpowerwtf 2 years ago
parent 4177984080
commit 3893e0253d

@ -1,5 +1,20 @@
# A2O

# Current Status

* for now, /rel is the original and /dev has updates:

* compiles with verilator, iverilog, yosys
* runs original simple boot code up to test invocation with cocotb (A2L2 interface partially implemented in Python)

## To Do

* continue with cocotb testing
* add A2Node bridge to WB, and Litex wrapper
* experiment with parameters to create smaller version(s) for dOpenLane

# Original Release

## The Project
This is the release of the A2O POWER processor core RTL and associated FPGA implementation (using ADM-PCIE-9V3 FPGA).


1
dev/.gitignore vendored

@ -0,0 +1 @@
*.pdf

@ -0,0 +1,32 @@
# Testing RTL with new environments

##

* RTL

* updated source to remove a bunch of Verilator warnings
* updated source for compatibility with Icaraus -g2012
* changed the GPR/FPR macro to remove need for clk4x on FPGA; was ugly and not working with either simulator

* Verilator

* can IFETCH some ops in ST and SMT2 mode
* can't get cocotb to build with Verilator (very long compile times)

* Icarus (w/cocotb)

* executing boot code until test call with python A2L2 interface

* Yosys

* finishes compile


## Next To Do

* create A2L2 cpp model that can be used by Verilator and cocotb (Cython wrapper)
* create simple A2L2-WB RTL for easily connecting to Litex, etc.
* create Litex core wrapper
* OpenLane experiments with blackbox arrays and yosys/abc/sta
* create FPGA version of GPR/FPR (4R4W) using (4)4R1W banks and valid table
* parse vcd/fst and serve browser code for custom trace screens (handle spec/arch mapped facilities, arrays, etc.)

11
dev/sim/.gitignore vendored

@ -0,0 +1,11 @@
# verilator
**/obj_dir*/
# cooc/icarus
coco_icarus
**/sim_build*/
# gtkwave
*.vcd
*.fst
# python
**/__pycache__/
*.py[cod]

@ -0,0 +1,413 @@
# A2L2 Interface

import cocotb
from cocotb.triggers import Timer, RisingEdge
from cocotb.binary import BinaryValue
from cocotb.handle import Force
from cocotb.handle import Release

from dotmap import DotMap
import itertools

# ------------------------------------------------------------------------------------------------
# Classes

'''
Data return timings from spec:

* Reload Data Coming
Indicates that reload data is coming in three cycles. This signal is required for L2 designs that return data in consecutive cycles, but can be
tied to a logic 0 for designs that return data in every other cycle. For L2 designs that return data in consecutive cycles, this signal should be
asserted three cycles ahead of the first of two paired data beats. If more than two data beats will be presented consecutively, this signal should be
asserted once for the first set of two (paired) data beats and once for the second set of two (paired) data beats. Each assertion
should be three cycles ahead of the first beat of the paired set of data beats. This signal allows the A2 core to insert an issue bubble for the second
reload data beat to avoid flushing the processor pipe. This signal is not required to be asserted as described above for DITC return data.
For non-cacheable (I=1) reloads of one or two beats, this signal should be asserted three cycles ahead of the first (and possibly only) data beat transfer.

* Reload Data Valid
Indicates that reload data is coming in two cycles. This signal qualifies the other reload interface signals sent in this cycle: reld_ditc, reld_core_tag, reld_crit_qw, and reld_qw.
If reld_data_vld is not active, then the qualified signals should be ignored.

* Reload Direct Inter-Thread Communication
Indicates that the reload data is associated with a DITC transfer instead of a standard load-ttype reload. This signal is qualified by reld_data_vld and determines the
interpretation of the reld_core_tag bus. DITC reload data transfers are always 64-Byte transfers that follow the same consecutive cycle or every-other-cycle behavior
as standard load-ttype reloads for the attached L2.

**i believe this means ditc can use either 1of2/2of2 or 1of2/-/-/2of2 pattern, but never requires data_coming (probs because pipe considerations not important for ditc)**

======
Cycles:

* d-3 (reld_data_coming)
Loads:
1. I=1: assert 3 cycs ahead of first transfer (two transfers only if 32B allowed)
2. I=0 data every other cycle: not asserted
3. I=0 data consecutive cycles: assert 3 cycs ahead of the 1of2 paired beats; if more than 2 beats are consecutive, assert 3 cycs ahead of each paired beat
DITC:
1. assertion not required **(or used by core?)**

* d-2 (reld_data_vld and qualified signals)
Loads:
1. assert 2 cycs ahead of data
DITC:
1. assert 2 cycs ahead of data and also assert reld_ditc

Cacheable Return Modes:
1. no back-to-back: coming=0
2. all back-to-back: coming=1/0/1
3. interleaved back-to-back: coming=1/0/0/0/1
4. mixed: legal cases for subxfers (?) **i think the 'mixed' aren't valid - xucr0[52] selects b2b mode**
* 1 1 1 1 (no b2b)
* 1 2 1 (mixed)
* 1 1 2 (mixed)
* 2 1 1 (mixed)
* 2 2 (full b2b)
5. between subxfers a delay or other transaction can be inserted

?? xucr0[52] definition selects b2b but also says crit first; i guess this means crit first is allowed, but not required?? a2l2 spec says it is not required to send crit first

'''
class A2L2Trans(DotMap):
'''A2L2 Transaction'''
nextID = itertools.count()
def __init__(self, sim, tid, tt, tag=None, addr=None, length=0, wimg=0, cycD=None, be=None, data=None):
super().__init__()
self.sim = sim
self.id = next(A2L2Trans.nextID)
self.tid = tid
self.tt = tt
self.tag = tag
self.addr = addr
self.len = length
self.wimg = wimg
self.xfers = 1
self.xferNum = 0
self.xferCrit = 1
self.beatNum = 1
if cycD is not None:
self.cycC = cycD - 3
self.cycV = cycD - 2
self.cycD = cycD
self.be = f'{int(be, 16):032b}' if be is not None else None
self.data = data
self.done = False

self.ieq1 = wimg & 0x4 == 0x4

self.load = tt == 0x00 or tt == 0x08 or tt == 0x22 or tt == 0x09 or tt == 0x0B # IF, LD, DITC, LARX, LARX_HINT
self.store = tt == 0x20 or tt == 0x29 # ST, STCX

if self.load:
self.addr = self.addr & 0xFFFFFFF0
elif self.store:
self.addr = self.addr & 0xFFFFFFE0
if self.be == None or self.data == None:
raise Exception('A2L2Trans: store must have BE and data')
else:
self.len = 0
self.storeStart = None
for i in range(len(self.be)):
if self.be[i] == '1':
if self.storeStart is None:
self.storeStart = i
self.len += 1
elif self.storeStart is not None:
break
else:
raise Exception(f'A2L2Trans: unsupported ttype={tt}')

self.ditc = tt == 0x22

if self.ieq1:
if tt == 0x00 or tt == 0x08: # IF, LD
if len == 7:
self.xfers = 2
elif tt == 0x22: # DITC
self.xfers = 4
else:
if self.load:
self.xfers = 4
self.xferCrit = ((self.addr & 0x30) >> 4) + 1
self.addr = self.addr & 0xFFFFFFC0

def readXfer(self):
# read() returns this qw crit-first if cacheable!
w0 = self.sim.mem.read(self.addr)
w1 = self.sim.mem.read(self.addr+4)
w2 = self.sim.mem.read(self.addr+8)
w3 = self.sim.mem.read(self.addr+12)
beatNum = self.beatNum
if self.beatNum < self.xfers:
self.beatNum += 1
self.cycD += 1
self.addr += 16 #wtf this is wrong - going to need to schedule the pattern when the trans is created!!!!!!!!!!!!!!!!!!!!!!!!
return w0,w1,w2,w3,beatNum

def doStore(self):
addr = ((self.addr + self.storeStart) >> 2) << 2
dataStart = self.storeStart*2
if self.len == 1:
word = self.sim.mem.read(addr)
byte = self.addr & 0x3
if byte == 0:
mask = 0xFFFFFF00
elif byte == 1:
mask = 0xFFFF00FF
elif byte == 2:
mask = 0xFF00FFFF
else:
mask = 0x00FFFFFF
word = (word & mask) | (int(self.data[dataStart:dataStart+2], 16) << (byte*2))
self.sim.mem.write(addr, word)

elif self.len == 2:
word = self.sim.mem.read(addr)
hw = (self.addr & 0x2) >> 1
if hw == 0:
mask = 0xFFFF0000
else:
mask = 0x0000FFFF
word = (word & mask) | (int(self.data[dataStart:dataStart+4], 16) << (hw*4))
self.sim.mem.write(addr, word)

elif self.len == 4:
self.sim.mem.write(addr, int(self.data[dataStart:dataStart+8], 16))

elif self.len == 8:
self.sim.mem.write(addr, int(self.data[dataStart:dataStart+16], 16))
self.sim.mem.write(addr+4, int(self.data[dataStart+16:dataStart+32], 16))

elif self.len == 16:
self.sim.mem.write(addr, int(self.data[0:8], 16))
self.sim.mem.write(addr+4, int(self.data[8:16], 16))
self.sim.mem.write(addr+8, int(self.data[16:24], 16))
self.sim.mem.write(addr+12, int(self.data[24:32], 16))

elif self.len == 32:
self.sim.mem.write(addr, int(self.data[0:8], 16))
self.sim.mem.write(addr+4, int(self.data[8:16], 16))
self.sim.mem.write(addr+8, int(self.data[16:24], 16))
self.sim.mem.write(addr+12, int(self.data[24:32], 16))
self.sim.mem.write(addr+16, int(self.data[32:40], 16))
self.sim.mem.write(addr+20, int(self.data[40:48], 16))
self.sim.mem.write(addr+24, int(self.data[48:56], 16))
self.sim.mem.write(addr+28, int(self.data[56:64], 16))

else:
raise Exception(f'A2L2Trans: unsupported store len={self.len}')


# ------------------------------------------------------------------------------------------------
# Functions

def hex(n, pad=0):
if pad:
return f'000000000000000000000000{n.value.hex()[2:].upper()}'[-pad:]
else:
return n.value.hex()[2:].upper()

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

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

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

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

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
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

dut.an_ac_sync_ack.value = 0
dut.an_ac_icbi_ack.value = 0
dut.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
# bummer TypeError: Unsupported type for value assignment: <class 'str'> ('48000000480000004800000048000000')
#dut.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}'
# 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

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

tt = hex(dut.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
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':
# when allowing out-of-order, schedule reld once added
if len(readPending) == 0:
reldCyc = sim.cycle + 6 # const for now
else:
reldCyc = readPending[-1].cycD + 4 # worst-case const for now
trans = A2L2Trans(sim, tid, int(tt, 16), int(tag, 16), int(ra, 16), int(lenEnc, 16), wimg, reldCyc)
readPending.append(trans)
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)
trans = A2L2Trans(sim, tid, int(tt, 16), int(tag, 16), int(ra, 16), int(lenEnc, 16), wimg, None, be=be, data=data)
sim.msg(f'T{tid} {transType} {ra} tag={tag} len={trans.len} be={be} data={data} {le}WIMG:{wimg:X}')
trans.doStore()
#assert False, 'got a store'

# data early indicator (d-3)
dut.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
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

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
if trans.xferNum < 4 and trans.xfers == 4:
trans.cycV += 1

# data beat
if len(readPending) > 0 and readPending[0].cycD == sim.cycle: # ordered

trans = readPending[0]
w0,w1,w2,w3,beatNum = trans.readXfer()

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.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 ""}')

if beatNum == trans.xfers:
trans.done = True
countReads += 1 #wtf do this in monitor
if len(readPending) == 1:
readPending = []
else:
readPending = readPending[1:]
dut.an_ac_req_ld_pop.value = 1 #wtf can randomize, etc.


# A2L2 Checker
# check protocol, etc.
async def A2L2Checker(dut, sim):
"""A2L2 interface checker """

me = 'A2L2 Checker'
ok = True
sim.msg(f'{me}: started.')

while ok:
await RisingEdge(dut.clk_1x)


# A2L2 Monitor
# count transactions, etc.
# fail on bad addresses
async def A2L2Monitor(dut, sim):
"""A2L2 interface monitor"""

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

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

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
for i in range(len(sim.config.a2l2.badAddr)):
blk = sim.config.a2l2.badAddr[i]
if 'I' in blk[2].upper():
blkStart = int(blk[0], 16)
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

class A2L2:
driver = A2L2Driver
checker = A2L2Checker
monitor = A2L2Monitor

def __init__(self):
pass

@ -0,0 +1,49 @@
# a2o tb
# make -f Makefile.icarus build # rebuild and sim and fst
# make -f Makefile.icarus run # sim and fst
# make -f Makefile.icarus # sim

#COCOTB_LOG_LEVEL=DEBUG
#GPI_EXTRA=vpi

#COCOTB_RESOLVE_X = ZEROS # VALUE_ERROR ZEROS ONES RANDOM

#SIM_BUILD ?= build
SIM ?= icarus

# options
#COCOTB_HDL_TIMEUNIT ?= 1ns
#COCOTB_HDL_TIMEPRECISION ?= 1ps
#COCOTB_RESOLVE_X = VALUE_ERROR # ZEROS ONES RANDOM

# icarus
#
# includes are needed for *.vh
# unisims is for FPGA RAMs
# coco forces -g2012 for some reason, and appends it after COMPILE_ARGS below! issue #781

VERILOG_ROOT = ../../verilog

COMPILE_ARGS = -I$(VERILOG_ROOT)/trilib -I$(VERILOG_ROOT)/work -y$(VERILOG_ROOT)/unisims -y$(VERILOG_ROOT)/trilib_clk1x -y$(VERILOG_ROOT)/trilib -y$(VERILOG_ROOT)/work

# other options

# rtl
TOPLEVEL_LANG = verilog
# top-level to enable trace, etc.
VERILOG_SOURCES = ./cocotb_icarus.v
TOPLEVEL = cocotb_icarus

# python test
MODULE = tb

# cocotb make rules
include $(shell cocotb-config --makefiles)/Makefile.sim

build: clean sim fst

run: sim fst

fst:
vcd2fst wtf-coco.vcd wtf-coco.fst
rm wtf-coco.vcd

@ -0,0 +1,44 @@
# a2o smt2 tb
# make -f Makefile.icarus build # rebuild and sim and fst
# make -f Makefile.icarus run # sim and fst
# make -f Makefile.icarus # sim

SIM_BUILD ?= build_smt2
SIM ?= icarus

# options
#COCOTB_HDL_TIMEUNIT ?= 1ns
#COCOTB_HDL_TIMEPRECISION ?= 1ps
#COCOTB_RESOLVE_X = VALUE_ERROR # ZEROS ONES RANDOM

# icarus
#
# includes are needed for *.vh
# unisims is for FPGA RAMs
# coco forces -g2012 for some reason, and appends it after COMPILE_ARGS below! issue #781

VERILOG_ROOT = ../../verilog

COMPILE_ARGS = -I$(VERILOG_ROOT)/smt2 -I$(VERILOG_ROOT)/trilib -I$(VERILOG_ROOT)/work -y$(VERILOG_ROOT)/unisims -y$(VERILOG_ROOT)/trilib_clk1x -y$(VERILOG_ROOT)/trilib -y$(VERILOG_ROOT)/work

# other options

# rtl
TOPLEVEL_LANG = verilog
# top-level to enable trace, etc.
VERILOG_SOURCES = ./cocotb_icarus.v
TOPLEVEL = cocotb_icarus

# python test
MODULE = tb

# cocotb make rules
include $(shell cocotb-config --makefiles)/Makefile.sim

build: clean sim fst

run: sim fst

fst:
vcd2fst wtf-coco.vcd wtf-coco.fst
rm wtf-coco.vcd

@ -0,0 +1,45 @@
# a2o tb
# make -f Makefile.icarus build # rebuild and sim and fst
# make -f Makefile.icarus run # sim and fst
# make -f Makefile.icarus # sim

#COCOTB_LOG_LEVEL=DEBUG
#GPI_EXTRA=vpi

#COCOTB_RESOLVE_X = ZEROS # VALUE_ERROR ZEROS ONES RANDOM

SIM_BUILD ?= build_sweetpea
SIM ?= icarus

# options
#COCOTB_HDL_TIMEUNIT ?= 1ns
#COCOTB_HDL_TIMEPRECISION ?= 1ps
#COCOTB_RESOLVE_X = VALUE_ERROR # ZEROS ONES RANDOM

# icarus

VERILOG_ROOT = ../../verilog

COMPILE_ARGS = -I$(VERILOG_ROOT)/sweetpea -I$(VERILOG_ROOT)/trilib -I$(VERILOG_ROOT)/work -y$(VERILOG_ROOT)/unisims -y$(VERILOG_ROOT)/trilib_clk1x -y$(VERILOG_ROOT)/trilib -y$(VERILOG_ROOT)/work

# other options

# rtl
TOPLEVEL_LANG = verilog
# top-level to enable trace, etc.
VERILOG_SOURCES = ./cocotb_icarus.v
TOPLEVEL = cocotb_icarus

# python test
MODULE = tb

# cocotb make rules
include $(shell cocotb-config --makefiles)/Makefile.sim

build: clean sim fst

run: sim fst

fst:
vcd2fst wtf-coco.vcd wtf-coco.fst
rm wtf-coco.vcd

@ -0,0 +1,30 @@
# a2o tb

SIM_BUILD ?= sim_build_verilator
SIM ?= verilator

# set precision
#COCOTB_HDL_TIMEPRECISION ?= 1ns

# verilator
COMPILE_ARGS = --error-limit 1 --language 1364-2001 -Wno-fatal -Wno-LITENDIAN -Iverilog/work -Iverilog/trilib -Iverilog/unisims

# coverage
#EXTRA_ARGS += --coverage
# tracing
EXTRA_ARGS += --trace

# rtl
TOPLEVEL_LANG = verilog
VERILOG_SOURCES += verilog/trilib_clk1x/*.v
VERILOG_SOURCES += verilog/trilib/*.v
VERILOG_SOURCES += verilog/work/*.v

# rtl top
TOPLEVEL = c

# python test
MODULE = tbv

# cocotb make rules
include $(shell cocotb-config --makefiles)/Makefile.sim

@ -0,0 +1,117 @@
# OP Environment

import cocotb
from cocotb.triggers import Timer
from cocotb.handle import Force
from cocotb.handle import Release

from dotmap import DotMap

# ------------------------------------------------------------------------------------------------
# Classes

class Sim(DotMap):

def msg(self, m):
self.dut._log.info(f'[{self.cycle:08d}] {m}') #wtf do multiline if /n in m

def __init__(self, dut, cfg=None):
super().__init__()
self.dut = dut
# defaults
self.memFiles = ['../mem/boot_ieq1.bin.hex'] #wtf cmdline parm
self.threads = None
self.resetCycle = 10
self.hbCycles = 100
self.clk2x = True
self.clk4x = False
self.resetAddr = 0xFFFFFFFC
self.resetOp = 0x48000002
self.maxCycles = 1500
self.memFiles = None
self.config = DotMap()
self.config.core = DotMap({
'creditsLd': None,
'creditsSt': None,
'creditsLdStSingle': False
})
self.config.a2l2 = DotMap({
'badAddr': [('E0','E0', 'IRW')]
})
# json
if cfg is not None:
pass

# runtime
self.cycle = 0
self.ok = True
self.fail = None
self.done = False

if self.threads is None:
try:
v = dut.an_ac_pm_thread_stop[1].value
self.threads = 2
except:
self.threads = 1
self.msg(f'Set threads={self.threads}.')

class TransQ(DotMap):
def __init__(self):
super().__init__()

class Memory(DotMap):

def __init__(self, sim, default=0, logStores=True):
super().__init__()
self.sim = sim
self.data = {}
self.le = False
self.default = default # default word data for unloaded
self.logStores = logStores

def loadFile(self, filename, format='ascii', addr=0, le=0):
# format # binary, ascii, ascii w/addr
# le: reverse bytes
try:
if format == 'ascii':
with open(filename, 'r') as f:
lines = f.readlines()
for line in lines:
self.data[addr] = int(line, 16) # key is int
addr += 4
elif format == 'binary':
pass
elif format == 'addrdata':
pass
except Exception as e:
self.sim.msg(f'Error reading {filename}:\n{e}')
raise IOError

# word-aligned byte address
def read(self, addr):
try:
addr = addr + 0
except:
addr = int(addr, 16)
if addr in self.data:
return self.data[addr]
else:
return self.default

# word-aligned byte address + data
def write(self, addr, data):
try:
addr = addr + 0
except:
addr = int(addr, 16)
try:
data = data + 0
except:
data = int(data, 16)
if self.logStores:
if addr not in self.data:
self.sim.msg(f'Mem Update: @{addr:08X} XXXXXXXX->{data:08X}')
else:
self.sim.msg(f'Mem Update: @{addr:08X} {self.data[addr]:08X}->{data:08X}')
self.data[addr] = data

@ -0,0 +1,913 @@
1 # © IBM Corp. 2020
2 # Licensed under and subject to the terms of the CC-BY 4.0
3 # license (https://creativecommons.org/licenses/by/4.0/legalcode).
4 # Additional rights, including the right to physically implement a softcore
5 # that is compliant with the required sections of the Power ISA
6 # Specification, will be available at no cost via the OpenPOWER Foundation.
7 # This README will be updated with additional information when OpenPOWER's
8 # license is available.
9
10 # boot kernel
11 # set up translations
12 # set up timer facilities
13 # set up threads
14 # call user code
15 # process user rc
16
17 # todo:
18 # 1. skip_printf_init flag should be threaded
19
20 .include "defines.s"
1 # © IBM Corp. 2020
2 # Licensed under and subject to the terms of the CC-BY 4.0
3 # license (https://creativecommons.org/licenses/by/4.0/legalcode).
4 # Additional rights, including the right to physically implement a softcore
5 # that is compliant with the required sections of the Power ISA
6 # Specification, will be available at no cost via the OpenPOWER Foundation.
7 # This README will be updated with additional information when OpenPOWER's
8 # license is available.
9
10 #-----------------------------------------
11 # Defines
12 #-----------------------------------------
13
14 # Regs
15
16 .set r0, 0
17 .set r1, 1
18 .set r2, 2
19 .set r3, 3
20 .set r4, 4
21 .set r5, 5
22 .set r6, 6
23 .set r7, 7
24 .set r8, 8
25 .set r9, 9
26 .set r10,10
27 .set r11,11
28 .set r12,12
29 .set r13,13
30 .set r14,14
31 .set r15,15
32 .set r16,16
33 .set r17,17
34 .set r18,18
35 .set r19,19
36 .set r20,20
37 .set r21,21
38 .set r22,22
39 .set r23,23
40 .set r24,24
41 .set r25,25
42 .set r26,26
43 .set r27,27
44 .set r28,28
45 .set r29,29
46 .set r30,30
47 .set r31,31
48
49 .set f0, 0
50 .set f1, 1
51 .set f2, 2
52 .set f3, 3
53 .set f4, 4
54 .set f5, 5
55 .set f6, 6
56 .set f7, 7
57 .set f8, 8
58 .set f9, 9
59 .set f10,10
60 .set f11,11
61 .set f12,12
62 .set f13,13
63 .set f14,14
64 .set f15,15
65 .set f16,16
66 .set f17,17
67 .set f18,18
68 .set f19,19
69 .set f20,20
70 .set f21,21
71 .set f22,22
72 .set f23,23
73 .set f24,24
74 .set f25,25
75 .set f26,26
76 .set f27,27
77 .set f28,28
78 .set f29,29
79 .set f30,30
80 .set f31,31
81
82 .set cr0, 0
83 .set cr1, 1
84 .set cr2, 2
85 .set cr3, 3
86 .set cr4, 4
87 .set cr5, 5
88 .set cr6, 6
89 .set cr7, 7
90
91 # SPR numbers
92
93 .set srr0, 26
94 .set srr1, 27
95 .set epcr, 307
96 .set tar, 815
97
98 .set dbsr, 304
99 .set dbcr0, 308
100 .set dbcr1, 309
101 .set dbcr2, 310
102 .set dbcr3, 848
103
104 .set ivpr, 63
105
106 .set iucr0, 1011
107 .set iucr1, 883
108 .set iucr2, 884
109
110 .set iudbg0, 888
111 .set iudbg1, 889
112 .set iudbg2, 890
113 .set iulfsr, 891
114 .set iullcr, 892
115
116 .set mmucr0, 1020
117 .set mmucr1, 1021
118 .set mmucr2, 1022
119 .set mmucr3, 1023
120
121 .set tb, 268
122 .set tbl, 284
123 .set tbh, 285
124
125 .set dec, 22
126 .set udec, 550
127 .set tsr, 336
128 .set tcr, 340
129
130 .set xucr0, 1014
131 .set xucr1, 851
132 .set xucr2, 1016
133 .set xucr3, 852
134 .set xucr4, 853
135
136 .set tens, 438
137 .set tenc, 439
138 .set tensr, 437
139
140 .set pid, 48
141 .set pir, 286
142 .set pvr, 287
143 .set tir, 446
144
21
22 .section .text
23 start:
24
25 int_000:
26 0000 48000400 b boot_start
27
28 # critical input
29 0004 4800001C .align 5
29 60000000
29 60000000
29 60000000
29 60000000
30 int_020:
31 0020 48000000 b .
32
33 # debug
34 0024 4800001C .align 5
34 60000000
34 60000000
34 60000000
34 60000000
35 int_040:
36 0040 48000000 b .
37
38 # dsi
39 0044 4800001C .align 5
39 60000000
39 60000000
39 60000000
39 60000000
40 int_060:
41 0060 48000000 b .
42
43 # isi
44 0064 4800001C .align 5
44 60000000
44 60000000
44 60000000
44 60000000
45 int_080:
46 0080 48000000 b .
47
48 # external
49 0084 4800001C .align 5
49 60000000
49 60000000
49 60000000
49 60000000
50 int_0A0:
51 00a0 48000000 b .
52
53 # alignment
54 00a4 4800001C .align 5
54 60000000
54 60000000
54 60000000
54 60000000
55 int_0C0:
56 00c0 48000000 b .
57
58 # program
59 00c4 4800001C .align 5
59 60000000
59 60000000
59 60000000
59 60000000
60 int_0E0:
61 00e0 48000000 b .
62
63 # fp unavailable
64 00e4 4800001C .align 5
64 60000000
64 60000000
64 60000000
64 60000000
65 int_100:
66 0100 48000000 b .
67
68 # sc
69 0104 4800001C .align 5
69 60000000
69 60000000
69 60000000
69 60000000
70 int_120:
71 0120 48000CE0 b int_120_handler
72
73 # apu unavailable
74 0124 4800001C .align 5
74 60000000
74 60000000
74 60000000
74 60000000
75 int_140:
76 0140 48000000 b .
77
78 # decrementer
79 0144 4800001C .align 5
79 60000000
79 60000000
79 60000000
79 60000000
80 int_160:
81 0160 48000000 b .
82
83 # fit
84 0164 4800001C .align 5
84 60000000
84 60000000
84 60000000
84 60000000
85 int_180:
86 0180 48000000 b .
87
88 # watchdog
89 0184 4800001C .align 5
89 60000000
89 60000000
89 60000000
89 60000000
90 int_1A0:
91 01a0 48000000 b .
92
93 # dtlb
94 01a4 4800001C .align 5
94 60000000
94 60000000
94 60000000
94 60000000
95 int_1C0:
96 01c0 48000000 b .
97
98 # itlb
99 01c4 4800001C .align 5
99 60000000
99 60000000
99 60000000
99 60000000
100 int_1E0:
101 01e0 48000000 b .
102
103 # vector unavailable
104 01e4 4800001C .align 5
104 60000000
104 60000000
104 60000000
104 60000000
105 int_200:
106 0200 48000000 b .
107
108 #
109 0204 4800001C .align 5
109 60000000
109 60000000
109 60000000
109 60000000
110 int_220:
111 0220 48000000 b .
112
113 #
114 0224 4800001C .align 5
114 60000000
114 60000000
114 60000000
114 60000000
115 int_240:
116 0240 48000000 b .
117
118 #
119 0244 4800001C .align 5
119 60000000
119 60000000
119 60000000
119 60000000
120 int_260:
121 0260 48000000 b .
122
123 # doorbell
124 0264 4800001C .align 5
124 60000000
124 60000000
124 60000000
124 60000000
125 int_280:
126 0280 48000000 b .
127
128 # doorbell critical
129 0284 4800001C .align 5
129 60000000
129 60000000
129 60000000
129 60000000
130 int_2A0:
131 02a0 48000000 b .
132
133 # doorbell guest
134 02a4 4800001C .align 5
134 60000000
134 60000000
134 60000000
134 60000000
135 int_2C0:
136 02c0 48000000 b .
137
138 # doorbell guest critical
139 02c4 4800001C .align 5
139 60000000
139 60000000
139 60000000
139 60000000
140 int_2E0:
141 02e0 48000000 b .
142
143 # hvsc
144 02e4 4800001C .align 8
144 60000000
144 60000000
144 60000000
144 60000000
145 int_300:
146 0300 48000A00 b int_300_handler
147
148 # hvpriv
149 0304 4800001C .align 5
149 60000000
149 60000000
149 60000000
149 60000000
150 int_320:
151 0320 48000000 b .
152
153 # lrat
154 0324 4800001C .align 5
154 60000000
154 60000000
154 60000000
154 60000000
155 int_340:
156 0340 48000000 b .
157
158 # -------------------------------------------------------------------------------------------------
159 # initial translation
160 # both erats:
161 # 00000000 1M: (boot)
162 # 10000000 1M: (test)
163
164 0344 480000BC .align 8
164 60000000
164 60000000
164 60000000
164 60000000
165 boot_start:
166
167 0400 7CBE6AA6 mfspr r5,tir # who am i?
168 0404 2C250000 cmpdi r5,0x00 # skip unless T0
169 0408 408200EC bne init_t123
170
171 040c 3C608C00 lis r3,0x8C00 # 32=ecl 36:37=tlbsel (10=i, 11=d)
172 # derat 31 @00000000
173
174 0410 3800001F li r0,0x001F # entry #31
175 0414 38400015 li r2,0x0015 # word 2 wlc=40:41 rsvd=42 u=44:47 r=48 c=49 wimge=52:56 vf=57 ux/
176 0418 38800000 li r4,0 # word 1 rpn(32:51)=32:51 rpn(22:31)=54:63
177 041c 3900025F li r8,0x025F # word 0 epn=32:51 class=52:53 v=54 x=55 size=56:59 thrd=60:63 s
178
179 0420 7C7CFBA6 mtspr mmucr0,r3
180 0424 7C4011A6 eratwe r2,r0,2
181 0428 7C8009A6 eratwe r4,r0,1
182 042c 7D0001A6 eratwe r8,r0,0
183 0430 4C00012C isync
184
185 0434 81400A08 lwz r10,CONFIG+S_ERATW2(r0) # load parms for erat settings
186
187 # derat 30 @100000000
188
189 0438 3800001E li r0,0x001E # entry #30
190 043c 3C801000 lis r4,0x1000 # word 1 rpn(32:51)=32:51 rpn(22:31)=54:63
191 0440 3900025F li r8,0x025F # word 0 epn=32:51 class=52:53 v=54 x=55 size=56:59 thrd=60:63 s
192 0444 65081000 oris r8,r8,0x1000
193
194 0448 7D4011A6 eratwe r10,r0,2
195 044c 7C8009A6 eratwe r4,r0,1
196 0450 7D0001A6 eratwe r8,r0,0
197 0454 4C00012C isync
198
199 0458 3C608800 lis r3,0x8800 # 32=ecl 36:37=tlbsel (10=i, 11=d)
200 # ierat 15 @00000000
201
202 045c 3800000F li r0,0x000F # entry #15
203 0460 3840003F li r2,0x003F # word 2 wlc=40:41 rsvd=42 u=44:47 r=48 c=49 wimge=52:56 vf=57 ux/
204 0464 38800000 li r4,0 # word 1 rpn(32:51)=32:51 rpn(22:31)=54:63
205 0468 3900025F li r8,0x025F # word 0 epn=32:51 class=52:53 v=54 x=55 size=56:59 thrd=60:63 s
206
207 046c 7C7CFBA6 mtspr mmucr0,r3
208 0470 7C4011A6 eratwe r2,r0,2
209 0474 7C8009A6 eratwe r4,r0,1
210 0478 7D0001A6 eratwe r8,r0,0
211 047c 4C00012C isync
212
213 # *** leave the init'd entry 14 for MT access to FFFFFFC0
214 # ierat 13 @10000000
215
216 0480 3800000D li r0,0x000D # entry #13
217 0484 3C801000 lis r4,0x1000 # word 1 rpn(32:51)=32:51 rpn(22:31)=54:63
218 0488 3900025F li r8,0x025F # word 0 epn=32:51 class=52:53 v=54 x=55 size=56:59 thrd=60:63 s
219 048c 65081000 oris r8,r8,0x1000
220
221 0490 7D4011A6 eratwe r10,r0,2
222 0494 7C8009A6 eratwe r4,r0,1
223 0498 7D0001A6 eratwe r8,r0,0
224 049c 4C00012C isync
225
226 # -------------------------------------------------------------------------------------------------
227 # init
228 #
229
230 # T0-only
231 # set up any core facilities, then enable the others if config'd
232 init_t0:
233
234 # switch to 64b
235
236 04a0 81400A00 lwz r10,CONFIG+S_MSR(r0)
237 04a4 7D400124 mtmsr r10
238 04a8 4C00012C isync
239
240 # other init
241
242 04ac 3C200300 lis r1,0x0300 # icm=gicm=1
243 04b0 7C334BA6 mtspr epcr,r1
244
245 # set up timer facs
246
247 04b4 38200000 li r1,0 # clear
248 04b8 7C3603A6 mtspr dec,r1
249 04bc 7C3D43A6 mtspr tbh,r1
250 04c0 7C3C43A6 mtspr tbl,r1
251
252 04c4 3C40FE00 lis r2,0xFE00 # mask: clear enw,wis,wrs,dis,fis,udis
253 04c8 7C5053A6 mtspr tsr,r2
254
255 04cc 7C56FAA6 mfspr r2,xucr0
256 04d0 70420200 andi. r2,r2,0x0200 # set tcs=0
257 04d4 7C56FBA6 mtspr xucr0,r2
258
259 04d8 7C3053A6 mtspr tsr,r1 # clear tsr
260 04dc 7C3453A6 mtspr tcr,r1 # disable all timers
261
262 # set thread configuration
263
264 04e0 80200A04 lwz r1,CONFIG+S_FLAGS(r0)
265 04e4 7021000F andi. r1,r1,0xF
266 04e8 7C366BA6 mtspr tens,r1 # 60:63 = tid 3:0 enabled
267 #not r1,r1
268 #mtspr tenc,r1 # in case T0 is marked disabled
269 04ec 4C00012C isync
270
271 04f0 48000014 b boot_complete
272
273 # except T0
274 # just worry about myself
275
276 init_t123:
277
278 # switch to 64b
279
280 04f4 81400A00 lwz r10,CONFIG+S_MSR(r0)
281 04f8 7D400124 mtmsr r10
282 04fc 4C00012C isync
283
284 0500 48000004 b boot_complete
285
286 # -------------------------------------------------------------------------------------------------
287 boot_complete:
288
289 # set up thread and hop to it
290
291 0504 80200A04 lwz r1,CONFIG+S_FLAGS(r0)
292 0508 74218000 andis. r1,r1,0x8000 # 1=skip initial printf init
293 050c 40820008 bne boot_complete_1
294 0510 480006F1 bl printf_reset # wipe buffer
295
296 boot_complete_1:
297
298 0514 80200A04 lwz r1,CONFIG+S_FLAGS(r0)
299 0518 3C407FFF lis r2,0x7FFF # clear printf flag
300 051c 6042FFFF ori r2,r2,0xFFFF
301 0520 7C211038 and r1,r1,r2
302 0524 90200A04 stw r1,CONFIG+S_FLAGS(r0)
303
304 0528 7CBE6AA6 mfspr r5,tir # who am i?
305 052c 78A53664 sldi r5,r5,6 # 64B offset
306 0530 38A50A80 addi r5,r5,CONFIG+T_CONFIG
307
308 0534 81650000 lwz r11,T_MSR(r5)
309 0538 E9850008 ld r12,T_STACK(r5)
310 053c E9A50010 ld r13,T_ENTRY(r5)
311
312 0540 80200A04 lwz r1,CONFIG+S_FLAGS(r0)
313 0544 70210010 andi. r1,r1,FLAG_EOT_SC
314 0548 4182001C beq eot_blr
315
316 eot_sc:
317
318 054c 80400A0C lwz r2,CONFIG+S_EOT_SC(r0)
319 0550 3C204400 lis r1,0x4400 # 'sc 1'
320 0554 60210012 ori r1,r1,0022
321 0558 F8220000 std r1,0x0(r2)
322 055c 7C2803A6 mtlr r1 # prog will blr to sc
323 0560 48000014 b process_start
324
325 eot_blr:
326
327 0564 48000005 bl 4
328 0568 7C2802A6 mflr r1
329 056c 38210030 addi r1,r1,0x30 # !!!!!!!!!!!!!!! <-- WARNING!
330 0570 7C2803A6 mtlr r1 # prog will blr to exec_complete
331
332 process_start:
333
334 0574 7D7B03A6 mtspr srr1,r11 # msr
335 0578 7DBA03A6 mtspr srr0,r13 # @entry
336 057c 7D816378 mr r1,r12 # @stack
337 0580 7C7E6AA6 mfspr r3,tir # tid - main(tid) if yall want it
338
339 0584 7C4C42A6 mfspr r2,tb
340 0588 F8450030 std r2,T_TIMER_START(r5)
341 058c 4C000064 rfi
342 0590 60000000 nop # !!!!!!!!!!!!!!! pads for lr calc
343 0594 60000000 nop
344 0598 60000000 nop
345
346 # -------------------------------------------------------------------------------------------------
347 exec_complete:
348 # allow blr to here, or it will be entered by sc directly
349
350 # user blr'd here...
351 059c 44000022 sc 1 # hvsc back to sup state
352
353 exec_complete_sup:
354 05a0 7CBE6AA6 mfspr r5,tir # who am i?
355 05a4 78A53664 sldi r5,r5,6 # 64B offset
356 05a8 38A50A80 addi r5,r5,CONFIG+T_CONFIG
357
358 05ac 7C4C42A6 mfspr r2,tb
359 05b0 F8450038 std r2,T_TIMER_END(r5)
360
361 05b4 2C230000 cmpdi r3,0 # check rc
362 05b8 41820148 beq pass
363 05bc 48000044 b fail
364
365 # -------------------------------------------------------------------------------------------------
366 # dead zone
367 05c0 48000040 .align 8
367 60000000
367 60000000
367 60000000
367 60000000
368 fail:
369 0600 48000000 b .
370
371 # -------------------------------------------------------------------------------------------------
372 # happy ending
373 0604 480000FC .align 8
373 60000000
373 60000000
373 60000000
373 60000000
374 pass:
375 0700 48000000 b .
376
377 # -------------------------------------------------------------------------------------------------
378
379 # dec
380 0704 480000FC .align 11
380 60000000
380 60000000
380 60000000
380 60000000
381 int_800:
382 0800 48000000 b .
383
384 # perf
385 0804 4800001C .align 5
385 60000000
385 60000000
385 60000000
385 60000000
386 int_820:
387 0820 48000000 b .
388
389 .set CONFIG,0x0A00
390 # -------------------------------------------------------------------------------------------------
391 # config info
392 0824 480001DC .align 9
392 60000000
392 60000000
392 60000000
392 60000000
393
394 0a00 8002B000 .long 0x8002B000 # sup MSR cm=1 ce=1 ee=1 pr=0 fp=1 me=1 fe=00 de=0 is=0 ds=0
395 0a04 80000001 .long 0x80000001 # flags: skip_printf_init=0 eot_sc=27 thr_en=28:31(T3:T0)
396 0a08 000000BF .long 0x000000BF # erat w2 (test) # word 2 wlc=40:41 rsvd=42 u=44:47 r=48 c=49 wi
397 0a0c 10000000 .long 0x10000000 # @user eot sc
398
399 # per-thread configs (64B each)
400 0a10 48000070 .align 7
400 60000000
400 60000000
400 60000000
400 60000000
401 0a80 8002F000 .long 0x8002F000 # usr MSR cm=1 ce=1 ee=1 pr=1 fp=1 me=1 fe=00 de=0 is=0 ds=0
402 0a84 00000000 .long 0x00000000 #
403 0a88 00000000 .long 0x00000000 #
404 0a8c 1003FF00 .long 0x1003FF00 # @stack
405 0a90 00000000 .long 0x00000000 #
406 0a94 100004B0 .long 0x100004B0 # @entry
407 0a98 00000000 .long 0
408 0a9c 10030000 .long 0x10030000 # @print_start
409 0aa0 00000000 .long 0
410 0aa4 10031FFF .long 0x10031FFF # @print_end
411 0aa8 00000000 .long 0
412 0aac 10030000 .long 0x10030000 # print ptr
413 0ab0 00000000 .quad 0 # start tb
413 00000000
414 0ab8 00000000 .quad 0 # end tb
414 00000000
415
416 0ac0 8002F000 .long 0x8002F000 # usr MSR cm=1 ce=1 ee=1 pr=1 fp=1 me=1 fe=00 de=0 is=0 ds=0
417 0ac4 00000000 .long 0x00000000 #
418 0ac8 00000000 .long 0x00000000 #
419 0acc 1003DF00 .long 0x1003DF00 # @stack
420 0ad0 00000000 .long 0x00000000 #
421 0ad4 100004B0 .long 0x100004B0 # @entry
422 0ad8 00000000 .long 0
423 0adc 10032000 .long 0x10032000 # @print_start
424 0ae0 00000000 .long 0
425 0ae4 10033FFF .long 0x10033FFF # @print_end
426 0ae8 00000000 .long 0
427 0aec 10032000 .long 0x10032000 # print ptr
428 0af0 00000000 .quad 0 # start tb
428 00000000
429 0af8 00000000 .quad 0 # end tb
429 00000000
430
431 0b00 8002F000 .long 0x8002F000 # usr MSR cm=1 ce=1 ee=1 pr=1 fp=1 me=1 fe=00 de=0 is=0 ds=0
432 0b04 00000000 .long 0x00000000 # flags
433 0b08 00000000 .long 0x00000000 #
434 0b0c 1003BF00 .long 0x1003BF00 # @stack
435 0b10 00000000 .long 0x00000000 #
436 0b14 100004B0 .long 0x100004B0 # @entry
437 0b18 00000000 .long 0
438 0b1c 10034000 .long 0x10034000 # @print_start
439 0b20 00000000 .long 0
440 0b24 10035FFF .long 0x10035FFF # @print_end
441 0b28 00000000 .long 0
442 0b2c 10034000 .long 0x10034000 # print ptr
443 0b30 00000000 .quad 0 # start tb
443 00000000
444 0b38 00000000 .quad 0 # end tb
444 00000000
445
446 0b40 8002F000 .long 0x8002F000 # usr MSR cm=1 ce=1 ee=1 pr=1 fp=1 me=1 fe=00 de=0 is=0 ds=0
447 0b44 00000000 .long 0x00000000 # flags
448 0b48 00000000 .long 0x00000000 #
449 0b4c 10039F00 .long 0x10039F00 # @stack
450 0b50 00000000 .long 0x00000000 #
451 0b54 100004B0 .long 0x100004B0 # @entry
452 0b58 00000000 .long 0
453 0b5c 10036000 .long 0x10036000 # @print_start
454 0b60 00000000 .long 0
455 0b64 10037FFF .long 0x10037FFF # @print_end
456 0b68 00000000 .long 0
457 0b6c 10036000 .long 0x10036000 # print ptr
458 0b70 00000000 .quad 0 # start tb
458 00000000
459 0b78 00000000 .quad 0 # end tb
459 00000000
460
461
462 .set S_MSR,0x00
463 .set S_FLAGS,0x04
464 .set S_ERATW2,0x08
465 .set S_EOT_SC,0x0C
466
467 .set T_CONFIG,0x80
468 .set T_MSR,0x00
469 .set T_FLAGS,0x04
470 .set T_STACK,0x08
471 .set T_ENTRY,0x10
472 .set T_TIMER_START,0x30
473 .set T_TIMER_END,0x38
474 .set T_PRINTSTART, 0x18
475 .set T_PRINTEND, 0x20
476 .set T_PRINTF, 0x28
477 .set FLAG_EOT_SC,0x10
478
479
480 # -------------------------------------------------------------------------------------------------
481 # other stuff
482 0b80 48000080 .align 10
482 60000000
482 60000000
482 60000000
482 60000000
483
484 # clear buffer and reset pointer to start
485 .align 6
486 printf_reset:
487
488 0c00 7CBE6AA6 mfspr r5,tir # who am i?
489 0c04 78A53664 sldi r5,r5,6 # 64B offset
490 0c08 38A50A80 addi r5,r5,CONFIG+T_CONFIG
491
492 0c0c 38C50018 addi r6,r5,T_PRINTSTART
493 0c10 E8E60000 ld r7,0(r6) # buffer start
494 0c14 38C50020 addi r6,r5,T_PRINTEND
495 0c18 E9060000 ld r8,0(r6) # buffer end
496 0c1c 7D074050 sub r8,r8,r7
497 0c20 39080001 addi r8,r8,1 # num bytes
498
499 0c24 7D0903A6 mtctr r8
500 0c28 38C00000 li r6,0
501 0c2c 7CE83B78 mr r8,r7
502 printf_reset_clr:
503 0c30 98C80000 stb r6,0(r8)
504 0c34 39080001 addi r8,r8,1
505 0c38 4200FFF8 bdnz printf_reset_clr
506
507 0c3c 39050028 addi r8,r5,T_PRINTF
508 0c40 F8E80000 std r7,0(r8) # reset ptr
509
510 0c44 4E800020 blr
511
512
513 # hvsc
514 0c48 480000B8 .align 8
514 60000000
514 60000000
514 60000000
514 60000000
515 # go to exec_complete_sup in sup mode
516 int_300_handler:
517
518 0d00 80000A00 lwz r0,CONFIG+S_MSR(r0)
519 0d04 7C000124 mtmsr r0
520 0d08 4C00012C isync
521 0d0c 4BFFF894 b exec_complete_sup
522
523 # sc
524 0d10 480000F0 .align 8
524 60000000
524 60000000
524 60000000
524 60000000
525 # r3 is id, remaining are function-specific
526 # not preserving r0, r3-r9 right now
527 #
528 # 0001 whoami
529 # 0010 tick
530 # 0100 putchar r4=c
531 # 0106 printf_mode *NI*
532 # 0107 printf_rst
533 #
534 int_120_handler:
535
536 0e00 7C0802A6 mflr r0
537
538 0e04 2C230001 cmpdi r3,0x0001
539 0e08 41820038 beq sc_whoami
540 0e0c 2C230010 cmpdi r3,0x0010
541 0e10 41820070 beq sc_tick
542 0e14 2C230100 cmpdi r3,0x100
543 0e18 418200A8 beq sc_putchar
544 0e1c 2C230107 cmpdi r3,0x107
545 0e20 41820120 beq sc_printf_rst
546
547 0e24 3860FFFF li r3,-1
548 0e28 7C0803A6 mtlr r0
549 0e2c 4C000064 rfi
550
551 # thread id
552 0e30 60000000 .align 6
552 60000000
552 60000000
552 60000000
553 sc_whoami:
554 0e40 7C7E6AA6 mfspr r3,tir
555 0e44 4C000064 rfi
556
557 # tb
558 0e48 48000038 .align 6
558 60000000
558 60000000
558 60000000
558 60000000
559 sc_tick:
560 0e80 7C6C42A6 mfspr r3,tb
561 0e84 4C000064 rfi
562
563 # wrap buffer; could add flag to stop when full, or reset
564 0e88 48000038 .align 6
564 60000000
564 60000000
564 60000000
564 60000000
565 sc_putchar:
566
567 0ec0 7CBE6AA6 mfspr r5,tir # who am i?
568 0ec4 78A53664 sldi r5,r5,6 # 64B offset
569 0ec8 38A50A80 addi r5,r5,CONFIG+T_CONFIG
570
571 0ecc 38C50028 addi r6,r5,T_PRINTF
572 0ed0 E8E60000 ld r7,0(r6) # buffer ptr
573 0ed4 98870000 stb r4,0(r7) # store char
574 0ed8 38E70001 addi r7,r7,1
575
576 0edc 39050020 addi r8,r5,T_PRINTEND
577 0ee0 E9080000 ld r8,0(r8) # buffer end
578 0ee4 7C274000 cmpd r7,r8
579 0ee8 38600000 li r3,0 # rc=normal
580 0eec 40810010 ble sc_putchar_ok
581 0ef0 39050018 addi r8,r5,T_PRINTSTART
582 0ef4 E8E80000 ld r7,0(r8) # buffer start
583 0ef8 3860FFFF li r3,-1 # rc=full
584 sc_putchar_ok:
585 0efc F8E60000 std r7,0(r6) # save ptr
586
587 0f00 4C000064 rfi
588
589 # clear buffer and reset pointer to start
590 0f04 4800003C .align 6
590 60000000
590 60000000
590 60000000
590 60000000
591 sc_printf_rst:
592
593 0f40 7C6902A6 mfctr r3
594
595 0f44 4BFFFCBD bl printf_reset
596
597 0f48 7C6903A6 mtctr r3
598 0f4c 7C0803A6 mtlr r0
599 0f50 38600000 li r3,0
600
601 0f54 4C000064 rfi
602

@ -0,0 +1 @@
+timescale+1ns/1ps

@ -0,0 +1,321 @@

`include "tri_a2o.vh"

`timescale 1ns/1ps

// might add some sim-only lines to enable clks, etc.

module cocotb_icarus (

input[0:`NCLK_WIDTH-1] nclk,
input scan_in,
output scan_out,

// Pervasive clock control
input an_ac_rtim_sl_thold_8,
input an_ac_func_sl_thold_8,
input an_ac_func_nsl_thold_8,
input an_ac_ary_nsl_thold_8,
input an_ac_sg_8,
input an_ac_fce_8,
input [0:7] an_ac_abst_scan_in,

// L2 LARX/STCX
input [0:`THREADS-1] an_ac_reservation_vld,
input [0:`THREADS-1] an_ac_stcx_complete,
input [0:`THREADS-1] an_ac_stcx_pass,

// ICBI ACK Interface
input an_ac_icbi_ack,
input [0:1] an_ac_icbi_ack_thread,

// Back invalidate interface
input an_ac_back_inv,
input [64-`REAL_IFAR_WIDTH:63] an_ac_back_inv_addr,
input [0:4] an_ac_back_inv_target, // connect to bit(0)
input an_ac_back_inv_local,
input an_ac_back_inv_lbit,
input an_ac_back_inv_gs,
input an_ac_back_inv_ind,
input [0:7] an_ac_back_inv_lpar_id,
output ac_an_back_inv_reject,
output [0:7] ac_an_lpar_id,

// L2 Reload Inputs
input an_ac_reld_data_vld, // reload data is coming next cycle
input [0:4] an_ac_reld_core_tag, // reload data destinatoin tag (which load queue)
input [0:127] an_ac_reld_data, // Reload Data
input [58:59] an_ac_reld_qw, // quadword address of reload data beat
input an_ac_reld_ecc_err, // Reload Data contains a Correctable ECC error
input an_ac_reld_ecc_err_ue, // Reload Data contains an Uncorrectable ECC error
input an_ac_reld_data_coming,
input an_ac_reld_ditc,
input an_ac_reld_crit_qw,
input an_ac_reld_l1_dump,
input [0:3] an_ac_req_spare_ctrl_a1, // spare control bits from L2

// load/store credit control
input an_ac_flh2l2_gate, // Gate L1 Hit forwarding SPR config bit
input an_ac_req_ld_pop, // credit for a load (L2 can take a load command)
input an_ac_req_st_pop, // credit for a store (L2 can take a store command)
input an_ac_req_st_gather, // credit for a store due to L2 gathering of store commands
input [0:`THREADS-1] an_ac_sync_ack,

//SCOM Satellite
input [0:3] an_ac_scom_sat_id,
input an_ac_scom_dch,
input an_ac_scom_cch,
output ac_an_scom_dch,
output ac_an_scom_cch,

// FIR and Error Signals
output [0:`THREADS-1] ac_an_special_attn,
output [0:2] ac_an_checkstop,
output [0:2] ac_an_local_checkstop,
output [0:2] ac_an_recov_err,
output ac_an_trace_error,
output ac_an_livelock_active,
input an_ac_checkstop,
input [0:`THREADS-1] an_ac_external_mchk,

// Perfmon Event Bus
output [0:4*`THREADS-1] ac_an_event_bus0,
output [0:4*`THREADS-1] ac_an_event_bus1,

// Reset related
input an_ac_reset_1_complete,
input an_ac_reset_2_complete,
input an_ac_reset_3_complete,
input an_ac_reset_wd_complete,

// Power Management
output [0:`THREADS-1] ac_an_pm_thread_running,
input [0:`THREADS-1] an_ac_pm_thread_stop,
input [0:`THREADS-1] an_ac_pm_fetch_halt,
output ac_an_power_managed,
output ac_an_rvwinkle_mode,

// Clock, Test, and LCB Controls
input an_ac_gsd_test_enable_dc,
input an_ac_gsd_test_acmode_dc,
input an_ac_ccflush_dc,
input an_ac_ccenable_dc,
input an_ac_lbist_en_dc,
input an_ac_lbist_ip_dc,
input an_ac_lbist_ac_mode_dc,
input an_ac_scan_diag_dc,
input an_ac_scan_dis_dc_b,

//Thold input to clock control macro
input [0:8] an_ac_scan_type_dc,

// Pervasive
output ac_an_reset_1_request,
output ac_an_reset_2_request,
output ac_an_reset_3_request,
output ac_an_reset_wd_request,
input an_ac_lbist_ary_wrt_thru_dc,