Commit ef467fd5 authored by Dimitris Lampridis's avatar Dimitris Lampridis Committed by Adam Wujek

sim: update testbenches to be compatible with current HDL. Tested, works.

parent 64b016b6
......@@ -27,47 +27,164 @@
`define __MOCK_TURTLE_DRIVER_INCLUDED
`include "simdrv_defs.svh"
`include "if_wishbone_accessor.svh"
`include "mt_cpu_csr_driver.svh"
`include "mt_mqueue_host_driver.svh"
`include "mt_queue_message.svh"
`include "mt_hmq_driver.svh"
`include "mt_config_rom_driver.svh"
// Simple interface to deliver the four interrupts of MT to the
// MockTurtleDriver class below
interface IMockTurtleIRQ (
input logic hmq_in,
input logic hmq_out,
input logic notify,
input logic console);
endinterface // IMockTurtleIRQ
// Macro to simplify attaching one side of the interface to signals
// in mock_turtle_core.vhd.
// (The "other" side is monitored by the MockTurtleDriver class below)
`define MT_ATTACH_IRQ(mt)\
.hmq_in (mt.hmq_in_irq),\
.hmq_out (mt.hmq_out_irq),\
.notify (mt.notify_irq),\
.console (mt.console_irq)
// A class can only accept virtual interfaces, so we declare it here
typedef virtual IMockTurtleIRQ vIMockTurtleIRQ;
// The main class, to monitor and drive the complete MT
class MockTurtleDriver;
protected CBusAccessor m_acc;
protected uint64_t m_base;
MTCPUControl m_csr;
MQueueHost m_hmq;
MTConfigRom m_rom;
function new ( CBusAccessor acc, uint64_t base );
m_acc = acc;
m_base = base;
protected CWishboneAccessor acc;
protected uint64_t base;
protected uint32_t core_count;
protected MTCPUControl csr;
protected MQueueHost hmq[];
protected MTConfigRom rom;
protected vIMockTurtleIRQ irq;
// When set to 0, parent application will need
// to clear notification irqs manually
protected bit autoclear_notify;
function new ( CWishboneAccessor acc, uint64_t base,
vIMockTurtleIRQ irq, bit autoclear_notify = 1'b1 );
this.acc = acc;
this.base = base;
this.irq = irq;
endfunction // new
task init();
m_csr = new ( m_acc, m_base + 'hc000 );
m_hmq = new ( m_acc, m_base + 'h0000 );
m_rom = new ( m_acc, m_base + 'he000 );
m_csr.init();
m_hmq.init();
m_rom.init();
task init ( wb_cycle_type_t mode = PIPELINED );
uint32_t slot_count;
wb_set_mode ( mode );
// first init the config ROM, to be able to get core count etc.
rom = new ( acc, base + 'he000 );
rom.init();
core_count = rom.getCoreCount();
$display ("App ID: 0x%x", rom.getAppID);
$display ("Core count: %0d", core_count);
// Next init the MT CSR
csr = new ( acc, base + 'hc000, core_count );
csr.init();
// Host message queue objects are one per cpu core
hmq = new [core_count];
for (int i = 0; i < core_count; i++)
begin
slot_count = rom.getHmqSlotCount(i);
// CSR is passed to each queue to be able to select slot
// inside the class via csr.hmq_select()
hmq[i] = new ( acc, base + 'h0000, i, csr, slot_count );
hmq[i].init();
end
endtask // init
task load_firmware ( int core, string filename, bit check = 1'b1);
m_csr.load_firmware ( core, filename, check );
csr.load_firmware ( core, filename, check );
endtask // load_firmware
task reset_core ( int core, int reset );
m_csr.reset_core ( core, reset );
csr.reset_core ( core, reset );
endtask // reset_core
task cfg_rom_display();
m_rom.pretty_print();
rom.pretty_print();
endtask // cfg_rom_display
// polls HMQ and Debug UART
task cfg_rom_dump();
rom.dump();
endtask // cfg_rom_dump
task wb_set_mode ( wb_cycle_type_t mode );
acc.set_mode ( mode );
endtask // wb_set_mode
task enable_console_irq ( int core, int enable );
csr.debug_int_enable ( core, enable );
endtask // enable_console_irq
task enable_hmq_irq ( int core, int queue, int enable );
hmq[core].slot_int_enable ( queue, enable );
endtask // enable_hmq_irq
task smem_read ( input uint32_t offset, ref uint32_t val );
uint64_t tmp;
acc.read (base + 32'h1_0000 + offset, tmp);
val = tmp;
endtask // smem_read
task smem_write ( uint32_t offset, uint32_t val);
acc.write (base + 32'h1_0000 + offset, val);
endtask // smem_write
task get_cpu_notifications (ref uint32_t val);
val = 0;
if (csr.notify_queue.size() == 0)
return;
while (csr.notify_queue.size() != 0)
val |= csr.notify_queue.pop_front();
endtask // get_cpu_notifications
task clear_cpu_notifications (uint32_t val);
csr.clear_notification_irq(val);
endtask // clear_cpu_notifications
task handle_hmq_in_irq ();
endtask // handle_hmq_in_irq
task hmq_receive_message (ref MQueueMsg msg);
msg = hmq[msg.core].receive_message (msg.slot);
endtask // hmq_receive_message
task hmq_send_message (input MQueueMsg msg);
hmq[msg.core].send_message (msg.slot, msg);
endtask // hmq_send_message
function bit hmq_pending_messages (uint32_t core, uint32_t slot);
return hmq[core].pending_in(slot);
endfunction // hmq_pending_messages
task update();
m_csr.update();
m_hmq.update();
uint32_t val;
if (irq.console == 1'b1)
begin
csr.check_consoles();
end
if (irq.notify == 1'b1)
begin
csr.handle_notification_irq(autoclear_notify);
end
if (irq.hmq_in == 1'b1)
begin
for (int i = 0; i < core_count; i++)
begin
hmq[i].receive_pending();
end
end
for (int i = 0; i < core_count; i++)
begin
hmq[i].send_pending();
end
endtask // update
endclass // MockTurtleDriver
......
......@@ -60,6 +60,22 @@ class MTConfigRom;
return m_data[pos];
endfunction // read
function uint32_t getAppID();
return read(5);
endfunction // getAppID
function uint32_t getCoreCount();
return read(6);
endfunction // getCoreCount
function uint32_t getHmqSlotCount(int core);
return read(16 + core);
endfunction // getHmqSlotCount
function uint32_t getRmqSlotCount(int core);
return read(24 + core);
endfunction // getRmqSlotCount
task dump ();
int i;
......@@ -71,7 +87,7 @@ class MTConfigRom;
task pretty_print ( );
int i, j;
int cpu_count = read(6);
int cpu_count = getCoreCount();
$display ( "Configuration ROM contents:" );
$display ( " Magic Value : %0s", read(0) );
......@@ -79,14 +95,14 @@ class MTConfigRom;
$display ( " Clock Frequency : %0d", read(3) );
$display ( " WR support : %0s", read(4) & 1 ? "yes" : "no" );
$display ( " RMQ support : %0s", read(4) & 2 ? "yes" : "no" );
$display ( " Application ID : %0x", read(5) );
$display ( " Application ID : %0x", getAppID() );
$display ( " Shared mem size : %0d", read(7) );
$display ( " CPU count : %0d", cpu_count );
for ( i = 0; i < cpu_count; i++ )
begin
int hmq_slots = read(16 + i);
int rmq_slots = read(24 + i);
int hmq_slots = getHmqSlotCount(i);
int rmq_slots = getRmqSlotCount(i);
$display ( " CPU #%0d", i );
$display ( " Local mem size : %0d", read(8+i) );
$display ( " HMQ slots : %0d", hmq_slots );
......
......@@ -41,27 +41,17 @@ class MTCPUControl;
protected CBusAccessor bus;
protected uint32_t base;
protected uint32_t app_id;
protected uint32_t core_count;
protected uint32_t core_memsizes[$];
protected uint32_t notify_irq_mask;
protected string dbg_msg_queue[];
function new ( CBusAccessor bus_, input uint32_t base_);
base = base_;
bus = bus_;
endfunction // new
function uint32_t getAppID();
return app_id;
endfunction // getAppID
function uint32_t getCoreCount();
return core_count;
endfunction // getCoreCount
uint32_t notify_queue[$];
function uint32_t getCoreMemorySize(int core);
return core_memsizes[core];
endfunction // getCoreMemorySize
function new ( CBusAccessor bus, input uint32_t base, int core_count);
this.base = base;
this.bus = bus;
this.core_count = core_count;
endfunction // new
task writel ( uint32_t r, uint32_t v );
bus.write ( base + r, v );
......@@ -74,27 +64,9 @@ class MTCPUControl;
endtask // readl
task init();
int i;
$display("Init CSR driver");
readl(`ADDR_MT_CPU_CSR_APP_ID, app_id);
readl(`ADDR_MT_CPU_CSR_CORE_COUNT, core_count);
core_count &= 'hf;
$display("App ID: 0x%x", app_id);
$display("Core count: %0d", core_count);
dbg_msg_queue = new[core_count];
for(i = 0; i < core_count; i++)
begin
uint32_t memsize;
writel(`ADDR_MT_CPU_CSR_CORE_SEL, i);
readl(`ADDR_MT_CPU_CSR_CORE_MEMSIZE, memsize);
$display("Core %1d: %3d kB private memory", i, memsize/1024);
core_memsizes.push_back( memsize );
end
notify_irq_mask = 0;
notify_queue = {};
dbg_msg_queue = new[core_count];
endtask // init
task reset_core(int core, int reset);
......@@ -126,7 +98,7 @@ class MTCPUControl;
// Stop in case of error.
if (f == 0)
$exit;
$exit;
reset_core(core, 1);
......@@ -144,22 +116,22 @@ class MTCPUControl;
end // while (!$feof(f))
if (check)
begin
void'($rewind(f));
begin
void'($rewind(f));
for(i = 0; i < addr; i++)
for(i = 0; i < addr; i++)
begin
uint32_t rv, data;
writel(`ADDR_MT_CPU_CSR_UADDR, i);
readl(`ADDR_MT_CPU_CSR_UDATA, rv);
uint32_t rv, data;
writel(`ADDR_MT_CPU_CSR_UADDR, i);
readl(`ADDR_MT_CPU_CSR_UDATA, rv);
void'($fread(data, f));
assert (rv == data) else
$fatal("verification error at %x, got %x, expected %x\n",
i, rv, data);
void'($fread(data, f));
assert (rv == data) else
$fatal("verification error at %x, got %x, expected %x\n",
i, rv, data);
end
end
end
$fclose(f);
endtask // load_firmware
......@@ -168,6 +140,7 @@ class MTCPUControl;
uint32_t rval, cpu_mask;
readl(`ADDR_MT_CPU_CSR_DBG_POLL , cpu_mask);
if (cpu_mask == 0)
return;
......@@ -182,19 +155,44 @@ class MTCPUControl;
if(rval == 0 || rval == 13 || rval == 10)
begin
$display("DBG MSG Core %0d: %s", i, dbg_msg_queue[i]);
dbg_msg_queue[i] = "";
dbg_msg_queue[i] = "";
end
else
dbg_msg_queue[i] = {dbg_msg_queue[i], rval[7:0]};
else
dbg_msg_queue[i] = {dbg_msg_queue[i], rval[7:0]};
end
endtask
task check_c2h_interrupts();
uint32_t val;
task get_notification_irq (ref uint32_t val);
readl(`ADDR_MT_CPU_CSR_INT, val);
if (val != 0)
$display("C2H interrupts: %x", val);
endtask
endtask // get_notification_irq
task get_hmq_in_status (ref uint64_t val);
uint32_t tmp;
readl(`ADDR_MT_CPU_CSR_HMQI_STATUS_LO, tmp);
val = tmp;
readl(`ADDR_MT_CPU_CSR_HMQI_STATUS_HI, tmp);
val |= tmp << 32;
endtask // get_hmq_in_status
task clear_notification_irq (uint32_t val);
writel(`ADDR_MT_CPU_CSR_INT, val);
notify_irq_mask &= ~val;
endtask // clear_notification_irq
task handle_notification_irq (input bit autoclear_notify = 1'b1);
uint32_t val;
get_notification_irq(val);
if (val & ~notify_irq_mask)
notify_queue.push_back(val);
notify_irq_mask |= val;
if (val != 0 && autoclear_notify == 1'b1)
clear_notification_irq(val);
endtask // handle_notification_irq
task hmq_select(uint32_t core, uint32_t queue);
uint32_t val = (core && 'b111) << 3 | (queue && 'b111);
writel(`ADDR_MT_CPU_CSR_HMQ_SEL, val);
endtask; // hmq_select
task update();
check_consoles();
......
//------------------------------------------------------------------------------
// CERN BE-CO-HT
// Mock Turtle
// https://gitlab.cern.ch/coht/mockturtle
//------------------------------------------------------------------------------
//
// unit name: MQueueHost
//
// description: A SystemVerilog Class to provide an abstraction of the
// MockTurtle core's host message queue.
//
//------------------------------------------------------------------------------
// 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_MQUEUE_HOST_DRIVER_INCLUDED
`define __MT_MQUEUE_HOST_DRIVER_INCLUDED
`define MQUEUE_BASE_IN ('h4000)
`define MQUEUE_BASE_OUT ('h8000)
`define MQUEUE_CMD_CLAIM (1<<24)
`define MQUEUE_CMD_PURGE (1<<25)
`define MQUEUE_CMD_READY (1<<26)
`define MQUEUE_CMD_DISCARD (1<<27)
`define MQUEUE_SLOT_COMMAND 0
`define MQUEUE_SLOT_STATUS 4
`define MQUEUE_SLOT_HEADER 16'h1000
`define MQUEUE_SLOT_DATA 16'h2000
`define MQUEUE_GCR_SLOT_COUNT 0
`define MQUEUE_GCR_SLOT_STATUS 4
`define MQUEUE_GCR_IRQ_MASK 8
`define MQUEUE_GCR_IRQ_COALESCE 12
`include "mt_queue_message.svh"
class MQueueHost;
protected CBusAccessor bus;
protected uint32_t base;
protected uint32_t core;
protected uint32_t slot_count;
protected MTCPUControl csr;
typedef MQueueMsg slot_queue_t[$];
slot_queue_t slots_in[], slots_out[];
function new( CBusAccessor bus, uint32_t base, uint32_t core,
MTCPUControl csr, uint32_t slot_count);
this.base = base;
this.bus = bus;
this.core = core;
this.csr = csr;
this.slot_count = slot_count;
endfunction // new
task init();
this.slots_in = new[slot_count];
this.slots_out = new[slot_count];
for (int i = 0; i < slot_count; i++)
begin
this.slots_in[i] = {};
this.slots_out[i] = {};
csr.hmq_select (core, i);
incoming_purge ();
outgoing_purge ();
end
endtask // init
task read (uint32_t offset, output uint32_t rv);
uint64_t tmp;
bus.read (base + offset, tmp);
rv = tmp;
endtask // read
task write (uint32_t offset, uint32_t rv);
bus.write (base + offset, rv);
endtask // write
task get_irq_mask (ref uint32_t val);
read (`MQUEUE_GCR_IRQ_MASK, val);
endtask // get_irq_mask
task set_irq_mask (input uint32_t val);
write (`MQUEUE_GCR_IRQ_MASK, val);
endtask // set_irq_mask
task slot_int_enable(int slot, int enable);
uint32_t imsk;
csr.hmq_select ( core, slot );
get_irq_mask (imsk);
if (enable)
imsk |= (1 << slot);
else
imsk &= ~(1 << slot);
set_irq_mask (imsk);
endtask // slot_int_enable
task incoming_write (uint32_t r, uint32_t v);
write (`MQUEUE_BASE_IN + r, v);
endtask // incoming_write
task outgoing_write (uint32_t r, uint32_t v);
write (`MQUEUE_BASE_OUT + r, v);
endtask // outgoing_write
task incoming_read (uint32_t r, ref uint32_t v);
read (`MQUEUE_BASE_IN + r, v);
endtask // incoming_read
task outgoing_read (uint32_t r, ref uint32_t v);
read (`MQUEUE_BASE_OUT + r, v);
endtask // outgoing_read
task incoming_purge ();
incoming_write (`MQUEUE_SLOT_COMMAND, `MQUEUE_CMD_PURGE );
endtask // incoming_purge
task outgoing_purge ();
outgoing_write (`MQUEUE_SLOT_COMMAND, `MQUEUE_CMD_PURGE );
endtask // outgoing_purge
task incoming_check_full (output int full);
uint32_t rv;
incoming_read (`MQUEUE_SLOT_STATUS, rv);
full = (rv & 1) ? 1: 0;
endtask // incoming_check_full
task outgoing_check_full (output int full);
uint32_t rv;
outgoing_read (`MQUEUE_SLOT_STATUS, rv);
full = (rv & 1) ? 1: 0;
endtask // outgoing_check_full
task slot_send ( int slot );
MQueueMsg msg;
csr.hmq_select ( core, slot );
msg = slots_out[slot].pop_back();
outgoing_write (`MQUEUE_SLOT_COMMAND, `MQUEUE_CMD_CLAIM);
for (int i = 0; i < msg.header.size(); i++)
begin
outgoing_write (`MQUEUE_SLOT_HEADER + i * 4, msg.header[i]);
end
for (int i = 0; i < msg.data.size(); i++)
begin
outgoing_write (`MQUEUE_SLOT_DATA + i * 4, msg.data[i]);
end
outgoing_write (`MQUEUE_SLOT_COMMAND, `MQUEUE_CMD_READY);
endtask // slot_send
task slot_recv ( int slot );
MQueueMsg msg;
uint32_t val;
csr.hmq_select ( core, slot );
msg = new (core, slot);
incoming_read (`MQUEUE_SLOT_HEADER + 0, val );
msg.header[0] = val;
incoming_read (`MQUEUE_SLOT_HEADER + 4, val );
msg.header[1] = val;
for (int i = 0; i < msg.header[0]; i++)
begin
incoming_read (`MQUEUE_SLOT_DATA + 4*i, val);
msg.data.push_back(val);
end
incoming_write(`MQUEUE_SLOT_COMMAND, `MQUEUE_CMD_DISCARD );
slots_in[slot].push_front(msg);
endtask // slot_recv
function MQueueMsg receive_message (int slot);
MQueueMsg ret = slots_in[slot].pop_back();
return ret;
endfunction // receive_message
function void send_message (int slot, MQueueMsg msg);
slots_out[slot].push_front(msg);
endfunction // send_message
function bit pending_in (int slot);
return slots_in[slot].size() != 0 ? 1'b1 : 1'b0;
endfunction // pending_in
task receive_pending();
uint64_t stat;
uint32_t core_stat;
uint32_t imask;
csr.get_hmq_in_status(stat);
core_stat = (stat >> (core*8)) & 'hff;
if (core_stat == 0)
return;
csr.hmq_select (core, 0);
get_irq_mask (imask);
core_stat &= imask;
if (core_stat == 0)
return;
for (int i = 0; i < slot_count; i++)
begin
csr.hmq_select (core, i);
if (core_stat & (1 << i))
slot_recv(i);
end
endtask // receive_pending
task send_pending();
uint32_t full;
for (int i = 0; i < slot_count ;i++)
begin
while ( slots_out[i].size() )
begin
csr.hmq_select (core, i);
outgoing_check_full(full);
if (full)
break;
slot_send(i);
end
end
endtask // send_pending
endclass // MQueueHost
`endif // `ifndef __MT_MQUEUE_HOST_DRIVER_INCLUDED
This diff is collapsed.
//------------------------------------------------------------------------------
// CERN BE-CO-HT
// Mock Turtle
// https://gitlab.cern.ch/coht/mockturtle
//------------------------------------------------------------------------------
//
// unit name: MQueueMsg
//
// description: A SystemVerilog Class to provide an abstraction of the
// MockTurtle core's queue message.
//
//------------------------------------------------------------------------------
// 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_MQUEUE_MSG_INCLUDED
`define __MT_MQUEUE_MSG_INCLUDED
class MQueueMsg;
int core;
int slot;
uint32_t header[$];
uint32_t data[$];
function new (int core = 0, int slot = 0);
this.core = core;
this.slot = slot;
this.header = {};
this.data = {};
endfunction // new
endclass // MQueueMsg
`endif // `ifndef __MT_MQUEUE_MSG_INCLUDED
//------------------------------------------------------------------------------
// CERN BE-CO-HT
// Mock Turtle
// https://gitlab.cern.ch/coht/mockturtle
//------------------------------------------------------------------------------
//
// unit name: Serializable
//
// description: A SystemVerilog Class representing a serializable object.
//
//------------------------------------------------------------------------------
// 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 __SERIALIZABLE_SVH
`define __SERIALIZABLE_SVH
`include "simdrv_defs.svh"
typedef byte int8_t;
typedef byte unsigned uint8_t;
typedef uint8_t uint8_array_t[$];
class ByteBuffer;
uint8_t data[$];
int pos;
function new();
pos = 0;
endfunction // new
function ByteBuffer copy();
copy = new();
copy.pos = this.pos;
copy.data = this.data;
return copy;
endfunction // copy
task automatic clear();
data = '{};
pos = 0;
endtask // clear
task dump();
int i;
$display("buffer has %d bytes", data.size());
for (i=0;i<data.size();i++)
$display("%d: %x", i, data[i]);
endtask // dump
function int size();
return data.size();
endfunction // size
function int getPos();
return pos;
endfunction // getPos
function automatic void setPos( int pos_ );
pos = pos_;
endfunction // setPos
function automatic void addByte ( uint8_t c );
data.push_back(c);
endfunction // addByte
function automatic void addShort ( uint32_t c );
data.push_back((c >> 8) & 'hff);
data.push_back(c & 'hff);
endfunction // addShort
function automatic void addWord ( uint32_t c );
data.push_back((c >> 24) & 'hff);
data.push_back((c >> 16) & 'hff);
data.push_back((c >> 8) & 'hff);
data.push_back(c & 'hff);
endfunction // addWord
function automatic void addBytes ( uint8_t d[$] );
for (int i=0;i<d.size();i++)
data.push_back(d[i]);
endfunction // addBytes
function automatic uint8_t getByte();
automatic uint8_t rv = data[pos++];
return rv;
endfunction // getByte
function automatic uint8_t at(int pos_);
return data[pos_];
endfunction
function automatic uint8_array_t getBytes(int count);
automatic uint8_array_t rv;
for (int i=0;i<count;i++)
rv.push_back(data[pos++]);
return rv;
endfunction // getBytes
function automatic uint32_t getWord();
automatic uint32_t rv;
rv = data[pos++];
rv <<= 8;
rv |= data[pos++];
rv <<= 8;
rv |= data[pos++];
rv <<= 8;
rv |= data[pos++];
return rv;
endfunction // getWord
function automatic void reset();
pos = 0;
endfunction
endclass // ByteBuffer
class Serializable;
protected ByteBuffer m_data;
virtual function automatic void serialize( ByteBuffer data );
endfunction // serialize
virtual function automatic void deserialize ( ByteBuffer data );
m_data = data;
endfunction // deserialize
virtual task automatic dump();
if(!m_data)
return;
m_data.dump();
endtask // dump
function automatic void deserializeBytes ( uint8_t data[$]);
automatic ByteBuffer b = new ;
b.data = data;
deserialize( b );
endfunction // deserializeBytes
endclass // Serializable
`endif // `ifndef __SERIALIZABLE_SVH
......@@ -26,6 +26,8 @@
`include "mock_turtle_driver.svh"
`include "vhd_wishbone_master.svh"
import mock_turtle_pkg::*;
`timescale 1ns/1ps
module main;
......@@ -33,6 +35,9 @@ module main;
reg rst_n = 0;
reg clk_sys = 0;
t_mt_stream_source_out_array2d rmq_src_out;
t_mt_stream_source_in_array2d rmq_src_in;
always #8ns clk_sys <= ~clk_sys;
initial begin
......@@ -40,55 +45,103 @@ module main;
rst_n = 1;
end
IVHDWishboneMaster Host ( clk_sys, rst_n );
mock_turtle_core # ()
DUT (
.clk_i (clk_sys),
.rst_n_i (rst_n),
.host_slave_i (Host.out),
.host_slave_o (Host.in),
.sp_master_o (),
.sp_master_i (),
.dp_master_o (),
.dp_master_i (),
.rmq_src_o (),
.rmq_src_i (),
.rmq_snk_o (),
.rmq_snk_i (),
.clk_ref_i (),
.tm_i (),
.gpio_o (),
.gpio_i (),
.hmq_in_irq_o (),
.clk_i (clk_sys),
.rst_n_i (rst_n),
.host_slave_i (Host.out),
.host_slave_o (Host.in),
.sp_master_o (),
.sp_master_i (),
.dp_master_o (),
.dp_master_i (),
.rmq_src_o (rmq_src_out),
.rmq_snk_i (rmq_src_out),
.rmq_snk_o (rmq_src_in),
.rmq_src_i (rmq_src_in),
.clk_ref_i (),
.tm_i (),
.gpio_o (),
.gpio_i (),
.hmq_in_irq_o (),
.hmq_out_irq_o (),
.notify_irq_o (),
.notify_irq_o (),
.console_irq_o ()
);
initial begin
IVHDWishboneMaster Host ( clk_sys, rst_n );
static string fw = "../../../demos/hello_world/firmware/fw-01/fw-hello.bin";
IMockTurtleIRQ IrqMonitor (`MT_ATTACH_IRQ(DUT));
string fw = "../../../tests/firmware/sim-verif/sim-verif.bin";
const uint64_t mt_base = 'h0000;
MockTurtleDriver drv;
uint64_t count;
task inc_counter();
uint32_t val;
drv.smem_read (0, val);
if (val != count)
$fatal (1, "incorrect count (%0d, expected %0d)", val, count);
count++;
drv.smem_write (0, count);
endtask // inc_counter
task check_cpu_notifications ();
uint32_t val;
drv.get_cpu_notifications (val);
if (val)
begin
if (val & 'h1)
inc_counter();
drv.clear_cpu_notifications (val);
end
endtask // check_cpu_notifications
task check_hmq_incoming ();
// check from pending messages in core 0, slot 0
while (drv.hmq_pending_messages(0, 0))
begin
// Get a message from core 0, slot 0
automatic MQueueMsg msg = new (0, 0);
drv.hmq_receive_message (msg);
//$display(msg);
inc_counter();
for (int i = 0; i < msg.data.size(); i++)
msg.data[i] = ~msg.data[i];
drv.hmq_send_message (msg);
end
endtask // check_hmq_incoming
CWishboneAccessor acc;
MockTurtleDriver drv;
initial begin
count = 0;
#10us;
acc = Host.get_accessor();
acc.set_mode (PIPELINED);
drv = new (Host.get_accessor(), mt_base, IrqMonitor, 1'b0);
drv = new(acc, 'h20000);
drv.init();
drv.load_firmware(0, fw, 1'b0);
drv.reset_core(0, 0);
drv.enable_console_irq (0, 1);
drv.enable_hmq_irq (0, 0, 1);
drv.load_firmware (0, fw, 1'b0);
drv.reset_core (0, 0);
forever begin
drv.update();
#1us;
drv.update ();
check_cpu_notifications ();
check_hmq_incoming ();
# 1us;
end
end // initial begin
endmodule
endmodule // main
vsim -L unisim work.main -novopt
vsim -quiet -L unisim work.main -novopt
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
do wave.do
radix -hexadecimal
run 1000us
\ No newline at end of file
log -r /*
run 300us
......@@ -5,7 +5,7 @@ vsim -quiet -L unisim work.main
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
run 500us
run 1500us
exit
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate -group Top /main/DUT/clk_i
add wave -noupdate -group Top /main/DUT/clk_cpu_i
add wave -noupdate -group Top /main/DUT/rst_n_i
add wave -noupdate -group Top /main/DUT/sp_master_o
add wave -noupdate -group Top /main/DUT/sp_master_i
add wave -noupdate -group Top /main/DUT/dp_master_o
add wave -noupdate -group Top /main/DUT/dp_master_i
add wave -noupdate -group Top /main/DUT/host_slave_i
add wave -noupdate -group Top /main/DUT/host_slave_o
add wave -noupdate -group Top /main/DUT/clk_ref_i
add wave -noupdate -group Top /main/DUT/tm_i
add wave -noupdate -group Top /main/DUT/gpio_o
add wave -noupdate -group Top /main/DUT/gpio_i
add wave -noupdate -group Top /main/DUT/host_irq_o
add wave -noupdate -group Top /main/DUT/debug_msg_irq_o
add wave -noupdate -group Top /main/DUT/hac_master_out
add wave -noupdate -group Top /main/DUT/hac_master_in
add wave -noupdate -group Top /main/DUT/si_slave_in
add wave -noupdate -group Top /main/DUT/si_slave_out
add wave -noupdate -group Top /main/DUT/si_master_in
add wave -noupdate -group Top /main/DUT/si_master_out
add wave -noupdate -group Top /main/DUT/cpu_csr_fromwb
add wave -noupdate -group Top -expand /main/DUT/cpu_csr_towb
add wave -noupdate -group Top /main/DUT/hmq_status
add wave -noupdate -group Top /main/DUT/rmq_status
add wave -noupdate -group Top /main/DUT/cpu_index
add wave -noupdate -group Top /main/DUT/cpu_dbg_drdy
add wave -noupdate -group Top /main/DUT/cpu_dbg_dack
add wave -noupdate -group Top /main/DUT/cpu_dbg_msg_data
add wave -noupdate -group Top /main/DUT/dbg_msg_data_read_ack
add wave -noupdate -group Top /main/DUT/cpu_csr_towb_cb
add wave -noupdate -group Top /main/DUT/cpu_gpio_out
add wave -noupdate -group Top /main/DUT/rst_n_ref
add wave -noupdate -group Top /main/DUT/host_remapped_in
add wave -noupdate -group Top /main/DUT/host_remapped_out
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/clk_i
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/rst_n_i
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/stat_o
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/inb_i
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/inb_o
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/outb_i
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/outb_o
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/out_discard_i
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/mem_raddr
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/mem_waddr
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/mem_wdata
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/mem_rdata_in
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/mem_rdata_out
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/rd_ptr
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/wr_ptr
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/occupied
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/words_written
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/mem_we
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/full
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/empty
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/wr_state
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/rd_state
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/in_claim
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/in_purge
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/in_ready
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/in_enqueue
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/in_commit
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/in_cmd_wr
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/in_stat_rd
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/out_cmd_wr
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/out_stat_rd
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/status
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/out_discard
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/out_purge
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/q_read
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/q_write
add wave -noupdate -expand -group OutSlot0 /main/DUT/U_Host_MQ/gen_outgoing_slots(0)/U_Out_SlotX/n_words_last
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/clk_i
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/rst_n_i
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/si_slave_i
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/si_slave_o
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/host_slave_i
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/host_slave_o
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/host_irq_o
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/hmq_status_o
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/si_incoming_in
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/host_incoming_in
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/si_incoming_out
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/host_incoming_out
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/si_outgoing_in
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/host_outgoing_in
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/si_outgoing_out
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/host_outgoing_out
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/incoming_stat
add wave -noupdate -expand -group HMQ -expand -subitemconfig {/main/DUT/U_Host_MQ/outgoing_stat(0) -expand} /main/DUT/U_Host_MQ/outgoing_stat
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/hmq_status
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/irq_config
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/tmr_div
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/tmr_tick
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/tmr_timeout
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/irq_vec_in
add wave -noupdate -expand -group HMQ /main/DUT/U_Host_MQ/irq_vec_out
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {175218 ns} 0}
configure wave -namecolwidth 282
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ns
update
WaveRestoreZoom {173892 ns} {176452 ns}
......@@ -88,122 +88,34 @@ module main;
.clk_i (DUT.clk_sys),
.rst_n_i (DUT.rst_n_sys));
IMockTurtleIRQ IrqMonitor (`MT_ATTACH_IRQ(DUT.U_Mock_Turtle));
// MT base (after VME sdb and vic).
const uint64_t base = 'h2_0000;
string fw = "../../../demos/hello_world/firmware/fw-01/fw-hello.bin";
uint64_t count;
const uint64_t mt_base = 'h2_0000;
task automatic inc_counter(ref CWishboneAccessor acc);
uint64_t val;
acc.read(base + 32'h1_0000, val);
if (val != count)
begin
$display("incorrect count (%x, expect %x)", val, count);
$stop;
end
count++;
acc.write(base + 32'h1_0000, count);
endtask
MockTurtleDriver drv;
initial begin
static string fw = "../../../tests/firmware/sim-verif/sim-verif.bin";
CWishboneAccessor acc;
MockTurtleDriver drv;
@(posedge DUT.rst_n_sys);
@(posedge DUT.clk_sys);
acc = Host.get_accessor();
acc.set_mode (PIPELINED);
// MT is mapped at 128kB on the VME wishbone port
drv = new(acc, base);
drv = new (Host.get_accessor(), mt_base, IrqMonitor);
drv.init();
$display("Display config rom");
drv.cfg_rom_display();
drv.enable_console_irq (0, 1);
$display("Loading binary for cpu #0");
drv.load_firmware(0, fw, 1'b0);
$display("Start cpu #0 at %t", $time);
drv.reset_core(0, 0);
// Enable all console interrupts
drv.m_csr.writel(`ADDR_MT_CPU_CSR_DBG_IMSK, 8'hff);
// Enable HMQ IN irqs.
drv.m_hmq.gcr_write(`MQUEUE_GCR_IRQ_MASK, 8'hff);
// Enable VIC interrupts (unmask)
acc.write(32'h2008, 8'hff);
count = 0;
forever begin
uint32_t val;
uint64_t risr;
// Read VIC RISR
acc.read(32'h2004, risr);
if (risr[2])
drv.m_csr.check_consoles();
// Check notify interrupt
if (risr[3])
begin
drv.m_csr.readl(`ADDR_MT_CPU_CSR_INT, val);
if (val != 0)
begin
// Read counter for cpu #0 (in smem)
inc_counter(acc);
$display("Notify interrupts: %x, count: %d", val, count);
drv.m_csr.writel(`ADDR_MT_CPU_CSR_INT, val);
end
end
// Check HMQ IN
if (risr[0])
begin
drv.m_hmq.gcr_read(`MQUEUE_GCR_SLOT_STATUS, val);
$display("HMQ IN irq: %x", val);
if ((val & 16'hff) != 0)
begin
uint32_t stat;
uint32_t len;
uint32_t dat;
$display("HMQ GCR status: %x", val);
drv.m_hmq.incoming_read (`MQUEUE_SLOT_STATUS, stat );
$display(" SLOT status: %x", stat);
drv.m_hmq.incoming_read (`MQUEUE_SLOT_HEADER + 0, len);
$display(" SLOT header: %x", len);
len = 2;
drv.m_hmq.outgoing_write(`MQUEUE_SLOT_COMMAND,
`MQUEUE_CMD_CLAIM );
drv.m_hmq.outgoing_write(`MQUEUE_SLOT_HEADER, len);
for (int i = 0; i < len; i++)
begin
drv.m_hmq.incoming_read(`MQUEUE_SLOT_DATA + 4*i, dat);
$display(" SLOT data[%d]: %x", i, dat);
drv.m_hmq.outgoing_write(`MQUEUE_SLOT_DATA + 4*i, ~dat);
end
inc_counter(acc);
drv.m_hmq.incoming_write(`MQUEUE_SLOT_COMMAND,
`MQUEUE_CMD_DISCARD );
drv.m_hmq.outgoing_write(`MQUEUE_SLOT_COMMAND,
`MQUEUE_CMD_READY );
end
end
drv.update ();
#1us;
end
end
end // initial begin
endmodule // main
......@@ -34,7 +34,6 @@ test_notify (void)
{
unsigned int v;
puts("#2 notify irq\n");
v = counts[cpu];
lr_writel(1, MT_CPU_LR_REG_HOST_INT);
while ((lr_readl(MT_CPU_LR_REG_HOST_INT) & (1 << cpu)) != 0)
......@@ -130,7 +129,11 @@ main(void)
puts("#1 console\n");
test_notify();
lr_writel(1, MT_CPU_LR_REG_HOST_INT);
puts("#2 notify irq\n");
for (int i = 0; i < 10; i++)
test_notify();
test_rmq();
......
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