start a2l2wb
parent
bc0e3204b7
commit
0dcb681aad
@ -0,0 +1,33 @@
|
|||||||
|
# a2o tb-node
|
||||||
|
|
||||||
|
SIM_BUILD ?= build_node
|
||||||
|
SIM ?= icarus
|
||||||
|
|
||||||
|
# icarus
|
||||||
|
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 -y$(VERILOG_ROOT)/a2node
|
||||||
|
|
||||||
|
# other options
|
||||||
|
|
||||||
|
# rtl
|
||||||
|
TOPLEVEL_LANG = verilog
|
||||||
|
# top-level to enable trace, etc.
|
||||||
|
VERILOG_SOURCES = ./cocotb_icarus_node.v
|
||||||
|
TOPLEVEL = cocotb_icarus_node
|
||||||
|
|
||||||
|
# python test
|
||||||
|
MODULE = tb_node
|
||||||
|
|
||||||
|
# cocotb make rules
|
||||||
|
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||||
|
|
||||||
|
build: clean sim fst
|
||||||
|
|
||||||
|
run: sim fst
|
||||||
|
|
||||||
|
vcd: sim
|
||||||
|
|
||||||
|
fst:
|
||||||
|
vcd2fst a2onode.vcd a2onode.fst
|
||||||
|
rm a2onode.vcd
|
@ -0,0 +1,231 @@
|
|||||||
|
|
||||||
|
`include "tri_a2o.vh"
|
||||||
|
|
||||||
|
`timescale 1ns/1ps
|
||||||
|
|
||||||
|
// might add some sim-only lines to enable clks, etc.
|
||||||
|
|
||||||
|
module cocotb_icarus_node (
|
||||||
|
|
||||||
|
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,
|
||||||
|
input [0:`THREADS-1] an_ac_external_mchk,
|
||||||
|
output an_ac_checkstop,
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
input an_ac_flh2l2_gate,
|
||||||
|
|
||||||
|
// 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 [0:31] mem_adr,
|
||||||
|
input [0:127] mem_dat,
|
||||||
|
output mem_wr_val,
|
||||||
|
output [0:15] mem_wr_be,
|
||||||
|
output [0:127] mem_wr_dat,
|
||||||
|
|
||||||
|
output wb_stb,
|
||||||
|
output wb_cyc,
|
||||||
|
output [31:0] wb_adr,
|
||||||
|
output wb_we,
|
||||||
|
output [3:0] wb_sel,
|
||||||
|
output [31:0] wb_datw,
|
||||||
|
input wb_ack,
|
||||||
|
input [31:0] wb_datr
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
a2owb c0 (
|
||||||
|
.nclk(nclk),
|
||||||
|
.scan_in(scan_in),
|
||||||
|
.scan_out(scan_out),
|
||||||
|
|
||||||
|
// Pervasive clock control
|
||||||
|
.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),
|
||||||
|
|
||||||
|
//SCOM Satellite
|
||||||
|
.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),
|
||||||
|
|
||||||
|
// FIR and Error Signals
|
||||||
|
.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),
|
||||||
|
|
||||||
|
// Perfmon Event Bus
|
||||||
|
.ac_an_event_bus0(ac_an_event_bus0),
|
||||||
|
.ac_an_event_bus1(ac_an_event_bus1),
|
||||||
|
|
||||||
|
// Reset related
|
||||||
|
.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),
|
||||||
|
|
||||||
|
// Power Management
|
||||||
|
.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_pm_fetch_halt(an_ac_pm_fetch_halt),
|
||||||
|
|
||||||
|
// Clock, Test, and LCB Controls
|
||||||
|
.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),
|
||||||
|
|
||||||
|
//Thold input to clock control macro
|
||||||
|
.an_ac_scan_type_dc(an_ac_scan_type_dc),
|
||||||
|
|
||||||
|
// Pervasive
|
||||||
|
.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),
|
||||||
|
|
||||||
|
// direct-attach mem
|
||||||
|
.mem_adr(mem_adr),
|
||||||
|
.mem_dat(mem_dat),
|
||||||
|
.mem_wr_val(mem_wr_val),
|
||||||
|
.mem_wr_be(mem_wr_be),
|
||||||
|
.mem_wr_dat(mem_wr_dat),
|
||||||
|
|
||||||
|
// wishbone
|
||||||
|
.wb_stb(wb_stb),
|
||||||
|
.wb_cyc(wb_cyc),
|
||||||
|
.wb_adr(wb_adr),
|
||||||
|
.wb_we(wb_we),
|
||||||
|
.wb_ack(wb_ack),
|
||||||
|
.wb_sel(wb_sel),
|
||||||
|
.wb_datr(wb_datr),
|
||||||
|
.wb_datw(wb_datw)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile ("a2onode.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
|
||||||
|
|
||||||
|
// see if coco lets me risingedge() these
|
||||||
|
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
|
@ -0,0 +1,5 @@
|
|||||||
|
# Cocotb Sim
|
||||||
|
|
||||||
|
```
|
||||||
|
make -f Makefile.node build |& grep -v Anac
|
||||||
|
```
|
@ -0,0 +1,326 @@
|
|||||||
|
# a2o test tb
|
||||||
|
# a2owb with external 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_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 node, etc. """
|
||||||
|
|
||||||
|
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.'
|
||||||
|
|
||||||
|
# 16B interface
|
||||||
|
async def memory(dut, sim):
|
||||||
|
"""Handle external memory interface (BE)"""
|
||||||
|
|
||||||
|
me = 'Memory'
|
||||||
|
ok = True
|
||||||
|
sim.msg(f'{me}: started.')
|
||||||
|
|
||||||
|
while ok:
|
||||||
|
await RisingEdge(dut.clk_1x)
|
||||||
|
|
||||||
|
try:
|
||||||
|
addr = dut.mem_adr.value.integer
|
||||||
|
w0 = sim.mem.read(addr)
|
||||||
|
w1 = sim.mem.read(addr+4)
|
||||||
|
w2 = sim.mem.read(addr+8)
|
||||||
|
w3 = sim.mem.read(addr+12)
|
||||||
|
v = cocotb.binary.BinaryValue()
|
||||||
|
v.assign(f'{w0:0>32b}{w1:0>32b}{w2:0>32b}{w3:0>32b}')
|
||||||
|
dut.mem_dat.value = v.value
|
||||||
|
except Exception as e:
|
||||||
|
#print(e)
|
||||||
|
dut.mem_dat.value = 0
|
||||||
|
|
||||||
|
if dut.mem_wr_val.value:
|
||||||
|
addr = dut.mem_adr.value.integer
|
||||||
|
dat = hex(dut.mem_wr_dat, 32)
|
||||||
|
be = f'{dut.mem_wr_be.value.integer:016b}'
|
||||||
|
for i in range(4):
|
||||||
|
sim.mem.write(addr, dat[i*8:i*8+8], be[i*4:i*4+4])
|
||||||
|
addr += 4
|
||||||
|
|
||||||
|
sim.msg(f'{me}: ended.')
|
||||||
|
|
||||||
|
async def checker(dut, sim):
|
||||||
|
"""Watch for error indicators"""
|
||||||
|
|
||||||
|
me = 'Node Checker'
|
||||||
|
ok = True
|
||||||
|
sim.msg(f'{me}: started.')
|
||||||
|
|
||||||
|
# errors
|
||||||
|
nodeCheckstop = dut.an_ac_checkstop
|
||||||
|
errors = [
|
||||||
|
{'name': 'A2Node Checkstop', 'sig': nodeCheckstop}
|
||||||
|
]
|
||||||
|
|
||||||
|
while ok:
|
||||||
|
|
||||||
|
await RisingEdge(dut.clk_1x)
|
||||||
|
|
||||||
|
if not sim.resetDone:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for i in range(len(errors)):
|
||||||
|
assert errors[i]['sig'].value == 0, f'{me} Error: {errors[i]["name"]}'
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------------------------
|
||||||
|
# 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_node(dut):
|
||||||
|
"""A Vulgar Display of OpenPower"""
|
||||||
|
|
||||||
|
sim = Sim(dut)
|
||||||
|
sim.mem = Memory(sim)
|
||||||
|
sim.maxCycles = 20000
|
||||||
|
|
||||||
|
'''
|
||||||
|
# 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, dut.c0.c0)
|
||||||
|
sim.a2o.traceFacUpdates = True
|
||||||
|
sim.a2o.stopOnLoop = 50
|
||||||
|
sim.a2o.iarPass = 0x7F0
|
||||||
|
sim.a2o.iarFail = 0x7F4
|
||||||
|
|
||||||
|
await cocotb.start(A2O.driver(dut, sim))
|
||||||
|
|
||||||
|
await cocotb.start(memory(dut, sim))
|
||||||
|
#await cocotb.start(A2L2.driver(dut, sim))
|
||||||
|
await cocotb.start(A2L2.checker(dut, sim))
|
||||||
|
await cocotb.start(A2L2.monitor(dut, sim, watchTrans=True))
|
||||||
|
|
||||||
|
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
|
||||||
|
# original fpga design needed 4 cred, no fwd (set in logic currently)
|
||||||
|
sim.a2o.config.creditsLd = 1
|
||||||
|
sim.a2o.config.creditsSt = 1
|
||||||
|
sim.a2o.config.creditsLdStSingle = True # need for node right now
|
||||||
|
#sim.a2o.lsDataForward = 0 # disable=1
|
||||||
|
#sim.a2o.cpcr4_sq_cnt = 0 # default=6
|
||||||
|
|
||||||
|
await A2O.config(dut, sim)
|
||||||
|
|
||||||
|
await cocotb.start(A2O.checker(dut, sim))
|
||||||
|
await cocotb.start(A2O.monitor(dut, sim))
|
||||||
|
|
||||||
|
await cocotb.start(checker(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,683 @@
|
|||||||
|
48000400
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
7CBE6AA6
|
||||||
|
2C250000
|
||||||
|
408200E0
|
||||||
|
3C608C00
|
||||||
|
3800001F
|
||||||
|
38400015
|
||||||
|
38800000
|
||||||
|
3900023F
|
||||||
|
7C7CFBA6
|
||||||
|
7C4011A6
|
||||||
|
7C8009A6
|
||||||
|
7D0001A6
|
||||||
|
4C00012C
|
||||||
|
39400000
|
||||||
|
654A0000
|
||||||
|
614A003F
|
||||||
|
3800001E
|
||||||
|
38800000
|
||||||
|
64840001
|
||||||
|
60840000
|
||||||
|
39000000
|
||||||
|
65080001
|
||||||
|
61080000
|
||||||
|
6108023F
|
||||||
|
7D4011A6
|
||||||
|
7C8009A6
|
||||||
|
7D0001A6
|
||||||
|
4C00012C
|
||||||
|
3C608800
|
||||||
|
3800000F
|
||||||
|
3840003F
|
||||||
|
38800000
|
||||||
|
3900023F
|
||||||
|
7C7CFBA6
|
||||||
|
7C4011A6
|
||||||
|
7C8009A6
|
||||||
|
7D0001A6
|
||||||
|
4C00012C
|
||||||
|
3800000D
|
||||||
|
38800000
|
||||||
|
64840001
|
||||||
|
60840000
|
||||||
|
39000000
|
||||||
|
65080001
|
||||||
|
61080000
|
||||||
|
6108023F
|
||||||
|
7D4011A6
|
||||||
|
7C8009A6
|
||||||
|
7D0001A6
|
||||||
|
4C00012C
|
||||||
|
48000004
|
||||||
|
39400000
|
||||||
|
654A8002
|
||||||
|
614AB000
|
||||||
|
7D400124
|
||||||
|
4C00012C
|
||||||
|
802008F0
|
||||||
|
48000020
|
||||||
|
39400000
|
||||||
|
654A8002
|
||||||
|
614AB000
|
||||||
|
7D400124
|
||||||
|
4C00012C
|
||||||
|
802008F4
|
||||||
|
48000004
|
||||||
|
3C600000
|
||||||
|
60630900
|
||||||
|
7C6903A6
|
||||||
|
7C7E6AA6
|
||||||
|
4E800421
|
||||||
|
480002E4
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
48000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
0001FFF8
|
||||||
|
0000FFF8
|
||||||
|
60000000
|
||||||
|
60000000
|
||||||
|
9421FFC0
|
||||||
|
90610038
|
||||||
|
3D200001
|
||||||
|
81290000
|
||||||
|
9121000C
|
||||||
|
81210038
|
||||||
|
2C090000
|
||||||
|
4182000C
|
||||||
|
3920FFFF
|
||||||
|
4800017C
|
||||||
|
3D200000
|
||||||
|
81290AAC
|
||||||
|
91210008
|
||||||
|
48000028
|
||||||
|
8121000C
|
||||||
|
39490004
|
||||||
|
9141000C
|
||||||
|
81410008
|
||||||
|
814A0000
|
||||||
|
91490000
|
||||||
|
81210008
|
||||||
|
39290004
|
||||||
|
91210008
|
||||||
|
3D200000
|
||||||
|
81290AAC
|
||||||
|
81410008
|
||||||
|
7C0A4840
|
||||||
|
4180FFCC
|
||||||
|
3D200001
|
||||||
|
81290000
|
||||||
|
91210008
|
||||||
|
48000020
|
||||||
|
3D200001
|
||||||
|
81290000
|
||||||
|
39400000
|
||||||
|
91490000
|
||||||
|
81210008
|
||||||
|
39290004
|
||||||
|
91210008
|
||||||
|
3D200001
|
||||||
|
81290000
|
||||||
|
81410008
|
||||||
|
7C0A4840
|
||||||
|
4180FFD4
|
||||||
|
3D200300
|
||||||
|
91210030
|
||||||
|
81210030
|
||||||
|
3C800000
|
||||||
|
60840009
|
||||||
|
7C934BA6
|
||||||
|
60000000
|
||||||
|
39200000
|
||||||
|
9121002C
|
||||||
|
8121002C
|
||||||
|
3C800000
|
||||||
|
60840009
|
||||||
|
7C9603A6
|
||||||
|
60000000
|
||||||
|
39200000
|
||||||
|
91210028
|
||||||
|
81210028
|
||||||
|
3C800000
|
||||||
|
60840009
|
||||||
|
7C9D43A6
|
||||||
|
60000000
|
||||||
|
39200000
|
||||||
|
91210024
|
||||||
|
81210024
|
||||||
|
3C800000
|
||||||
|
60840009
|
||||||
|
7C9C43A6
|
||||||
|
60000000
|
||||||
|
3D20FE00
|
||||||
|
91210020
|
||||||
|
81210020
|
||||||
|
3C800000
|
||||||
|
60840009
|
||||||
|
7C9053A6
|
||||||
|
60000000
|
||||||
|
7D36FAA6
|
||||||
|
9121001C
|
||||||
|
8121001C
|
||||||
|
552905AC
|
||||||
|
91210018
|
||||||
|
81210018
|
||||||
|
3C800000
|
||||||
|
60840009
|
||||||
|
7C96FBA6
|
||||||
|
60000000
|
||||||
|
39200000
|
||||||
|
91210014
|
||||||
|
81210014
|
||||||
|
3C800000
|
||||||
|
60840009
|
||||||
|
7C9053A6
|
||||||
|
60000000
|
||||||
|
39200000
|
||||||
|
91210010
|
||||||
|
81210010
|
||||||
|
3C800000
|
||||||
|
60840009
|
||||||
|
7C9453A6
|
||||||
|
60000000
|
||||||
|
39200000
|
||||||
|
7D234B78
|
||||||
|
38210040
|
||||||
|
4E800020
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,427 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# Parse table comments and create equations.
|
||||||
|
|
||||||
|
from optparse import OptionParser
|
||||||
|
import re
|
||||||
|
from shutil import copyfile
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------------------------------------
|
||||||
|
# Initialize
|
||||||
|
|
||||||
|
TYPE_INPUT = 0
|
||||||
|
TYPE_OUTPUT = 1
|
||||||
|
TYPE_SKIP = 99
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
tableMatches = []
|
||||||
|
tableNames = []
|
||||||
|
tableLines = []
|
||||||
|
tables = {}
|
||||||
|
|
||||||
|
failOnError = True
|
||||||
|
inFile = 'test.vhdl'
|
||||||
|
outFileExt = 'vtable'
|
||||||
|
overwrite = True
|
||||||
|
backupExt = 'orig'
|
||||||
|
backup = True
|
||||||
|
noisy = False
|
||||||
|
quiet = False
|
||||||
|
verilog = False
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------------------------------------
|
||||||
|
# Handle command line
|
||||||
|
|
||||||
|
usage = 'vtable [options] inFile'
|
||||||
|
|
||||||
|
parser = OptionParser(usage)
|
||||||
|
parser.add_option('-f', '--outfile', dest='outFile', help='output file, default=[inFile]' + outFileExt)
|
||||||
|
parser.add_option('-o', '--overwrite', dest='overwrite', help='overwrite inFile, default=' + str(overwrite))
|
||||||
|
parser.add_option('-b', '--backup', dest='backup', help='backup original file, default=' + str(backup))
|
||||||
|
parser.add_option('-q', '--quiet', dest='quiet', action='store_true', help='quiet messages, default=' + str(quiet))
|
||||||
|
parser.add_option('-n', '--noisy', dest='noisy', action='store_true', help='noisy messages, default=' + str(noisy))
|
||||||
|
parser.add_option('-V', '--verilog', dest='verilog', action='store_true', help='source is verilog, default=' + str(verilog))
|
||||||
|
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
|
||||||
|
if len(args) != 1:
|
||||||
|
parser.error(usage)
|
||||||
|
quit(-1)
|
||||||
|
else:
|
||||||
|
inFile = args[0]
|
||||||
|
|
||||||
|
if options.overwrite == '0':
|
||||||
|
overwrite = False
|
||||||
|
elif options.overwrite == '1':
|
||||||
|
overwrite == True
|
||||||
|
if options.outFile is not None:
|
||||||
|
parser.error('Can\'t specify outfile and overrite!')
|
||||||
|
quit(-1)
|
||||||
|
elif options.overwrite is not None:
|
||||||
|
parser.error('overwrite: 0|1')
|
||||||
|
quit(-1)
|
||||||
|
|
||||||
|
if options.quiet is not None:
|
||||||
|
quiet = True
|
||||||
|
|
||||||
|
if options.noisy is not None:
|
||||||
|
noisy = True
|
||||||
|
|
||||||
|
if options.verilog is not None:
|
||||||
|
verilog = True
|
||||||
|
|
||||||
|
if options.backup == '0':
|
||||||
|
backup = False
|
||||||
|
elif options.backup == '1':
|
||||||
|
backup == True
|
||||||
|
elif options.backup is not None:
|
||||||
|
parser.error('backup: 0|1')
|
||||||
|
quit(-1)
|
||||||
|
|
||||||
|
if options.outFile is not None:
|
||||||
|
outFile = options.outFile
|
||||||
|
elif overwrite:
|
||||||
|
outFile = inFile
|
||||||
|
else:
|
||||||
|
outFile = inFile + '.' + outFileExt
|
||||||
|
|
||||||
|
backupFile = inFile + '.' + backupExt
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------------------------------------
|
||||||
|
# Objects
|
||||||
|
|
||||||
|
class Signal:
|
||||||
|
|
||||||
|
def __init__(self, name, type):
|
||||||
|
self.name = name;
|
||||||
|
self.type = type;
|
||||||
|
|
||||||
|
class Table:
|
||||||
|
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
self.source = []
|
||||||
|
self.signals = {}
|
||||||
|
self.signalsByCol = {}
|
||||||
|
self.typesByCol = {}
|
||||||
|
self.specs = [] # list of specsByCol
|
||||||
|
self.equations = []
|
||||||
|
self.added = False
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
# check that all signals have a good type
|
||||||
|
for col in self.signalsByCol:
|
||||||
|
if col not in self.typesByCol:
|
||||||
|
error('Table ' + self.name + ': no signal type for ' + self.signalsByCol[col])
|
||||||
|
elif self.typesByCol[col] == None:
|
||||||
|
error('Table ' + self.name + ': bad signal type (' + str(self.typesByCol[col]) + ') for ' + str(self.signalsByCol[col]))
|
||||||
|
|
||||||
|
def makeRTL(self, form=None):
|
||||||
|
outputsByCol = {}
|
||||||
|
|
||||||
|
|
||||||
|
#for col,type in self.typesByCol.items():
|
||||||
|
for col in sorted(self.typesByCol):
|
||||||
|
type = self.typesByCol[col]
|
||||||
|
if type == TYPE_OUTPUT:
|
||||||
|
if col in self.signalsByCol:
|
||||||
|
outputsByCol[col] = self.signalsByCol[col]
|
||||||
|
else:
|
||||||
|
print(self.signalsByCol)
|
||||||
|
print(self.typesByCol)
|
||||||
|
error('Table ' + self.name + ': output is specified in col ' + str(col) + ' but no signal exists')
|
||||||
|
|
||||||
|
#for sigCol,sig in outputsByCol.items():
|
||||||
|
for sigCol in sorted(outputsByCol):
|
||||||
|
sig = outputsByCol[sigCol]
|
||||||
|
if not verilog:
|
||||||
|
line = sig + ' <= '
|
||||||
|
else:
|
||||||
|
line = 'assign ' + sig + ' = '
|
||||||
|
nonzero = False
|
||||||
|
for specsByCol in self.specs:
|
||||||
|
terms = []
|
||||||
|
if sigCol not in specsByCol:
|
||||||
|
#error('* Output ' + sig + ' has no specified value for column ' + str(col))
|
||||||
|
1 # no error, can be dontcare
|
||||||
|
elif specsByCol[sigCol] == '1':
|
||||||
|
for col,val in specsByCol.items():
|
||||||
|
if col not in self.typesByCol:
|
||||||
|
if noisy:
|
||||||
|
error('Table ' + self.name +': unexpected value in spec column ' + str(col) + ' (' + str(val) + ') - no associated signal', False) #wtf UNTIL CAN HANDLE COMMENTS AT END!!!!!!!!!!!!!!!!!!!
|
||||||
|
elif self.typesByCol[col] == TYPE_INPUT:
|
||||||
|
if val == '0':
|
||||||
|
terms.append(opNot + self.signalsByCol[col])
|
||||||
|
if nonzero and len(terms) == 1:
|
||||||
|
line = line + ') ' + opOr + '\n (';
|
||||||
|
elif len(terms) == 1:
|
||||||
|
line = line + '\n ('
|
||||||
|
nonzero = True
|
||||||
|
elif val == '1':
|
||||||
|
terms.append(self.signalsByCol[col])
|
||||||
|
if nonzero and len(terms) == 1:
|
||||||
|
line = line + ') ' + opOr + '\n (';
|
||||||
|
elif len(terms) == 1:
|
||||||
|
line = line + '\n ('
|
||||||
|
nonzero = True
|
||||||
|
else:
|
||||||
|
error('Table ' + self.name +': unexpected value in spec column ' + str(col) + ' (' + str(val) + ')')
|
||||||
|
if len(terms) > 0:
|
||||||
|
line = line + (' ' + opAnd + ' ').join(terms)
|
||||||
|
if not nonzero:
|
||||||
|
line = line + zero + ";";
|
||||||
|
else:
|
||||||
|
line = line + ');'
|
||||||
|
self.equations.append(line)
|
||||||
|
|
||||||
|
return self.equations
|
||||||
|
|
||||||
|
def printv(self):
|
||||||
|
self.makeRTL()
|
||||||
|
print('\n'.join(self.equations))
|
||||||
|
|
||||||
|
def printinfo(self):
|
||||||
|
print('Table: ' + self.name)
|
||||||
|
print
|
||||||
|
for l in self.source:
|
||||||
|
print(l)
|
||||||
|
print
|
||||||
|
print('Signals by column:')
|
||||||
|
for col in sorted(self.signalsByCol):
|
||||||
|
print('{0:>3}. {1:} ({2:}) '.format(col, self.signalsByCol[col], 'in' if self.typesByCol[col] == TYPE_INPUT else 'out'))
|
||||||
|
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------------------------------------
|
||||||
|
# Functions
|
||||||
|
|
||||||
|
def error(msg, quitOverride=None):
|
||||||
|
print('*** ' + msg)
|
||||||
|
if quitOverride == False:
|
||||||
|
1
|
||||||
|
elif (quitOverride == None) or failOnError:
|
||||||
|
quit(-10)
|
||||||
|
elif quitOverride:
|
||||||
|
quit(-10)
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------------------------------------
|
||||||
|
# Do something
|
||||||
|
|
||||||
|
if not verilog:
|
||||||
|
openBracket = '('
|
||||||
|
closeBracket = ')'
|
||||||
|
opAnd = 'and'
|
||||||
|
opOr = 'or'
|
||||||
|
opNot = 'not '
|
||||||
|
zero = "'0'"
|
||||||
|
tablePattern = re.compile(r'^\s*?--tbl(?:\s+([^\s]+).*$|\s*$)')
|
||||||
|
tableGenPattern = re.compile(r'^\s*?--vtable(?:\s+([^\s]+).*$)')
|
||||||
|
commentPattern = re.compile(r'^\s*?(--.*$|\s*$)')
|
||||||
|
tableLinePattern = re.compile(r'^.*?--(.*)')
|
||||||
|
namePattern = re.compile(r'([a-zA-z\d_\(\)\.\[\]]+)')
|
||||||
|
else:
|
||||||
|
openBracket = '['
|
||||||
|
closeBracket = ']'
|
||||||
|
opAnd = '&'
|
||||||
|
opOr = '+'
|
||||||
|
opNot = '~'
|
||||||
|
zero = "'b0"
|
||||||
|
tablePattern = re.compile(r'^\s*?\/\/tbl(?:\s+([^\s]+).*$|\s*$)')
|
||||||
|
tableGenPattern = re.compile(r'^\s*?\/\/vtable(?:\s+([^\s]+).*$)')
|
||||||
|
commentPattern = re.compile(r'^\s*?(\/\/.*$|\s*$)')
|
||||||
|
tableLinePattern = re.compile(r'^.*?\/\/(.*)')
|
||||||
|
namePattern = re.compile(r'([a-zA-z\d_\(\)\.\[\]]+)')
|
||||||
|
|
||||||
|
# find the lines with table spec
|
||||||
|
try:
|
||||||
|
inf = open(inFile)
|
||||||
|
for i, line in enumerate(inf):
|
||||||
|
lines.append(line.strip('\n'))
|
||||||
|
for match in re.finditer(tablePattern, line):
|
||||||
|
tableMatches.append(i)
|
||||||
|
inf.close()
|
||||||
|
except Exception as e:
|
||||||
|
error('Error opening input file ' + inFile + '\n' + str(e), True)
|
||||||
|
|
||||||
|
# validate matches; should be paired, nothing but comments and empties; table may be named
|
||||||
|
# between them
|
||||||
|
|
||||||
|
for i in range(0, len(tableMatches), 2):
|
||||||
|
|
||||||
|
if i + 1 > len(tableMatches) - 1:
|
||||||
|
error('Mismatched table tags.\nFound so far: ' + ', '.join(tableNames), True)
|
||||||
|
|
||||||
|
tLines = lines[tableMatches[i]:tableMatches[i+1]+1]
|
||||||
|
tableLines.append(tLines)
|
||||||
|
tName = re.match(tablePattern, lines[tableMatches[i]]).groups()[0]
|
||||||
|
if tName is None:
|
||||||
|
tName = 'noname_' + str(tableMatches[i] + 1)
|
||||||
|
tableNames.append(tName)
|
||||||
|
|
||||||
|
for line in tLines:
|
||||||
|
if not re.match(commentPattern, line):
|
||||||
|
error('Found noncomment, nonempty line in table ' + tName + ':\n' + line, True)
|
||||||
|
|
||||||
|
print('Found tables: ' + ', '.join(tableNames))
|
||||||
|
|
||||||
|
# build table objects
|
||||||
|
|
||||||
|
for table, tName in zip(tableLines, tableNames):
|
||||||
|
print('Parsing ' + tName + '...')
|
||||||
|
namesByCol = {}
|
||||||
|
colsByName = {}
|
||||||
|
bitsByCol = {}
|
||||||
|
typesByCol = {}
|
||||||
|
specs = []
|
||||||
|
|
||||||
|
# parse the table - do by Table.parse()
|
||||||
|
tLines = table[1:-1] # exclude --tbl
|
||||||
|
for line in tLines:
|
||||||
|
if line.strip() == '':
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
spec = re.search(tableLinePattern, line).groups()[0]
|
||||||
|
except Exception as e:
|
||||||
|
error('Problem parsing table line:\n' + line, True)
|
||||||
|
if len(spec) > 0:
|
||||||
|
if spec[0] == 'n':
|
||||||
|
for match in re.finditer(namePattern, spec[1:]):
|
||||||
|
# col 0 is first col after n
|
||||||
|
namesByCol[match.start()] = match.groups()[0]
|
||||||
|
colsByName[match.groups()[0]] = match.start()
|
||||||
|
elif spec[0] == 'b':
|
||||||
|
for i, c in enumerate(spec[1:]):
|
||||||
|
if c == ' ' or c == '|':
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
bit = int(c)
|
||||||
|
except:
|
||||||
|
error('Unexpected char in bit line at position ' + str(i) + ' (' + c + ')\n' + line)
|
||||||
|
bit = None
|
||||||
|
if i in bitsByCol and bitsByCol[i] is not None:
|
||||||
|
bitsByCol[i] = bitsByCol[i]*10+bit
|
||||||
|
else:
|
||||||
|
bitsByCol[i] = bit
|
||||||
|
elif spec[0] == 't':
|
||||||
|
for i, c in enumerate(spec[1:]):
|
||||||
|
if c.lower() == 'i':
|
||||||
|
typesByCol[i] = TYPE_INPUT
|
||||||
|
elif c.lower() == 'o':
|
||||||
|
typesByCol[i] = TYPE_OUTPUT
|
||||||
|
elif c.lower() == '*':
|
||||||
|
typesByCol[i] = TYPE_SKIP
|
||||||
|
elif c != ' ':
|
||||||
|
error('Unexpected char in type line at position ' + str(i) + ' (' + c + ')\n' + line)
|
||||||
|
typesByCol[i] = None
|
||||||
|
else:
|
||||||
|
typesByCol[i] = None
|
||||||
|
elif spec[0] == 's':
|
||||||
|
specsByCol = {}
|
||||||
|
for i, c in enumerate(spec[1:]):
|
||||||
|
if c == '0' or c == '1':
|
||||||
|
specsByCol[i] = c
|
||||||
|
specs.append(specsByCol)
|
||||||
|
else:
|
||||||
|
#print('other:')
|
||||||
|
#print(line)
|
||||||
|
1
|
||||||
|
|
||||||
|
# create table object
|
||||||
|
|
||||||
|
# add strand to name where defined; don't combine for now into vector
|
||||||
|
# consecutive strands belong to the last defined name
|
||||||
|
lastName = None
|
||||||
|
lastCol = 0
|
||||||
|
signalsByCol = {}
|
||||||
|
|
||||||
|
for col,name in namesByCol.items(): # load with unstranded names
|
||||||
|
signalsByCol[col] = name
|
||||||
|
|
||||||
|
# sort by col so consecutive columns can be easily tracked
|
||||||
|
#for col,val in bitsByCol.items(): # update with stranded names
|
||||||
|
for col in sorted(bitsByCol):
|
||||||
|
val = bitsByCol[col]
|
||||||
|
|
||||||
|
if col > lastCol + 1:
|
||||||
|
lastName = None
|
||||||
|
if val is None:
|
||||||
|
lastName = None
|
||||||
|
if col in namesByCol:
|
||||||
|
if val is None:
|
||||||
|
signalsByCol[col] = namesByCol[col]
|
||||||
|
else:
|
||||||
|
lastName = namesByCol[col]
|
||||||
|
signalsByCol[col] = lastName + openBracket + str(val) + closeBracket
|
||||||
|
elif lastName is not None:
|
||||||
|
signalsByCol[col] = lastName + openBracket + str(val) + closeBracket
|
||||||
|
else:
|
||||||
|
error('Can\'t associate bit number ' + str(val) + ' in column ' + str(col) + ' with a signal name.')
|
||||||
|
lastCol = col
|
||||||
|
|
||||||
|
t = Table(tName)
|
||||||
|
t.source = table
|
||||||
|
t.signalsByCol = signalsByCol
|
||||||
|
t.typesByCol = typesByCol
|
||||||
|
t.specs = specs
|
||||||
|
|
||||||
|
tables[tName] = t
|
||||||
|
|
||||||
|
for name in tables:
|
||||||
|
t = tables[name]
|
||||||
|
t.validate()
|
||||||
|
t.makeRTL()
|
||||||
|
|
||||||
|
print()
|
||||||
|
print('Results:')
|
||||||
|
|
||||||
|
# find the lines with generate spec and replace them with new version
|
||||||
|
outLines = []
|
||||||
|
inTable = False
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
if not inTable:
|
||||||
|
match = re.search(tableGenPattern, line)
|
||||||
|
if match is not None:
|
||||||
|
tName = match.groups(1)[0]
|
||||||
|
if tName not in tables:
|
||||||
|
if tName == 1:
|
||||||
|
tName = '<blank>'
|
||||||
|
error('Found vtable start for \'' + tName + '\' but didn\'t generate that table: line ' + str(i+1) + '\n' + line, True)
|
||||||
|
else:
|
||||||
|
outLines.append(line)
|
||||||
|
outLines += tables[tName].equations
|
||||||
|
tables[tName].added = True
|
||||||
|
inTable = True
|
||||||
|
else:
|
||||||
|
outLines.append(line)
|
||||||
|
else:
|
||||||
|
match = re.search(tableGenPattern, line)
|
||||||
|
if match is not None:
|
||||||
|
if match.groups(1)[0] != tName:
|
||||||
|
error('Found vtable end for \'' + match.groups(1)[0] + '\' but started table \'' + tName + '\': line ' + str(i+1) + '\n' + line, True)
|
||||||
|
outLines.append(line)
|
||||||
|
inTable = False
|
||||||
|
else:
|
||||||
|
1#print('stripped: ' + line)
|
||||||
|
|
||||||
|
if backup:
|
||||||
|
try:
|
||||||
|
copyfile(inFile, backupFile)
|
||||||
|
except Exception as e:
|
||||||
|
error('Error creating backup file!\n' + str(e), True)
|
||||||
|
|
||||||
|
try:
|
||||||
|
of = open(outFile, 'w')
|
||||||
|
for line in outLines:
|
||||||
|
of.write("%s\n" % line)
|
||||||
|
except Exception as e:
|
||||||
|
error('Error writing output file ' + outFile + '!\n' + str(e), True)
|
||||||
|
|
||||||
|
print('Generated ' + str(len(tables)) + ' tables: ' + ', '.join(tableNames))
|
||||||
|
notAdded = {}
|
||||||
|
for table in tables:
|
||||||
|
if not tables[table].added:
|
||||||
|
notAdded[table] = True
|
||||||
|
print('Output file: ' + outFile)
|
||||||
|
if backup:
|
||||||
|
print('Backup file: ' + backupFile)
|
||||||
|
if len(notAdded) != 0:
|
||||||
|
error('Tables generated but not added to file! ' + ', '.join(notAdded))
|
Loading…
Reference in New Issue