Commit 9cb7cc15 authored by Tristan Gingold's avatar Tristan Gingold

testbench: add simple debug interface test.

parent 4533ff05
......@@ -31,6 +31,7 @@
`include "mt_cpu_csr_driver.svh"
`include "mt_queue_message.svh"
`include "mt_hmq_driver.svh"
`include "mt_debug_driver.svh"
`include "mt_config_rom_driver.svh"
// Simple interface to deliver the four interrupts of MT to the
......@@ -63,6 +64,7 @@ class MockTurtleDriver;
protected MQueueHost hmq[];
protected MTConfigRom rom;
protected vIMockTurtleIRQ irq;
MDebug dbg;
function new ( CWishboneAccessor acc, uint64_t base, vIMockTurtleIRQ irq );
this.acc = acc;
......@@ -82,6 +84,8 @@ class MockTurtleDriver;
// Next init the MT CSR
csr = new ( acc, base + 'hc000, core_count );
csr.init();
// Debug interface
dbg = new (acc, csr);
// Host message queue objects are one per cpu core
hmq = new [core_count];
for (int i = 0; i < core_count; i++)
......
//------------------------------------------------------------------------------
// CERN BE-CO-HT
// Mock Turtle
// https://gitlab.cern.ch/coht/mockturtle
//------------------------------------------------------------------------------
//
// unit name: MDebug
//
// description: A SystemVerilog Class to provide an abstraction of the
// MockTurtle core's debug interface.
//
//------------------------------------------------------------------------------
// Copyright CERN 2018
//------------------------------------------------------------------------------
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-2.0.
// Unless required by applicable law or agreed to in writing, software,
// hardware and materials distributed under this 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.
//------------------------------------------------------------------------------
`ifndef __MT_DEBUG_DRIVER_INCLUDED
`define __MT_DEBUG_DRIVER_INCLUDED
/* [0x180]: REG Debug Interface Status Register */
`define MT_CPU_CSR_REG_DBG_STATUS 32'h00000180
/* [0x184]: REG Debug Interface Force Register */
`define MT_CPU_CSR_REG_DBG_FORCE 32'h00000184
/* [0x188]: REG Debug Interface Instruction Ready Register */
`define MT_CPU_CSR_REG_DBG_INSN_READY 32'h00000188
/* [0x18c]: REG Debug Interface Core[0] Instruction Register */
`define MT_CPU_CSR_REG_DBG_CORE0_INSN 32'h0000018c
/* [0x190]: REG Debug Interface Core[1] Instruction Register */
`define MT_CPU_CSR_REG_DBG_CORE1_INSN 32'h00000190
/* [0x194]: REG Debug Interface Core[0] Mailbox Data Register */
`define MT_CPU_CSR_REG_DBG_CORE0_MBX 32'h00000194
/* [0x198]: REG Debug Interface Core[1] Mailbox Data Register */
`define MT_CPU_CSR_REG_DBG_CORE1_MBX 32'h00000198
class MDebug;
protected CBusAccessor bus;
protected MTCPUControl csr;
function new( CBusAccessor bus, MTCPUControl csr);
this.bus = bus;
this.csr = csr;
endfunction // new
local task read (uint32_t offset, ref uint32_t rv);
csr.readl (offset, rv);
endtask // read
local task write (uint32_t offset, uint32_t rv);
csr.writel (offset, rv);
endtask // write
task force_core(int core, uint32_t v);
uint32_t val;
read(`MT_CPU_CSR_REG_DBG_FORCE, val);
val[core] = v;
write(`MT_CPU_CSR_REG_DBG_FORCE, val);
endtask
local task write_mbx(int core, uint32_t v);
write(`MT_CPU_CSR_REG_DBG_CORE0_MBX + 4 * core, v);
endtask
local task read_mbx(int core, output uint32_t v);
read(`MT_CPU_CSR_REG_DBG_CORE0_MBX + 4 * core, v);
endtask
local task exec_insn(int core, uint32_t insn);
write(`MT_CPU_CSR_REG_DBG_CORE0_INSN + 4 * core, insn);
endtask
local task exec_mbx_to_reg(int core, uint32_t r);
exec_insn(core, 32'h7d002073 + (r << 7));
endtask
local task exec_reg_to_mbx(int core, uint32_t r);
exec_insn(core, 32'h7d001073 + (r << 15));
endtask
local task exec_nop(int core);
exec_insn(core, 32'h00000013);
endtask
task read_reg(int core, int r, output uint32_t v);
exec_reg_to_mbx(core, r);
exec_nop(core);
exec_nop(core);
exec_nop(core);
read_mbx(core, v);
endtask
task write_reg(int core, int r, uint32_t v);
write_mbx(core, v);
exec_mbx_to_reg(core, r);
endtask
task read_pc_via_ra(int core, output uint32_t pc);
// Read current pc value but destroy ra.
exec_insn(core, 32'h000000ef); // ra = pc + 4
exec_nop(core);
exec_nop(core);
exec_nop(core);
exec_reg_to_mbx(core, 1);
exec_nop(core);
exec_nop(core);
exec_nop(core);
read_mbx(core, pc);
pc -= 4;
endtask
task write_pc_via_ra(int core);
exec_insn(core, 32'h00008067); // ret
exec_nop(core);
exec_nop(core);
exec_nop(core);
endtask
task advance_pc_4(int core);
exec_insn(core, 32'h00000263); // beqz zero, +4
exec_nop(core);
exec_nop(core);
exec_nop(core);
endtask
task write_word(int core, uint32_t addr, uint32_t v);
uint32_t a0, a1;
read_reg(core, 10, a0);
read_reg(core, 11, a1);
write_reg(core, 10, addr);
write_reg(core, 11, v);
exec_insn(core, 32'h00b52023); // sw a1,0(a0)
// exec_insn(core, 32'h00450513); // addi a0, a0, 4
write_reg(core, 10, a0);
write_reg(core, 11, a1);
endtask
task read_word(int core, uint32_t addr, output uint32_t v);
uint32_t a0, a1;
read_reg(core, 10, a0);
read_reg(core, 11, a1);
write_reg(core, 10, addr);
exec_insn(core, 32'h00052583); // lw a1,0(a0)
read_reg(core, 11, v);
write_reg(core, 10, a0);
write_reg(core, 11, a1);
endtask
/*
task incoming_write (uint32_t r, uint32_t v);
write (`MQUEUE_BASE_IN + r, v);
endtask // incoming_write
*/
endclass
`endif
......@@ -124,6 +124,21 @@ module main;
end
endtask // check_hmq_incoming
task check_debug_interface(int core);
uint32_t v;
// Enable debug
drv.dbg.force_core(core, 1);
drv.reset_core(core, 0);
drv.dbg.force_core(core, 0);
// Check write/read
drv.dbg.write_word(core, 32'h4, 32'h12349876);
drv.dbg.read_word(core, 32'h4, v);
if (v != 32'h12349876)
$fatal(1, "debug interface: r/w memory");
endtask : check_debug_interface
task check_final_count (uint32_t expected);
#500us;
if (count != expected)
......@@ -134,12 +149,6 @@ module main;
initial begin
fork
check_final_count(11);
join_none
count = 0;
#10us;
drv = new (Host.get_accessor(), mt_base, IrqMonitor);
......@@ -150,6 +159,14 @@ module main;
drv.enable_hmqi_irq (0, 0, 1);
check_debug_interface(0);
fork
check_final_count(11);
join_none
count = 0;
drv.load_firmware (0, fw, 1'b0);
drv.reset_core (0, 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment