openpowerwtf 2 years ago
commit 2ab95aafc4

@ -0,0 +1,331 @@
# 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

@ -0,0 +1,173 @@
// simple verilator top
// uses a2owb with sim mem interface

#define TRACING

#include <cstddef>
#include <iostream>
#include <iomanip>

#include "verilated.h"
#include "Vc.h"

#ifdef TRACING
#include "verilated_vcd_c.h"
VerilatedVcdC *t;
#else
unsigned int t = 0;
#endif

/*
#include "uart/uartsim.h"
*/

Vc* m;

vluint64_t main_time = 0; // in units of timeprecision used in verilog or --timescale-override
// what is it? it changed to 941621251 after calling loadmem()

double sc_time_stamp() { // $time in verilog
return main_time;
}

const int resetCycle = 10;
const int threadRunCycle = 200;
const int runCycles = 1000;
const int hbCycles = 500;
const int threads = 1; // needs a more realistic a2l2 data return to work in smt

int mem[16384][4]; // 16K QW

void loadmem(void) {
int adr;
mem[0x0000/4] = 0x48000400;
adr = 0x400/4;

mem[adr++] = threads == 1 ? 0x38200001 : 0x38200003;
mem[adr++] = 0x7C366BA6;
mem[adr++] = 0x7C366BA6;
mem[adr++] = 0x7C3E6AA6;
mem[adr++] = 0x4C00012C;
mem[adr++] = 0x2C010000;
mem[adr++] = 0x38200660;
mem[adr++] = 0x41820008;
mem[adr++] = 0x38210100;
mem[adr++] = 0x7C2903A6;
mem[adr++] = 0x4E800420;

}

// nclk = (clk,reset,clk2x,clk4x,-,-)

int main(int argc, char **argv) {
using namespace std;

loadmem();

cout << setfill('0');

Verilated::commandArgs(argc, argv);
m = new Vc;

#ifdef TRACING
Verilated::traceEverOn(true);
t = new VerilatedVcdC;
m->trace(t, 99);
t->open("wtf.vcd");
cout << "Tracing enabled." << endl;
#endif

bool resetDone = false;
unsigned int threadStop = 0x3;

unsigned int tick = 0;
unsigned int cycle = 1;
unsigned int readPending = 0;
unsigned int readAddr = 0;
unsigned int readTag = 0;
unsigned int readTID = 0;
unsigned int countReads = 0;

m->nclk = 0x3C; // run 2x,4x = 1x
cout << setw(8) << cycle << "Resetting..." << endl;

m->an_ac_pm_thread_stop = threadStop;
cout << setw(8) << cycle << "Thread stop=" << threadStop << endl;

// can skip 4x with new gpr array
// 1x=4/4 2x=2/2 4x=1/1
// 1 1 1 7
// 1 1 0 6
// 1 0 1 5
// 1 0 0 4
// 0 1 1 3
// 0 1 0 2
// 0 0 1 1
// 0 0 0 0
// (insert reset)
//const int clocks[8] = {11, 0, 11, 0, 11, 0, 11, 0}; // 2x,4x == 1x
//const int clocks[8] = {11, 10, 9, 8, 3, 2, 1, 0}; // 1x, 2x, 4x
//const int ticks1x = 8;
const int clocks[4] = {10, 8, 2, 0}; // 1x, 2x
const int ticks1x = 4;

while (!Verilated::gotFinish()) {

if (!resetDone && (cycle > resetCycle)) {
m->nclk &= 0x2F;
cout << setw(8) << cycle << "Releasing reset." << endl;
resetDone = true;
}

if (threadStop && (cycle > threadRunCycle)) {
threadStop = 0x0;
m->an_ac_pm_thread_stop = threadStop;
cout << setw(8) << cycle << "Thread stop=" << threadStop << endl;
}

m->nclk = (m->nclk & 0x10) | (clocks[tick % 8] << 2);
tick++;
m->eval();

// bus is 1x clock
if ((tick % ticks1x) == 0) {

/*
cout << setw(8) << cycle << " an_ac_rsp: data="<< hex << uppercase << setw(8) << m->an_ac_reld_data[3]
<< hex << uppercase << setw(8) << m->an_ac_reld_data[2]
<< hex << uppercase << setw(8) << m->an_ac_reld_data[1]
<< hex << uppercase << setw(8) << m->an_ac_reld_data[0]
<< dec << nouppercase << endl;
*/

}

// finish clock stuff
if ((tick % ticks1x) == 0) {
cycle++;
if ((cycle % hbCycles) == 0) {
cout << setw(8) << cycle << " ...tick..." << endl;
}
}
#ifdef TRACING
t->dump(tick);
t->flush();
#endif

// check for fails

// hit limit
if (cycle > runCycles) {
break;
}

}

#ifdef TRACING
t->close();
#endif
m->final();

exit(EXIT_SUCCESS);

}

@ -0,0 +1,337 @@
// © IBM Corp. 2022
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by
// the terms below; you may not use the files in this repository except in
// compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the
// License, the "Work" hereby includes implementations of the work of authorship
// in physical form.
//
// 2) Notwithstanding any terms to the contrary in the License, any licenses
// necessary for implementation of the Work that are available from OpenPOWER
// via the Power ISA End User License Agreement (EULA) are explicitly excluded
// hereunder, and may be obtained from OpenPOWER under the terms and conditions
// of the EULA.
//
// Unless required by applicable law or agreed to in writing, the reference design
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
// for the specific language governing permissions and limitations under the License.
//
// Additional rights, including the ability to physically implement a softcore that
// is compliant with the required sections of the Power ISA Specification, are
// available at no cost under the terms of the OpenPOWER Power ISA EULA, which can be
// obtained (along with the Power ISA) here: https://openpowerfoundation.org.

// A2L2 bridge
// 1. interface to a sim mem[]
// 2. interface to wb (could use mem for l2 also)

a2l2wb n0(
parameter MEM_QW = 16384;
)
(
input clk,
input rst,

input ac_an_req_pwr_token,
input ac_an_req,
input [64-`REAL_IFAR_WIDTH:63] ac_an_req_ra,
input [0:5] ac_an_req_ttype,
input [0:2] ac_an_req_thread,
input [0:4] ac_an_req_ld_core_tag,
input [0:2] ac_an_req_ld_xfr_len,
input ac_an_req_wimg_w,
input ac_an_req_wimg_i,
input ac_an_req_wimg_m,
input ac_an_req_wimg_g,
input ac_an_req_endian,
input [0:3] ac_an_req_user_defined,
input [0:3] ac_an_req_spare_ctrl_a0,
input ac_an_st_data_pwr_token,
input [0:31] ac_an_st_byte_enbl,
input [0:255] ac_an_st_data,

output an_ac_reld_data_vld,
output [0:4] an_ac_reld_core_tag,
output [0:127] an_ac_reld_data,
output [58:59] an_ac_reld_qw,
output an_ac_reld_ecc_err,
output an_ac_reld_ecc_err_ue,
output an_ac_reld_data_coming,
output an_ac_reld_ditc,
output an_ac_reld_crit_qw,
output an_ac_reld_l1_dump,
output [0:3] an_ac_req_spare_ctrl_a1,
output [0:`THREADS-1] an_ac_sync_ack,

output an_ac_req_ld_pop,
output an_ac_req_st_pop,
output an_ac_req_st_gather,

output [0:`THREADS-1] an_ac_stcx_complete,
output [0:`THREADS-1] an_ac_stcx_pass,
output [0:`THREADS-1] an_ac_reservation_vld,

output an_ac_icbi_ack,
output [0:1] an_ac_icbi_ack_thread,
output an_ac_back_inv,
output [64-`REAL_IFAR_WIDTH:63] an_ac_back_inv_addr,
output [0:4] an_ac_back_inv_target,
output an_ac_back_inv_local,
output an_ac_back_inv_lbit,
output an_ac_back_inv_gs,
output an_ac_back_inv_ind,
output [0:7] an_ac_back_inv_lpar_id,
input ac_an_back_inv_reject,
input [0:7] ac_an_lpar_id,

output [0:31] mem_adr,
input [0:127] mem_dat,
output mem_wr_val,
output [0:127] mem_wr_dat,

output wb_i_stb,
output wb_i_cyc,
output [31:0] wb_i_adr,
input wb_i_ack,
input [31:0] wb_i_datr,
output wb_d_stb,
output wb_d_cyc,
output [31:0] wb_d_adr,
output wb_d_we,
output [3:0] wb_d_sel,
output [31:0] wb_d_datw,
input wb_d_ack,
input [31:0] wb_d_datr
);

// unsupported right now

assign an_ac_sync_ack = 0;
assign an_ac_stcx_complete = 0;
assign an_ac_stcx_pass = 0;
assign an_ac_reservation_vld = 0;

assign an_ac_icbi_ack = 0;
assign an_ac_icbi_ack_thread = 0;
assign an_ac_back_inv = 0;
assign an_ac_back_inv_addr = 0;
assign an_ac_back_inv_target = 0;
assign an_ac_back_inv_local = 0;
assign an_ac_back_inv_lbit = 0;
assign an_ac_back_inv_gs = 0;
assign an_ac_back_inv_ind = 0;
assign an_ac_back_inv_lpar_id = 0;

assign an_ac_req_st_gather = 0;
assign an_ac_req_spare_ctrl_a1 = 0;
assign an_ac_reld_l1_dump = 0;

wire [0:4] cmdseq_d;
reg [0:4] cmdseq_q;
wire [0:31+`REAL_IFAR_WIDTH] req_d;
reg [0:31+`REAL_IFAR_WIDTH] req_q;
wire [0:31+256] std_d;
reg [0:31+256] std_q;
reg std_q
reg req_tkn_q;
reg std_tkn_q;
wire [0:255] rld_d;
reg [0:255] rld_q;

wire req_ld_val;
wire req_st_val;
wire [64-`REAL_IFAR_WIDTH:63] req_adr;
wire [0:127] st_alg_data;
wire [0:127] st_mask;
wire rld_coming;
wire rld_valid;
wire rld_done;
wire [0:1] rld_qw;
wire idle;

//reg [0:127] mem[MEM_QW];

// todo
/*


input ac_an_req_pwr_token,
input ac_an_req,
input [64-`REAL_IFAR_WIDTH:63] ac_an_req_ra,
input [0:5] ac_an_req_ttype,
input [0:2] ac_an_req_thread,
input [0:4] ac_an_req_ld_core_tag,
input [0:2] ac_an_req_ld_xfr_len,
input ac_an_req_wimg_w,
input ac_an_req_wimg_i,
input ac_an_req_wimg_m,
input ac_an_req_wimg_g,
input ac_an_req_endian,
input [0:3] ac_an_req_user_defined,
input [0:3] ac_an_req_spare_ctrl_a0,
input ac_an_st_data_pwr_token,
input [0:31] ac_an_st_byte_enbl,
input [0:255] ac_an_st_data
*/

// FF
always @(posedge clk) begin

if (rst) begin

cmdseq_q = 'b11111;
req_q = 0;
std_q = 0;
req_tkn_q = 0;
std_tkn_q = 0;

end else begin

cmdseq_q = cmdseq_d;
req_q = req_d;
std_q = std_d;
req_tkn_q = ac_an_req_pwr_token;
std_tkn_q = ac_an_st_data_pwr_token;

end
end

// Mem

/*
always @(posedge clk) begin

if (do_store) begin
mem[req_adr] = st_rmw_data;
end
end
assign mem_dat = mem[mem_adr];

*/
assign mem_adr = req_adr >> 4;

// clkgate
assign req_d = req_tkn_q ? {ac_an_req,
ac_an_req_thread, // 0:2
ac_an_req_ttype, // 0:5
ac_an_req_ld_core_tag, // 0:2
ac_an_req_ra, //
ac_an_req_ld_xfr_len, // 0:2
ac_an_req_wimg_w,
ac_an_req_wimg_i,
ac_an_req_wimg_m,
ac_an_req_wimg_g,
ac_an_req_wimg_endian,
ac_an_req_user_defined, // 0:3
ac_an_req_spare_ctrl_a0 // 0:3
} : 0;
assign std_d = std_tkn_q ? {ac_an_st_byte_enbl, // 0:31
ac_an_st_data // 0:255
} : 0;

// request
assign req_ld_val = req_q[0] & (
(req_q[4:9] == 'b000000) | // if
(req_q[4:9] == 'b001000) | // ld
(req_q[4:9] == 'b100010) | // ditc
(req_q[4:9] == 'b001001) | // larx
(req_q[4:9] == 'b001011); // larx hint
);

assign req_st_val = req_q[0] & (
(req_q[4:9] == 'b100000) | // st
(req_q[4:9] == 'b101001) // stcx
);

assign req_tag = req_q[10:12];
assign req_adr = req_q[14+64-`REAL_IFAR_WIDTH:14+63];

// coming --- ---
// valid --- --- --- --- (and qw, crit)
// data --- --- --- ---

//tbl cmdseq
//n cmdseq_q cmdseq_d
//n | | rld_coming
//n | ld_req_val | |rld_valid
//n | |st_req_val | ||do_store
//n | ||ld_ready | |||rld_done
//n | |||st_ready | ||||
//n | ||||ld_ieq1 | |||| idle
//n | ||||| | |||| |
//n | ||||| | |||| |
//b 01234 ||||| 01234 |||| |
//t iiiii iiiii ooooo oooo o
//*----------------------------------------------------------------------
//* Idle ****************************************************************
//s 11111 ----- ----- 0000 1
//s 11111 00--- 11111 0000 - * ...zzz...
//s 11111 1---- 00001 0000 -
//s 11111 -1--- 10000 0000 -
//* Load ****************************************************************
//* 00001 --0-- 00001 0000 0
//* 00001 --1-- 00010 1000 0
//* Reload V0 *********************************************************** * val 0
//* 00010 ----1 00011 0100 0
//* 00011 ----0 00100 0100 0
//* Reload D0 (I=1) ****************************************************** * dat 0
//* 00011 ----- 11111 0001 0
//* Reload D0 ************************************************************ * val 1, dat 0
//* 00100 ----- 00101 1100 0
//* Reload D1 ************************************************************ * val 2, dat 1
//* 00101 ----- 00110 0100 0
//* Reload D2 ************************************************************ * val 3, dat 2
//* 00110 ----- 00111 0100 0
//* Reload D3 ************************************************************ * dat 3
//* 00111 ----- 11111 0001 0
//* Store ***************************************************************
//* 10000 ---0- 10000 0000 0
//* 10000 ---1- 11111 0010 0
//*----------------------------------------------------------------------
//tbl cmdseq

assign reld_qw = cmdseq_q[3:4];

// response
assign an_ac_reld_ecc_err = 0;
assign an_ac_reld_ecc_err_ue = 0;
assign an_ac_reld_ditc = 0;

// loads
assign an_ac_reld_data_coming = rld_coming;
assign an_ac_reld_data_vld = rld_valid;
assign an_ac_reld_core_tag = req_tag;
assign an_ac_reld_qw = reld_qw;
assign an_ac_reld_crit_qw = req_ieq1 | (req_adr[58:59] == reld_qw);
assign an_ac_reld_data = mem[{req_adr[64-`REAL_IFAR_WIDTH:59], reld_qw}];
assign an_ac_req_ld_pop = rld_done;

// stores
assign st_ready = 1; // random delay, or future functional stuff
assign an_ac_req_st_pop = st_ready;

assign st_mask = {
{8{std_q[0]}}, {8{std_q[1]}}, {8{std_q[2]}}, {8{std_q[3]}},
{8{std_q[4]}}, {8{std_q[5]}}, {8{std_q[6]}}, {8{std_q[7]}},
{8{std_q[8]}}, {8{std_q[9]}}, {8{std_q[10]}}, {8{std_q[11]}},
{8{std_q[12]}}, {8{std_q[13]}}, {8{std_q[14]}}, {8{std_q[15]}},
{8{std_q[16]}}, {8{std_q[17]}}, {8{std_q[18]}}, {8{std_q[19]}},
{8{std_q[20]}}, {8{std_q[21]}}, {8{std_q[22]}}, {8{std_q[23]}},
{8{std_q[24]}}, {8{std_q[25]}}, {8{std_q[26]}}, {8{std_q[27]}},
{8{std_q[28]}}, {8{std_q[29]}}, {8{std_q[30]}}, {8{std_q[31]}}
};

// BE, 16B max store
assign st_alg_data = req_q[32:32+127]; // no shift needed?

assign mem_wr_val = do_store;
assign mem_wr_dat = (mem_dat & st_mask) | (st_alg_data & ~st_mask);


//vtable cmdseq
//vtable cmdseq

@ -0,0 +1,380 @@
// © IBM Corp. 2022
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by
// the terms below; you may not use the files in this repository except in
// compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the
// License, the "Work" hereby includes implementations of the work of authorship
// in physical form.
//
// 2) Notwithstanding any terms to the contrary in the License, any licenses
// necessary for implementation of the Work that are available from OpenPOWER
// via the Power ISA End User License Agreement (EULA) are explicitly excluded
// hereunder, and may be obtained from OpenPOWER under the terms and conditions
// of the EULA.
//
// Unless required by applicable law or agreed to in writing, the reference design
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
// for the specific language governing permissions and limitations under the License.
//
// Additional rights, including the ability to physically implement a softcore that
// is compliant with the required sections of the Power ISA Specification, are
// available at no cost under the terms of the OpenPOWER Power ISA EULA, which can be
// obtained (along with the Power ISA) here: https://openpowerfoundation.org.

`include "tri_a2o.vh"

`timescale 1ns/1ps

module a2owb (

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,

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

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

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

// 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,
input [0:`THREADS-1] an_ac_sleep_en,
input [0:`THREADS-1] an_ac_ext_interrupt,
input [0:`THREADS-1] an_ac_crit_interrupt,
input [0:`THREADS-1] an_ac_perf_interrupt,
input [0:`THREADS-1] an_ac_hang_pulse,
input an_ac_tb_update_enable,
input an_ac_tb_update_pulse,
input [0:3] an_ac_chipid_dc,
input [0:7] an_ac_coreid,
output [0:`THREADS-1] ac_an_machine_check,
input an_ac_debug_stop,
output [0:`THREADS-1] ac_an_debug_trigger,
input [0:`THREADS-1] an_ac_uncond_dbg_event,
output [0:31] ac_an_debug_bus,
output ac_an_coretrace_first_valid,
output ac_an_coretrace_valid,
output [0:1] ac_an_coretrace_type,

output wb_i_stb,
output wb_i_cyc,
output [31:0] wb_i_adr,
input wb_i_ack,
input [31:0] wb_i_datr,
output wb_d_stb,
output wb_d_cyc,
output [31:0] wb_d_adr,
output wb_d_we,
output [3:0] wb_d_sel,
output [31:0] wb_d_datw,
input wb_d_ack,
input [31:0] wb_d_datr
);

c c0(
.nclk(nclk),
.scan_in(scan_in),
.scan_out(scan_out),

.an_ac_rtim_sl_thold_8(an_ac_rtim_sl_thold_8),
.an_ac_func_sl_thold_8(an_ac_func_sl_thold_8),
.an_ac_func_nsl_thold_8(an_ac_func_nsl_thold_8),
.an_ac_ary_nsl_thold_8(an_ac_ary_nsl_thold_8),
.an_ac_sg_8(an_ac_sg_8),
.an_ac_fce_8(an_ac_fce_8),
.an_ac_abst_scan_in(an_ac_abst_scan_in),

.an_ac_stcx_complete(an_ac_stcx_complete[0]),
.an_ac_stcx_pass(an_ac_stcx_pass[0]),
.an_ac_reservation_vld(an_ac_reservation_vld[0]),

.an_ac_icbi_ack(an_ac_icbi_ack),
.an_ac_icbi_ack_thread(an_ac_icbi_ack_thread),
.an_ac_sync_ack(an_ac_sync_ack[0]),

.an_ac_back_inv(an_ac_back_inv),
.an_ac_back_inv_addr(an_ac_back_inv_addr),
.an_ac_back_inv_target(an_ac_back_inv_target),
.an_ac_back_inv_local(an_ac_back_inv_local),
.an_ac_back_inv_lbit(an_ac_back_inv_lbit),
.an_ac_back_inv_gs(an_ac_back_inv_gs),
.an_ac_back_inv_ind(an_ac_back_inv_ind),
.an_ac_back_inv_lpar_id(an_ac_back_inv_lpar_id),
.ac_an_back_inv_reject(ac_an_back_inv_reject),
.ac_an_lpar_id(ac_an_lpar_id),

.an_ac_reld_data_vld(an_ac_reld_data_vld),
.an_ac_reld_core_tag(an_ac_reld_core_tag),
.an_ac_reld_data(an_ac_reld_data),
.an_ac_reld_qw(an_ac_reld_qw),
.an_ac_reld_ecc_err(an_ac_reld_ecc_err),
.an_ac_reld_ecc_err_ue(an_ac_reld_ecc_err_ue),
.an_ac_reld_data_coming(an_ac_reld_data_coming),
.an_ac_reld_ditc(an_ac_reld_ditc),
.an_ac_reld_crit_qw(an_ac_reld_crit_qw),
.an_ac_reld_l1_dump(an_ac_reld_l1_dump),
.an_ac_req_spare_ctrl_a1(an_ac_req_spare_ctrl_a1),

.an_ac_flh2l2_gate(an_ac_flh2l2_gate),
.an_ac_req_ld_pop(an_ac_req_ld_pop),
.an_ac_req_st_pop(an_ac_req_st_pop),
.an_ac_req_st_gather(an_ac_req_st_gather),
.an_ac_pm_fetch_halt(an_ac_pm_fetch_halt),

.an_ac_scom_sat_id(an_ac_scom_sat_id),
.an_ac_scom_dch(an_ac_scom_dch),
.an_ac_scom_cch(an_ac_scom_cch),
.ac_an_scom_dch(ac_an_scom_dch),
.ac_an_scom_cch(ac_an_scom_cch),

.ac_an_special_attn(ac_an_special_attn),
.ac_an_checkstop(ac_an_checkstop),
.ac_an_local_checkstop(ac_an_local_checkstop),
.ac_an_recov_err(ac_an_recov_err),
.ac_an_trace_error(ac_an_trace_error),
.ac_an_livelock_active(ac_an_livelock_active),
.an_ac_checkstop(an_ac_checkstop),
.an_ac_external_mchk(an_ac_external_mchk),

.ac_an_event_bus0(ac_an_event_bus0),
.ac_an_event_bus1(ac_an_event_bus1),

.an_ac_reset_1_complete(an_ac_reset_1_complete),
.an_ac_reset_2_complete(an_ac_reset_2_complete),
.an_ac_reset_3_complete(an_ac_reset_3_complete),
.an_ac_reset_wd_complete(an_ac_reset_wd_complete),

.ac_an_pm_thread_running(ac_an_pm_thread_running),
.an_ac_pm_thread_stop(an_ac_pm_thread_stop),
.ac_an_power_managed(ac_an_power_managed),
.ac_an_rvwinkle_mode(ac_an_rvwinkle_mode),

.an_ac_gsd_test_enable_dc(an_ac_gsd_test_enable_dc),
.an_ac_gsd_test_acmode_dc(an_ac_gsd_test_acmode_dc),
.an_ac_ccflush_dc(an_ac_ccflush_dc),
.an_ac_ccenable_dc(an_ac_ccenable_dc),
.an_ac_lbist_en_dc(an_ac_lbist_en_dc),
.an_ac_lbist_ip_dc(an_ac_lbist_ip_dc),
.an_ac_lbist_ac_mode_dc(an_ac_lbist_ac_mode_dc),
.an_ac_scan_diag_dc(an_ac_scan_diag_dc),
.an_ac_scan_dis_dc_b(an_ac_scan_dis_dc_b),
.an_ac_scan_type_dc(an_ac_scan_type_dc),
.ac_an_reset_1_request(ac_an_reset_1_request),
.ac_an_reset_2_request(ac_an_reset_2_request),
.ac_an_reset_3_request(ac_an_reset_3_request),
.ac_an_reset_wd_request(ac_an_reset_wd_request),
.an_ac_lbist_ary_wrt_thru_dc(an_ac_lbist_ary_wrt_thru_dc),
.an_ac_sleep_en(an_ac_sleep_en),
.an_ac_ext_interrupt(an_ac_ext_interrupt),
.an_ac_crit_interrupt(an_ac_crit_interrupt),
.an_ac_perf_interrupt(an_ac_perf_interrupt),
.an_ac_hang_pulse(an_ac_hang_pulse),
.an_ac_tb_update_enable(an_ac_tb_update_enable),
.an_ac_tb_update_pulse(an_ac_tb_update_pulse),
.an_ac_chipid_dc(an_ac_chipid_dc),
.an_ac_coreid(an_ac_coreid),
.ac_an_machine_check(ac_an_machine_check),
.an_ac_debug_stop(an_ac_debug_stop),
.ac_an_debug_trigger(ac_an_debug_trigger),
.an_ac_uncond_dbg_event(an_ac_uncond_dbg_event),

.ac_an_req_pwr_token(ac_an_req_pwr_token),
.ac_an_req(ac_an_req),
.ac_an_req_ra(ac_an_req_ra),
.ac_an_req_ttype(ac_an_req_ttype),
.ac_an_req_thread(ac_an_req_thread),
.ac_an_req_wimg_w(ac_an_req_wimg_w),
.ac_an_req_wimg_i(ac_an_req_wimg_i),
.ac_an_req_wimg_m(ac_an_req_wimg_m),
.ac_an_req_wimg_g(ac_an_req_wimg_g),
.ac_an_req_user_defined(ac_an_req_user_defined),
.ac_an_req_spare_ctrl_a0(ac_an_req_spare_ctrl_a0),
.ac_an_req_ld_core_tag(ac_an_req_ld_core_tag),
.ac_an_req_ld_xfr_len(ac_an_req_ld_xfr_len),
.ac_an_st_byte_enbl(ac_an_st_byte_enbl),
.ac_an_st_data(ac_an_st_data),
.ac_an_req_endian(ac_an_req_endian),
.ac_an_st_data_pwr_token(ac_an_st_data_pwr_token)
);

a2l2wb n0(
.clk(clk_1x),
.rst(rst),

// request
.ac_an_req_pwr_token(ac_an_req_pwr_token),
.ac_an_req(ac_an_req),
.ac_an_req_ra(ac_an_req_ra),
.ac_an_req_ttype(ac_an_req_ttype),
.ac_an_req_thread(ac_an_req_thread),
.ac_an_req_ld_core_tag(ac_an_req_ld_core_tag),
.ac_an_req_ld_xfr_len(ac_an_req_ld_xfr_len),
.ac_an_st_data_pwr_token(ac_an_st_data_pwr_token)
.ac_an_st_byte_enbl(ac_an_st_byte_enbl),
.ac_an_st_data(ac_an_st_data),
.ac_an_req_wimg_w(ac_an_req_wimg_w),
.ac_an_req_wimg_i(ac_an_req_wimg_i),
.ac_an_req_wimg_m(ac_an_req_wimg_m),
.ac_an_req_wimg_g(ac_an_req_wimg_g),
.ac_an_req_endian(ac_an_req_endian),
.ac_an_req_user_defined(ac_an_req_user_defined),
.ac_an_req_spare_ctrl_a0(ac_an_req_spare_ctrl_a0),

// reload
.an_ac_reld_data_vld(an_ac_reld_data_vld),
.an_ac_reld_core_tag(an_ac_reld_core_tag),
.an_ac_reld_data(an_ac_reld_data),
.an_ac_reld_qw(an_ac_reld_qw),
.an_ac_reld_ecc_err(an_ac_reld_ecc_err),
.an_ac_reld_ecc_err_ue(an_ac_reld_ecc_err_ue),
.an_ac_reld_data_coming(an_ac_reld_data_coming),
.an_ac_reld_ditc(an_ac_reld_ditc),
.an_ac_reld_crit_qw(an_ac_reld_crit_qw),
.an_ac_reld_l1_dump(an_ac_reld_l1_dump),
.an_ac_req_spare_ctrl_a1(an_ac_req_spare_ctrl_a1),

// larx/stcx
.an_ac_stcx_complete(an_ac_stcx_complete),
.an_ac_stcx_pass(an_ac_stcx_pass),
.an_ac_reservation_vld(an_ac_reservation_vld),

// icbi
.an_ac_icbi_ack(an_ac_icbi_ack),
.an_ac_icbi_ack_thread(an_ac_icbi_ack_thread),

// back invalidate
.an_ac_back_inv(an_ac_back_inv),
.an_ac_back_inv_addr(an_ac_back_inv_addr),
.an_ac_back_inv_target(an_ac_back_inv_target),
.an_ac_back_inv_local(an_ac_back_inv_local),
.an_ac_back_inv_lbit(an_ac_back_inv_lbit),
.an_ac_back_inv_gs(an_ac_back_inv_gs),
.an_ac_back_inv_ind(an_ac_back_inv_ind),
.an_ac_back_inv_lpar_id(an_ac_back_inv_lpar_id),
.ac_an_back_inv_reject(ac_an_back_inv_reject),
.ac_an_lpar_id(ac_an_lpar_id),

// credits
.an_ac_req_ld_pop(an_ac_req_ld_pop),
.an_ac_req_st_pop(an_ac_req_st_pop),
.an_ac_req_st_gather(an_ac_req_st_gather),
.an_ac_sync_ack(an_ac_sync_ack),
.an_ac_pm_fetch_halt(an_ac_pm_fetch_halt),

// misc
.an_ac_flh2l2_gate(an_ac_flh2l2_gate),
.an_ac_reset_1_complete(an_ac_reset_1_complete),
.an_ac_reset_2_complete(an_ac_reset_2_complete),
.an_ac_reset_3_complete(an_ac_reset_3_complete),
.an_ac_reset_wd_complete(an_ac_reset_wd_complete),
.an_ac_sleep_en(an_ac_sleep_en),
.an_ac_ext_interrupt(an_ac_ext_interrupt),
.an_ac_crit_interrupt(an_ac_crit_interrupt),
.an_ac_perf_interrupt(an_ac_perf_interrupt),
.an_ac_hang_pulse(an_ac_hang_pulse),
.an_ac_tb_update_enable(an_ac_tb_update_enable),
.an_ac_tb_update_pulse(an_ac_tb_update_pulse),
.an_ac_chipid_dc(an_ac_chipid_dc),
.an_ac_coreid(an_ac_coreid),
.an_ac_debug_stop(an_ac_debug_stop),
.ac_an_debug_trigger(ac_an_debug_trigger),
.an_ac_uncond_dbg_event(an_ac_uncond_dbg_event),

// scom
.an_ac_scom_sat_id(an_ac_scom_sat_id),
.an_ac_scom_dch(an_ac_scom_dch),
.an_ac_scom_cch(an_ac_scom_cch),
.ac_an_scom_dch(ac_an_scom_dch),
.ac_an_scom_cch(ac_an_scom_cch),

// errors
.ac_an_special_attn(ac_an_special_attn),
.ac_an_checkstop(ac_an_checkstop),
.ac_an_local_checkstop(ac_an_local_checkstop),
.ac_an_recov_err(ac_an_recov_err),
.ac_an_trace_error(ac_an_trace_error),
.ac_an_livelock_active(ac_an_livelock_active),
.an_ac_checkstop(an_ac_checkstop),
.an_ac_external_mchk(an_ac_external_mchk),
.ac_an_machine_check(ac_an_machine_check),

// perfmon
.ac_an_event_bus0(ac_an_event_bus0),
.ac_an_event_bus1(ac_an_event_bus1),

// power
.ac_an_pm_thread_running(ac_an_pm_thread_running),
.an_ac_pm_thread_stop(an_ac_pm_thread_stop),
.ac_an_power_managed(ac_an_power_managed),
.ac_an_rvwinkle_mode(ac_an_rvwinkle_mode),
);

initial begin
$dumpfile ("a2owb.vcd");
// you can do it by levels and also by module so could prune down
$dumpvars;
// need to explicitly specify arrays for icarus
// guess not: $dumpvars cannot dump a vpiMemory
//$dumpvars(0, c0.iuq0.iuq_slice_top0.slice0.iuq_ibuf0.buffer_data_q);
#1;
end

wire clk_1x, clk_2x, clk_4x, rst;

assign clk_1x = nclk[0];
assign clk_2x = nclk[2];
assign clk_4x = nclk[3];
assign rst = nclk[1];

endmodule
Loading…
Cancel
Save