Commit 74004b07 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

testbench: SystemVerilog RT+HDL testbench, all tests passing

parent a3af67a7
*.*~
*.*#
transcript
vsim.wlf
\ No newline at end of file
/*
* This program source code file is part of MasterFip project.
*
* Copyright (C) 2013-2017 CERN
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* logger.svh - implementation of test result logging classes */
`ifndef __LOGGER_SVH
`define __LOGGER_SVH
`include "serializable.svh"
// converts an array of bytes to a string with given format
function automatic string array2str(string fmt, uint8_t data[$]);
string rv ="";
for(int i =0 ;i<data.size();i++)
rv = {rv, $sformatf(fmt, data[i]) };
return rv;
endfunction // str
// represents a single test log:
class UnitTestMessage;
string m_msg;
int m_slot;
function new ( int slot, string msg );
m_msg = msg;
m_slot = slot;
endfunction // new
endclass // UnitTestMessage
typedef enum
{
TR_UNKNOWN,
TR_FAIL,
TR_PASS
} TestResult;
// represents a single test log:
class UnitTest;
// test ID
int m_id;
// final result (failure, pass, unknown)
TestResult m_result;
// name of the test
string m_name;
// detailed reason for the failure
string m_failureReason;
// message buffer
UnitTestMessage m_messages[$];
function automatic void msg( int slot, string str );
UnitTestMessage m = new( slot, str );
m_messages.push_back(m);
endfunction // msg
function new ( int id, string name );
m_id = id;
m_name = name;
m_result = TR_UNKNOWN;
endfunction // new
endclass // UnitTest
// class Logger
//
// A singleton class that handles all test result logging activities.
class Logger;
int m_id;
protected static Logger m_self;
protected int m_loggerId;
protected UnitTest m_currentTest;
protected UnitTest m_tests[$];
protected int m_passedTests;
protected int m_failedTests;
function new ( string log_file, int id = -1 );
m_id = 1;
m_loggerId = id;
m_currentTest = null;
m_passedTests = 0;
m_failedTests = 0;
endfunction
// returns the singleton instance
static function Logger get();
if (m_self == null) begin
m_self = new( "sim_log.txt" );
end
return m_self;
endfunction // get
// begins a test
function automatic void startTest( string name );
m_currentTest = new( m_id, name );
m_tests.push_back(m_currentTest);
$display("[*] Running test %d: %s", m_id, name);
m_id++;
endfunction // startTest
// marks the current test as passed
function automatic void pass();
if( m_currentTest.m_result == TR_UNKNOWN)
begin
$display("[*] Test %d PASSED", m_id);
m_currentTest.m_result = TR_PASS;
end
endfunction // pass
// marks the current test as failed
function automatic void fail ( string reason );
$display("[*] Test %d FAILED: %s", m_id, reason);
m_currentTest.m_result = TR_FAIL;
m_currentTest.m_failureReason = reason;
endfunction
// logs a message within the scope of the current test
function automatic void msg ( int slot, string m );
if(m_currentTest)
m_currentTest.msg(slot, m);
$display(" %s", m);
endfunction // msg
function automatic int getPassedTestCount();
automatic int cnt = 0;
foreach(m_tests[i])
if (m_tests[i].m_result == TR_PASS)
cnt++;
return cnt;
endfunction // getPassedTestCount
function automatic int getFailedTestCount();
automatic int cnt = 0;
foreach(m_tests[i])
if (m_tests[i].m_result == TR_FAIL)
cnt++;
return cnt;
endfunction // getPassedTestCount
function automatic void fprint(int fd, string str);
$fdisplay(fd, str);
$display(str);
endfunction // fprint
function automatic string getSystemDate();
automatic int fd;
string t;
void'($system("date +%X--%x > sys_time.tmp"));
fd = $fopen("sys_time.tmp","r");
void'($fscanf(fd,"%s",t));
$fclose(fd);
void'($system("rm sys_time.tmp"));
return t;
endfunction // getSystemDate
function automatic void writeTestReport( string filename );
automatic int fd = $fopen(filename,"wb");
fprint(fd, "MasterFIP SV Test Report");
fprint(fd, $sformatf("Test date: %s\n\n", getSystemDate() ));
fprint(fd, "Test Summary ");
fprint(fd, "-------------");
fprint(fd, $sformatf("%-02d tests PASSED", getPassedTestCount() ) );
fprint(fd, $sformatf("%-02d tests FAILED", getFailedTestCount() ) );
fprint(fd, "\nIndividual Test Results:" );
fprint(fd, "ID | Test Name | Status | Failure Reason" );
fprint(fd, "----------------------------------------------------------------------------------------------------------" );
foreach(m_tests[i])
begin
fprint(fd, $sformatf("%-3d | %-74s | %-6s | %s" , m_tests[i].m_id, m_tests[i].m_name, m_tests[i].m_result == TR_PASS ? "PASS" : "FAIL", m_tests[i].m_failureReason ) );
end
fprint(fd,"\n\n");
foreach(m_tests[i])
begin
automatic UnitTest test = m_tests[i];
$fdisplay(fd, "Test messages for test %d", test.m_id );
$fdisplay(fd, "---------------------------\n" );
foreach(test.m_messages[j])
begin
$fdisplay(fd, test.m_messages[j].m_msg);
end
$fdisplay(fd, "\n---------------------------\n" );
end
endfunction
endclass // Logger
class LoggerClient;
function automatic void startTest( string name );
automatic Logger l = Logger::get();
l.startTest( name );
endfunction // startTest
function automatic void pass();
automatic Logger l = Logger::get();
l.pass();
endfunction // pass
function automatic void fail ( string reason );
automatic Logger l = Logger::get();
l.fail(reason);
endfunction
function automatic void msg ( int slot, string m );
automatic Logger l = Logger::get();
l.msg(slot, m);
endfunction // msg
endclass // LoggerClient
`endif // `ifndef __LOGGER_SVH
`ifndef __MOCK_TURTLE_DRIVER_INCLUDED
`define __MOCK_TURTLE_DRIVER_INCLUDED
`include "simdrv_defs.svh"
`include "mt_cpu_csr_driver.svh"
`include "mt_mqueue_host_driver.svh"
class MockTurtleDriver;
protected CBusAccessor m_acc;
protected uint64_t m_base;
protected NodeCPUControl m_cpu_csr;
protected MQueueHost m_hmq;
function NodeCPUControl CPUs();
return m_cpu_csr;
endfunction // CPUs
function MQueueHost HMQ();
return m_hmq;
endfunction // CPUs
function new ( CBusAccessor acc, uint64_t base );
m_acc = acc;
m_base = base;
endfunction // new
task automatic init();
m_cpu_csr = new ( m_acc, m_base + 'hc000 );
m_hmq = new ( m_acc, m_base + 'h0000 );
m_cpu_csr.init();
m_hmq.init();
endtask // init
// polls HMQ and Debug UART
task automatic update();
m_cpu_csr.update();
m_hmq.update();
endtask // update
endclass // MockTurtleDriver
`endif // `ifndef __MOCK_TURTLE_DRIVER_INCLUDED
`include "wrn_cpu_csr_regs.vh"
typedef class NodeCPUDbgQueue;
`define SMEM_OP_DIRECT 0
`define SMEM_OP_ADD 1
`define SMEM_OP_SUB 2
class NodeCPUControl;
protected CBusAccessor bus;
protected uint32_t base;
protected uint32_t core_count ,app_id;
protected uint32_t core_memsizes[$];
// NodeCPUDbgQueue dbgq [$];
NodeCPUDbgQueue dbgq [$];
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
function uint32_t getCoreMemorySize(int core);
return core_memsizes[core];
endfunction // getCoreMemorySize
task writel ( uint32_t r, uint32_t v );
bus.write ( base + r, v );
endtask // _write
task readl ( uint32_t r, ref uint32_t v );
uint64_t tmp;
bus.read (base + r, tmp );
v= tmp;
endtask // readl
task init();
int i;
readl(`ADDR_WRN_CPU_CSR_APP_ID, app_id);
readl(`ADDR_WRN_CPU_CSR_CORE_COUNT, core_count);
core_count&='hf;
for(i=0;i<core_count;i++)
begin
NodeCPUDbgQueue q = new ( this, i );
dbgq.push_back (q);
end
for(i=0;i<core_count;i++)
begin
uint32_t memsize;
writel(`ADDR_WRN_CPU_CSR_CORE_SEL, i);
readl(`ADDR_WRN_CPU_CSR_CORE_MEMSIZE, memsize);
core_memsizes.push_back( memsize );
end
endtask // init
task reset_core(int core, int reset);
uint32_t rstr;
readl(`ADDR_WRN_CPU_CSR_RESET, rstr);
if(reset)
rstr |= (1<<core);
else
rstr &= ~(1<<core);
writel(`ADDR_WRN_CPU_CSR_RESET, rstr);
endtask // enable_cpu
task debug_int_enable(int core, int enable);
uint32_t imsk;
readl(`ADDR_WRN_CPU_CSR_DBG_IMSK, imsk);
if(enable)
imsk |= (1<<core);
else
imsk &= ~(1<<core);
writel(`ADDR_WRN_CPU_CSR_DBG_IMSK, imsk);
endtask // debug_int_enable
task load_firmware(int core, string filename);
integer f = $fopen(filename,"r");
uint32_t q[$];
int n, i;
reset_core(core, 1);
writel(`ADDR_WRN_CPU_CSR_CORE_SEL, core);
while(!$feof(f))
begin
int addr, data;
string cmd;
$fscanf(f,"%s %08x %08x", cmd,addr,data);
if(cmd == "write")
begin
writel(`ADDR_WRN_CPU_CSR_UADDR, addr);
writel(`ADDR_WRN_CPU_CSR_UDATA, data);
q.push_back(data);
n++;
end
end
endtask // load_firmware
task load_firmware_bin(int core, string filename);
integer f = $fopen(filename,"r");
uint32_t q[$];
int addr = 0;
reset_core(core, 1);
writel(`ADDR_WRN_CPU_CSR_CORE_SEL, core);
while(!$feof(f))
begin
uint32_t data;
$fread(data, f);
writel(`ADDR_WRN_CPU_CSR_UADDR, addr);
writel(`ADDR_WRN_CPU_CSR_UDATA, data);
q.push_back(data);
addr ++;
end
endtask
task update();
int i;
for(i=0;i<core_count;i++)
begin
dbgq[i].update();
end
endtask // update
task set_smem_op(int op);
writel(`ADDR_WRN_CPU_CSR_SMEM_OP, op);
endtask // set_smem_op
endclass
class NodeCPUDbgQueue;
protected NodeCPUControl cctl;
protected int core_id;
int queue[$];
function new ( NodeCPUControl cctl_, int core_id_);
cctl = cctl_;
core_id = core_id_;
endfunction // new
task automatic update();
automatic uint32_t rval;
automatic string s;
cctl.readl(`ADDR_WRN_CPU_CSR_DBG_POLL , rval);
if(! (rval & (1<<core_id)))
return;
cctl.writel(`ADDR_WRN_CPU_CSR_CORE_SEL, core_id);
cctl.readl(`ADDR_WRN_CPU_CSR_DBG_MSG, rval);
queue.push_back(rval);
if(rval == 0 || rval == 13 || rval == 10)
begin
foreach(queue[i])
if(queue[i] != 0 && queue[i] != 13 && queue[i] != 10)
s = $sformatf("%s%c", s, queue[i]);
else
s = $sformatf("%s ", s);
$display("DBG RX: %s", s );
queue='{};
end
endtask // update
endclass // NodeCPUDbgQueue
This diff is collapsed.
`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
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
// reset
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
`ifndef __VHD_WISHBONE_MASTER_INCLUDED
`define __VHD_WISHBONE_MASTER_INCLUDED
`include "simdrv_defs.svh"
`include "if_wb_master.svh"
import wishbone_pkg::*;
interface IVHDWishboneMaster
(
input clk_i,
input rst_n_i
);
parameter g_addr_width = 32;
parameter g_data_width = 32;
typedef virtual IWishboneMaster VIWishboneMaster;
IWishboneMaster #(g_addr_width, g_data_width) TheMaster (clk_i, rst_n_i);
t_wishbone_master_in in;
t_wishbone_master_out out;
modport master
(
input in,
output out
);
assign out.cyc = TheMaster.cyc;
assign out.stb = TheMaster.stb;
assign out.we = TheMaster.we;
assign out.sel = TheMaster.sel;
assign out.adr = TheMaster.adr;
assign out.dat = TheMaster.dat_o;
assign TheMaster.ack = in.ack;
assign TheMaster.stall = in.stall;
assign TheMaster.rty = in.rty;
assign TheMaster.err = in.err;
assign TheMaster.dat_i = in.dat;
function automatic CWishboneAccessor get_accessor();
automatic CWishboneAccessor acc = TheMaster.get_accessor();
return acc;
endfunction // get_accessor
initial begin
@(posedge rst_n_i);
@(posedge clk_i);
TheMaster.settings.addr_gran = BYTE;
TheMaster.settings.cyc_on_stall = 1;
end
endinterface // IVHDWishboneMaster
`endif // `ifndef __VHD_WISHBONE_MASTER_INCLUDED
interface IWishboneLink;
parameter g_data_width = 32;
parameter g_addr_width = 32;
wire [g_addr_width - 1 : 0] adr;
wire [g_data_width - 1 : 0] dat_o;
wire [g_data_width - 1 : 0] dat_i;
wire [(g_data_width/8)-1 : 0] sel;
wire ack;
wire stall;
wire err;
wire rty;
wire cyc;
wire stb;
wire we;
modport slave
(
output adr,
output dat_o,
input dat_i,
output sel,
output cyc,
output stb,
output we,
input ack,
input stall,
input err,
input rty
);
modport master
(
input adr,
input dat_o,
output dat_i,
input sel,
input cyc,
input stb,
input we,
output ack,
output stall,
output err,
output rty
);
endinterface // IWishboneLink
This diff is collapsed.
`ifndef __IF_WISHBONE_SLAVE_SVH
`define __IF_WISHBONE_SLAVE_SVH
`timescale 1ns/1ps
`include "if_wishbone_types.svh"
interface IWishboneSlave
(
input clk_i,
input rst_n_i
);
parameter g_addr_width = 32;
parameter g_data_width = 32;
wire [g_addr_width - 1: 0] adr;
wire [g_data_width - 1: 0] dat_i;
wire [(g_data_width/8)-1 : 0] sel;
logic [g_data_width - 1 : 0] dat_o;
logic ack;
logic stall;
logic err;
logic rty;
wire cyc;
wire stb;
wire we;
time last_access_t = 0;
modport slave
(
input adr,
input dat_o,
input sel,
input cyc,
input stb,
input we,
output ack,
output dat_i,
output stall,
output err,
output rty
);
wb_cycle_t c_queue[$];
wb_cycle_t current_cycle;
reg cyc_prev;
int trans_index;
int first_transaction;
struct {
wb_cycle_type_t mode;
int gen_random_stalls;
int gen_random_errors;
int stall_min_duration;
int stall_max_duration;
real stall_prob;
real error_prob;
} settings;
int permanent_stall = 0;
function automatic int _poll(); return poll(); endfunction
function automatic int _permanent_stall_enable(); return permanent_stall_enable(); endfunction
function automatic int _permanent_stall_disable(); return permanent_stall_disable(); endfunction
task automatic _get(ref wb_cycle_t xfer); get(xfer); endtask
class CIWBSlaveAccessor extends CWishboneAccessor;
function automatic int poll();
return _poll();
endfunction
function automatic int permanent_stall_enable();
return _permanent_stall_enable();
endfunction
function automatic int permanent_stall_disable();
return _permanent_stall_disable();
endfunction
task get(ref wb_cycle_t xfer);
_get(xfer);
endtask
task clear();
endtask // clear
endclass // CIWBSlaveAccessor
function CIWBSlaveAccessor get_accessor();
CIWBSlaveAccessor tmp;
tmp = new;
return tmp;
endfunction // get_accessor
function automatic int permanent_stall_enable();
permanent_stall = 1;
$display("permanent stall ON");
return permanent_stall;
endfunction
function automatic int permanent_stall_disable();
permanent_stall = 0;
$display("permanent stall OFF");
return permanent_stall;
endfunction
function automatic int poll();
return c_queue.size() != 0;
endfunction // poll
task automatic get(ref wb_cycle_t xfer);
while(c_queue.size() <= 0)
@(posedge clk_i);
xfer = c_queue.pop_front();
endtask // pop_cycle
always@(posedge clk_i) cyc_prev <= cyc;
wire cyc_start = !cyc_prev && cyc;
wire cyc_end = cyc_prev && !cyc;
task gen_random_stalls();
static int stall_remaining = 0;
static int seed = 0;
// $display("stallr: %d\n", stall_remaining);
if(settings.gen_random_stalls && (probability_hit(settings.stall_prob) || stall_remaining > 0))
begin
if(stall_remaining == 0)
stall_remaining = $dist_uniform(seed,
settings.stall_min_duration,
settings.stall_max_duration);
if(stall_remaining)
stall_remaining--;
stall <= 1;
end else
stall <= 0;
endtask // gen_random_stalls
function automatic int count_ones(int x, int n_bits);
int i, cnt;
cnt = 0;
for(i=0;i<n_bits;i++) if(x & (1<<i)) cnt ++;
return cnt;
endfunction
function automatic int count_leading_zeroes(int x, int n_bits);
int i;
for(i=0;i<n_bits && !(x & (1<<i)); i++);
return i;
endfunction // count_leading_zeroes
function automatic int count_trailing_zeroes(int x, int n_bits);
int i;
for(i=n_bits-1;i>=0 && !(x & (1<<i)); i--);
return (n_bits-1-i);
endfunction
task pipelined_fsm();
// ML
if(permanent_stall)
stall <= 1;
else if(settings.gen_random_stalls)
gen_random_stalls();
else
stall <= 0;
/* -----\/----- EXCLUDED -----\/-----
if(cyc) begin
end else
stall <= 0;
-----/\----- EXCLUDED -----/\----- */
if(cyc_start) begin
current_cycle.data = {};
trans_index <= 0;
first_transaction = 1;
end
if(cyc_end) begin
c_queue.push_back(current_cycle);
end
if(cyc && settings.gen_random_errors && probability_hit(settings.error_prob))
err <= 1;
else
err <= 0;
if(stb && we && !stall && cyc) begin
int oc, lzc, tzc;
wb_xfer_t d;
oc = count_ones(sel, g_data_width/8);
lzc = count_leading_zeroes(sel, g_data_width/8);
tzc = count_trailing_zeroes(sel, g_data_width/8);
d.a = adr * (g_data_width / 8);
d.size = oc;
d.d = (dat_i>>(8*lzc)) & ((1<<(oc*8)) -1);
if(lzc + tzc + oc != g_data_width/8)
$error("IWishboneSlave [write a %x d %x sel %x]: non-contiguous sel", adr, dat_i, sel);
d.sel [g_data_width/8-1:0] = sel;
current_cycle.data.push_back(d);
// $display("ifWb:[%d] write a %x d %x sel %x",current_cycle.data.size(), adr, dat_i, sel);
ack <= 1;
end else if(stb && !we && !stall) begin
// $error("Sorry, no pipelined read for slave yet implemented");
ack <= 0;
end else
ack <= 0;
endtask // pipelined_fsm
always@(posedge clk_i)
begin
if(!rst_n_i)
begin
c_queue = {};
current_cycle.data = {};
trans_index = 0;
ack <= 0;
rty <= 0;
err <= 0;
dat_o <= 0;
stall <= 0;
end else begin
if(settings.mode == PIPELINED)
pipelined_fsm();
end
end
initial begin
settings.mode = PIPELINED;
settings.gen_random_stalls = 1;
settings.stall_prob = 0.1;
settings.stall_min_duration = 1;
settings.stall_max_duration = 2;
end
endinterface // IWishboneSlave
`endif
\ No newline at end of file
`ifndef IF_WISHBONE_ACCESSOR_SV
`define IF_WISHBONE_ACCESSOR_SV
`include "if_wishbone_types.svh"
virtual class CWishboneAccessor extends CBusAccessor;
static int _null = 0;
protected wb_cycle_type_t m_cycle_type;
function new();
m_cycle_type = CLASSIC;
m_default_xfer_size = 4;
endfunction // new
virtual task set_mode(wb_cycle_type_t mode);
m_cycle_type = mode;
endtask // set_mode
// [slave only] checks if there are any transactions in the queue
virtual function automatic int poll();
return 0;
endfunction // poll
// ML stuff [slave only]
virtual function automatic int permanent_stall_enable();
$display("CWisboneAccessor: permanent_stall: ON");
endfunction;
// ML stuff [slave only]
virtual function automatic int permanent_stall_disable();
$display("CWisboneAccessor: permanent_stall: OFF");
endfunction;
// [slave only] adds a simulation event (e.g. a forced STALL, RETRY, ERROR)
// evt = event type (STALL, ERROR, RETRY)
// behv = event behavior: DELAYED - event occurs after a predefined delay (dly_start)
// RANDOM - event occurs randomly with probability (prob)
// These two can be combined (random events occuring after a certain initial delay)
// DELAYED events can be repeated (rep_rate parameter)
virtual task add_event(wba_sim_event_t evt, wba_sim_behavior_t behv, int dly_start, real prob, int rep_rate);
endtask // add_event
// [slave only] gets a cycle from the queue
virtual task get(ref wb_cycle_t xfer);
endtask // get
// [master only] executes a cycle and returns its result
virtual task put(ref wb_cycle_t xfer);
endtask // put
virtual function int idle();
return 1;
endfunction // idle
// [master only] generic write(s), blocking
virtual task writem(uint64_t addr[], uint64_t data[], int size = 4, ref int result = _null);
wb_cycle_t cycle;
int i;
cycle.ctype = m_cycle_type;
cycle.rw = 1'b1;
for(i=0;i < addr.size(); i++)
begin
wb_xfer_t xfer;
xfer.a = addr[i];
xfer.d = data[i];
xfer.size = size;
cycle.data.push_back(xfer);
end
// $display("DS: %d", cycle.data.size());
put(cycle);
get(cycle);
result = cycle.result;
endtask // write
// [master only] generic read(s), blocking
virtual task readm(uint64_t addr[], ref uint64_t data[],input int size = 4, ref int result = _null);
wb_cycle_t cycle;
int i;
cycle.ctype = m_cycle_type;
cycle.rw = 1'b0;
for(i=0;i < addr.size(); i++)
begin
wb_xfer_t xfer;
xfer.a = addr[i];
xfer.size = size;
cycle.data.push_back(xfer);
end
put(cycle);
get(cycle);
for(i=0;i < addr.size(); i++)
data[i] = cycle.data[i].d;
result = cycle.result;
endtask // readm
virtual task read(uint64_t addr, ref uint64_t data, input int size = 4, ref int result = _null);
uint64_t aa[], da[];
aa = new[1];
da = new[1];
aa[0] = addr;
readm(aa, da, size, result);
data = da[0];
endtask
virtual task write(uint64_t addr, uint64_t data, int size = 4, ref int result = _null);
uint64_t aa[], da[];
aa = new[1];
da = new[1];
aa[0] = addr;
da[0] = data;
writem(aa, da, size, result);
endtask
endclass // CWishboneAccessor
static int seed = 0;
function automatic int probability_hit(real prob);
real rand_val;
rand_val = real'($dist_uniform(seed, 0, 1000)) / 1000.0;
if(rand_val < prob)
return 1;
else
return 0;
endfunction // probability_hit
`endif // `ifndef IF_WISHBONE_ACCESSOR_SV
//
// Title : Software Wishbone master unit for testbenches
//
// File : wishbone_master_tb.v
// Author : Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
// Created : Tue Mar 23 12:19:36 2010
// Standard : Verilog 2001
//
`ifndef __IF_WB_DEFS_SV
`define __IF_WB_DEFS_SV
`include "simdrv_defs.sv"
typedef enum
{
R_OK = 0,
R_ERROR,
R_RETRY
} wb_cycle_result_t;
typedef enum
{
CLASSIC = 0,
PIPELINED = 1
} wb_cycle_type_t;
typedef struct {
uint64_t a;
uint64_t d;
bit[7:0] sel;
int size;
} wb_xfer_t;
typedef struct {
int rw;
wb_cycle_type_t ctype;
wb_xfer_t data[$];
wb_cycle_result_t result;
} wb_cycle_t;
virtual class CWishboneAccessor;
virtual function automatic int poll();
return 0;
endfunction // poll
virtual task get(output wb_cycle_t xfer);
endtask // get
virtual task put(input wb_cycle_t xfer);
endtask // put
virtual function int idle();
return 0;
endfunction // idle
virtual task clear(); endtask
endclass // CWishboneAccessor
int seed = 0;
function automatic int probability_hit(real prob);
real rand_val;
rand_val = real'($dist_uniform(seed, 0, 1000)) / 1000.0;
if(rand_val < prob)
return 1;
else
return 0;
endfunction // probability_hit
`endif // `ifndef __IF_WB_DEFS_SV
//
// Title : Pipelined Wishbone BFM - type definitions
//
// File : if_wishbone_types.sv
// Author : Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
// Created : Tue Mar 23 12:19:36 2010
// Standard : Verilog 2001
//
`ifndef __IF_WB_TYPES_SVH
`define __IF_WB_TYPES_SVH
`include "simdrv_defs.svh"
typedef enum
{
R_OK = 0,
R_ERROR,
R_RETRY
} wb_cycle_result_t;
typedef enum
{
CLASSIC = 0,
PIPELINED = 1
} wb_cycle_type_t;
typedef enum {
WORD = 0,
BYTE = 1
} wb_address_granularity_t;
typedef struct {
uint64_t a;
uint64_t d;
int size;
bit [7:0] sel;
} wb_xfer_t;
typedef struct {
int rw;
wb_cycle_type_t ctype;
wb_xfer_t data[$];
wb_cycle_result_t result;
} wb_cycle_t;
typedef enum
{
RETRY = 0,
STALL,
ERROR
} wba_sim_event_t;
typedef enum
{
RANDOM = (1<<0),
DELAYED = (1<<1)
} wba_sim_behavior_t;
`endif // `ifndef __IF_WB_TYPES_SVH
`ifndef SIMDRV_DEFS_SV
`define SIMDRV_DEFS_SV 1
typedef longint unsigned uint64_t;
typedef int unsigned uint32_t;
typedef shortint unsigned uint16_t;
typedef uint64_t u64_array_t[];
typedef byte byte_array_t[];
virtual class CBusAccessor;
static int _null = 0;
int m_default_xfer_size;
task set_default_xfer_size(int default_size);
m_default_xfer_size = default_size;
endtask // set_default_xfer_size
pure virtual task writem(uint64_t addr[], uint64_t data[], input int size, ref int result);
pure virtual task readm(uint64_t addr[], ref uint64_t data[], input int size, ref int result);
virtual task read(uint64_t addr, ref uint64_t data, input int size = m_default_xfer_size, ref int result = _null);
int res;
uint64_t aa[1], da[];
da= new[1];
aa[0] = addr;
readm(aa, da, size, res);
data = da[0];
endtask
virtual task write(uint64_t addr, uint64_t data, input int size = m_default_xfer_size, ref int result = _null);
uint64_t aa[1], da[1];
aa[0] = addr;
da[0] = data;
writem(aa, da, size, result);
endtask
endclass // CBusAccessor
class CSimUtils;
static function automatic u64_array_t pack(byte x[], int size, int big_endian = 1);
u64_array_t tmp;
int i, j;
int nwords, nbytes;
nwords = (x.size() + size - 1) / size;
tmp = new [nwords];
for(i=0;i<nwords;i++)
begin
uint64_t d;
d =0;
nbytes = (x.size() - i * nbytes > size ? size : x.size() - i*nbytes);
for(j=0;j<nbytes;j++)
begin
if(big_endian)
d = d | ((x[i*size+j] << (8*(size-1-j))));
else
d = d | ((x[i*size+j] << (8*j)));
end
tmp[i] = d;
end
return tmp;
endfunction // pack
static function automatic byte_array_t unpack(u64_array_t x, int entry_size, int size, int big_endian = 1);
byte_array_t tmp;
int i, n;
tmp = new[size];
n = 0;
i = 0;
while(n < size)
begin
tmp[n] = x[i] >> (8*(entry_size-1 - (n % entry_size)));
n++;
if(n % entry_size == 0)
i++;
end
return tmp;
endfunction // unpack
endclass // CSimUtils
static CSimUtils SimUtils;
`endif
\ No newline at end of file
`define ADDR_WRN_CPU_CSR_APP_ID 6'h0
`define ADDR_WRN_CPU_CSR_RESET 6'h4
`define ADDR_WRN_CPU_CSR_ENABLE 6'h8
`define ADDR_WRN_CPU_CSR_UADDR 6'hc
`define WRN_CPU_CSR_UADDR_ADDR_OFFSET 0
`define WRN_CPU_CSR_UADDR_ADDR 32'h000fffff
`define ADDR_WRN_CPU_CSR_CORE_SEL 6'h10
`define ADDR_WRN_CPU_CSR_CORE_COUNT 6'h14
`define ADDR_WRN_CPU_CSR_CORE_MEMSIZE 6'h18
`define ADDR_WRN_CPU_CSR_UDATA 6'h1c
`define ADDR_WRN_CPU_CSR_DBG_JTAG 6'h20
`define WRN_CPU_CSR_DBG_JTAG_JDATA_OFFSET 0
`define WRN_CPU_CSR_DBG_JTAG_JDATA 32'h000000ff
`define WRN_CPU_CSR_DBG_JTAG_JADDR_OFFSET 8
`define WRN_CPU_CSR_DBG_JTAG_JADDR 32'h00000700
`define WRN_CPU_CSR_DBG_JTAG_RSTN_OFFSET 16
`define WRN_CPU_CSR_DBG_JTAG_RSTN 32'h00010000
`define WRN_CPU_CSR_DBG_JTAG_TCK_OFFSET 17
`define WRN_CPU_CSR_DBG_JTAG_TCK 32'h00020000
`define WRN_CPU_CSR_DBG_JTAG_UPDATE_OFFSET 18
`define WRN_CPU_CSR_DBG_JTAG_UPDATE 32'h00040000
`define ADDR_WRN_CPU_CSR_DBG_MSG 6'h24
`define WRN_CPU_CSR_DBG_MSG_DATA_OFFSET 0
`define WRN_CPU_CSR_DBG_MSG_DATA 32'h000000ff
`define ADDR_WRN_CPU_CSR_DBG_POLL 6'h28
`define WRN_CPU_CSR_DBG_POLL_READY_OFFSET 0
`define WRN_CPU_CSR_DBG_POLL_READY 32'h000000ff
`define ADDR_WRN_CPU_CSR_DBG_IMSK 6'h2c
`define WRN_CPU_CSR_DBG_IMSK_ENABLE_OFFSET 0
`define WRN_CPU_CSR_DBG_IMSK_ENABLE 32'h000000ff
`define ADDR_WRN_CPU_CSR_SMEM_OP 6'h30
sim_tool = "modelsim"
sim_top="main"
top_module="main"
action = "simulation"
target = "xilinx"
fetchto = "../../ip_cores"
vcom_opt="-mixedsvvh l"
vlog_opt = "+incdir+../include +incdir+. +incdir+../include/wb"
syn_device="xc6slx150t"
include_dirs=["../include/wb", "../include" ]
files = [ "main.sv" ]
modules = { "local" : [ "../../top/spec" ] }
This diff is collapsed.
/*
* This program source code file is part of MasterFip project.
*
* Copyright (C) 2013-2017 CERN
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/*
fip_device.svh - implementation of the FipDevice class, representing
an abstract model of a device speaking WorldFIP protocol
*/
`ifndef __FIP_DEVICE_MODEL_INCLUDED
`define __FIP_DEVICE_MODEL_INCLUDED
`include "fip_phy_model.svh"
`include "logger.svh"
typedef class FipFrame;
class FipDevice extends LoggerClient;
// PHY interface the device is connected to
virtual FipPHY m_phy;
task automatic attach (virtual FipPHY phy );
m_phy = phy;
m_phy.setHandler(this);
endtask // attachInterface
virtual task automatic send ( FipFrame frame );
m_phy.send(frame);
endtask // send
virtual task automatic onReceive( FipFrame frame );
endtask // onReceive
virtual task automatic onPreamble();
endtask // onReceive
function automatic bit isIdle();
return m_phy.isIdle();
endfunction // isIdle
task automatic setSpeed( int speed );
m_phy.setSpeed( speed );
endtask // setSpeed
function automatic longint getTurnaroundTime();
return m_phy.getTurnaroundTime();
endfunction // getTurnaroundTime
function automatic longint getSilenceTime();
return m_phy.getSilenceTime();
endfunction // getTurnaroundTime
endclass // FipDevice
`endif // `ifndef __FIP_DEVICE_MODEL_INCLUDED
This diff is collapsed.
`ifndef __FIP_HARDWARE_MODEL_INCLUDED
`define __FIP_HARDWARE_MODEL_INCLUDED
interface FIPBus;
wire p;
wire n;
// fieldrive-side port
modport fd
(
inout p,
inout n
);
// agent-side port
modport bus
(
inout p,
inout n
);
endinterface // FIPBus
interface FieldriveFPGA;
logic fd_rxcdn;
logic fd_rxd;
logic fd_txer;
logic fd_wdgn;
logic fd_rstn;
logic fd_txck;
logic fd_txd;
logic fd_txena;
logic [1:0] speed;
logic ext_sync;
// fieldrive side
modport fd
(
input fd_rxcdn,
input fd_rxd,
input fd_txer,
input fd_wdgn,
output fd_rstn,
output fd_txck,
output fd_txd,
output fd_txena,
input speed
);
// FPGA side
modport fpga
(
output fd_rxcdn,
output fd_rxd,
output fd_txer,
output fd_wdgn,
input fd_rstn,
input fd_txck,
input fd_txd,
input fd_txena,
output speed,
output ext_sync
);
endinterface // FieldriveFPGA
interface FieldriveModel
(
FieldriveFPGA.fd fpga,
FIPBus.fd fip
);
task setSpeed( int s );
case(s)
31250:
fpga.speed = 0;
1000000:
fpga.speed = 1;
2500000:
fpga.speed = 2;
endcase // case (s)
endtask // setSpeed
reg tx_reg = 0;
reg txen_reg = 0;
initial begin
fpga.fd_txer = 0;
fpga.fd_wdgn = 1;
end
always@(fpga.fd_rstn)
if(!fpga.fd_rstn)
begin
tx_reg <= 0;
txen_reg <= 0;
fpga.fd_wdgn <= 1;
end
always@(posedge fpga.fd_txck)
begin
tx_reg <= fpga.fd_txd;
txen_reg <= fpga.fd_txena;
end
// fixme: comment
always@*
if ((fip.p == 1'b1 && fip.n == 1'b0) || (fip.p == 1'b0 && fip.n == 1'b1))
fpga.fd_rxcdn <= 0;
else
fpga.fd_rxcdn <= 1;
reg bus_error = 0;
reg force_txer = 0;
always@*
if(!force_txer)
fpga.fd_txer <= ( fip.p === 1'bx || fip.n === 1'bx);
else
fpga.fd_txer <= 1;
task forceTxError ( bit err );
force_txer <= err;
endtask // forceTxError
task forceWatchdogError ();
fpga.fd_wdgn <= 0;
#1;
endtask // forceWatchdogReset
assign fpga.fd_rxd = !fpga.fd_rxcdn ? fip.p : 1'b0;
// assign fpga.fd_txer = ;
assign fip.p = (txen_reg ? tx_reg : 1'bz);
assign fip.n = (txen_reg ? ~tx_reg : 1'bz);
// assign fpga.fd_wdgn = 1'b1;
endinterface // FieldriveModel
interface MasterfipMezzanine
(
FieldriveFPGA.fpga fpga,
FIPBus.fd fip
);
FieldriveModel U_Fieldrive
( fpga, fip );
initial begin
fpga.ext_sync = 0;
end
task automatic setSpeed ( int bitrate );
case (bitrate)
31250: fpga.speed = 0;
1000000: fpga.speed = 1;
2500000: fpga.speed = 2;
endcase // case (bitrate)
endtask // setSpeed
task automatic pulseTrigger();
fpga.ext_sync <= 1;
#1us;
fpga.ext_sync <= 0;
#1;
endtask // pulseTrigger
function automatic int getSpeed();
case (fpga.speed)
0: return 31250;
1: return 1000000;
2: return 2500000;
endcase // case (bitrate)
endfunction // getSpeed
endinterface // MasterfipMezzanine
`endif
`ifndef __FIP_MONITOR_DEVICE_SVH
`define __FIP_MONITOR_DEVICE_SVH
`include "fip_device.svh"
class FipMonitorDevice extends FipDevice;
protected FipFrameList m_frames;
function automatic FipFrameList getFrames();
return m_frames;
endfunction // getFrames
virtual task automatic onReceive ( FipFrame frame );
Logger l = Logger::get();
m_frames.push_back( frame );
l.msg(0, $sformatf("----[%.1f us] > %s", real'(frame.getStartTime()) / real'(1us), frame.str() ) );
// m_phy.setVerbose(1);
endtask // onReceive
virtual task automatic clear();
m_frames = '{};
endtask // clear
endclass // FipMonitorDevice
`endif
This diff is collapsed.
`ifndef __FIP_VIRTUAL_MASTER_SVH
`define __FIP_VIRTUAL_MASTER_SVH
`include "fip_frame.svh"
`include "fip_device.svh"
class FipVirtualTransfer;
protected bit m_is_send;
protected FipFrame m_frame;
function new ( bit isSend, FipFrame theFrame = null );
m_is_send = isSend;
m_frame = theFrame;
endfunction // new
function automatic bit isSend();
return m_is_send;
endfunction // isSend
function automatic FipFrame getFrame();
return m_frame;
endfunction // getFrame
task automatic setFrame( FipFrame frame );
m_frame = frame;
endtask // setFrame
endclass
class Timeout;
protected time m_length, m_start_time;
function new ( time length );
m_length = length;
m_start_time = $time;
endfunction // new
function automatic int expired();
return ($time-m_start_time) >= m_length;
endfunction // expired
task automatic waitExpire();
while(!expired())
#100ns;
endtask // waitExpire
endclass // Timeout
class FipVirtualMaster extends FipDevice;
protected FipVirtualTransfer m_xfers[$];
protected time m_silenceTime, m_turnaroundTime;
protected FipFrame m_lastRxFrame;
protected bit m_rxFrameReady, m_rxFramePreambleReady;
function new;
super.new;
endfunction // setTiming
task automatic setTiming( time silenceTime, time turnaroundTime);
m_silenceTime = silenceTime;
m_turnaroundTime = turnaroundTime;
endtask // setTiming
task automatic requestSend( FipFrame frame );
FipVirtualTransfer xfer = new( 1, frame );
m_xfers.push_back(xfer);
endtask // requestSend
task automatic expectRecv( int count );
int i;
for(i=0;i<count;i++)
begin
FipVirtualTransfer xfer = new (0);
m_xfers.push_back( xfer );
end
endtask // expectRecv
task automatic onReceive( FipFrame frame );
// $display("********************OnREceive [%x %x]", this, frame.getControl());
m_lastRxFrame = frame.copy();
m_rxFrameReady = 1;
endtask // onReceive
task automatic onPreamble( );
m_rxFramePreambleReady = 1;
endtask // onPreamble
task automatic waitTxIdle();
while(!isIdle())
#100ns;
endtask
task automatic runMacrocycle();
int i;
FipVirtualTransfer xfer;
for (i=0;i<m_xfers.size(); i++)
begin
automatic int prevIsSend = 0;
automatic int prevIsExpect = 0;
automatic int nextIsSend = 0;
if( i > 1 )
prevIsSend = m_xfers[i-1].isSend();
if( i > 1 )
prevIsExpect = !m_xfers[i-1].isSend();
if( i < m_xfers.size() - 1)
nextIsSend = m_xfers[i+1].isSend();
if( m_xfers[i].isSend() )
begin
FipFrame frame = m_xfers[i].getFrame();
// $display("VM: Sending %d/%d", i+1, m_xfers.size(), frame.size(), nextIsSend);
if( prevIsExpect )
begin
#(m_turnaroundTime);
end
send( frame ); // non-blocking
if( nextIsSend )
begin
waitTxIdle();
#(m_turnaroundTime);
end
end else begin // if ( m_xfers[i].isSend() )
// we expect a frame
Timeout tmo = new(m_silenceTime);
m_rxFrameReady = 0;
m_rxFramePreambleReady = 0;
while( !tmo.expired() )
begin
if( m_rxFramePreambleReady )
begin
while (! m_rxFrameReady )
#100ns;
m_xfers[i].setFrame(m_lastRxFrame);
break;
end
#100ns;
end
if(tmo.expired() && !m_rxFrameReady )
begin
// $error("Didn't receive expected frame\n");
end
m_rxFrameReady = 0;
m_rxFramePreambleReady = 0;
end // else: !if( m_xfers[i].isSend() )
end
waitTxIdle();
endtask // runMacrocycle
virtual task automatic configure();
endtask // configure
endclass // FipVirtualMaster
class FipTestVirtualMaster extends FipVirtualMaster;
function new;
super.new;
endfunction // setTiming
task automatic configure();
int i;
// periodic vars
// ID_DAT (0x0101) + RP_DAT (master produces)
requestSend( FipFrame::makeRaw( '{'h03, 'h01, 'h01 }) );
requestSend( FipFrame::makeRaw( '{'h02, 'h40, 'h41, 'h00, 'h01, 'h02, 'h03, 'h04, 'h05, 'h06, 'h07, 'h08, 'h09, 'h0a, 'h0b, 'h0c, 'h0d, 'h0e, 'h0f, 'h10, 'h11, 'h12, 'h13, 'h14, 'h15, 'h16, 'h17, 'h18, 'h19, 'h1a, 'h1b, 'h1c, 'h1d, 'h1e, 'h1f, 'h20, 'h21, 'h22, 'h23, 'h24, 'h25, 'h26, 'h27, 'h28, 'h29, 'h2a, 'h2b, 'h2c, 'h2d, 'h2e, 'h2f, 'h30, 'h31, 'h32, 'h33, 'h34, 'h35, 'h36, 'h37, 'h38, 'h39, 'h3a, 'h3b, 'h3c, 'h3d, 'h3e, 'h3f, 'h05 } ) );
// ID_DAT (0x015f) + RP_DAT (master produces)
requestSend( FipFrame::makeRaw( '{ 'h03, 'h01, 'h5f }) );
requestSend( FipFrame::makeRaw( '{ 'h02, 'h40, 'h03, 'h00, 'h01, 'h05 }) );
// ID_DAT (0x01b4) + RP_DAT (master produces)
requestSend( FipFrame::makeRaw( '{ 'h03, 'h01, 'hb4, 'h3e, 'h70 } ) );
requestSend( FipFrame::makeRaw( '{ 'h02, 'h40, 'h7d, 'h00, 'h01, 'h02, 'h03, 'h04, 'h05, 'h06, 'h07, 'h08, 'h09, 'h0a, 'h0b, 'h0c, 'h0d, 'h0e, 'h0f, 'h10, 'h11, 'h12, 'h13, 'h14, 'h15, 'h16, 'h17, 'h18, 'h19, 'h1a, 'h1b, 'h1c, 'h1d, 'h1e, 'h1f, 'h20, 'h21, 'h22, 'h23, 'h24, 'h25, 'h26, 'h27, 'h28, 'h29, 'h2a, 'h2b, 'h2c, 'h2d, 'h2e, 'h2f, 'h30, 'h31, 'h32, 'h33, 'h34, 'h35, 'h36, 'h37, 'h38, 'h39, 'h3a, 'h3b, 'h3c, 'h3d, 'h3e, 'h3f, 'h40, 'h41, 'h42, 'h43, 'h44, 'h45, 'h46, 'h47, 'h48, 'h49, 'h4a, 'h4b, 'h4c, 'h4d, 'h4e, 'h4f, 'h50, 'h51, 'h52, 'h53, 'h54, 'h55, 'h56, 'h57, 'h58, 'h59, 'h5a, 'h5b, 'h5c, 'h5d, 'h5e, 'h5f, 'h60, 'h61, 'h62, 'h63, 'h64, 'h65, 'h66, 'h67, 'h68, 'h69, 'h6a, 'h6b, 'h6c, 'h6d, 'h6e, 'h6f, 'h70, 'h71, 'h72, 'h73, 'h74, 'h75, 'h76, 'h77, 'h78, 'h79, 'h7a, 'h7b, 'h05} ) );
// ID_DAT (0x0201) + expect RP_DAT (slave 0x1 produces)
requestSend( FipFrame::makeRaw( '{ 'h03, 'h02, 'h01 } ) );
expectRecv(1);
// ID_DAT (0x025f) + expect RP_DAT (slave 0x5f produces)
requestSend( FipFrame::makeRaw( '{ 'h03, 'h02, 'h5f } ) );
expectRecv(1);
// ID_DAT (0x02b4) + expect RP_DAT (slave 0xb4 produces)
requestSend( FipFrame::makeRaw( '{ 'h03, 'h02, 'hb4 } ) );
expectRecv(1);
//aperiodic vars
// ID_MSG( 0201), expect RP_MSG_DAT + RP_FIN
requestSend( FipFrame::makeRaw( '{'h05, 'h02, 'h01 }) );
expectRecv(2);
// ID_MSG( 0001 ), send RP_MSG_DAT + RP_FIN
requestSend( FipFrame::makeRaw( '{'h05, 'h00, 'h01 }) );
requestSend( FipFrame::makeRP_MSG( FT_RP_DAT_MSG, 'h0, 'h400, makeRange(0, 255 ) ) );
requestSend( FipFrame::makeRP_FIN( ) );
// SMMPS vars
for(i = 0; i <256; i++)
begin
uint8_t payload [$] = '{ 'h03, 'h14, 0 };
payload[2]= i;
// ID_DAT: SMMPS frame
requestSend( FipFrame::makeRaw(payload));
expectRecv(1);
end
endtask
endclass // FipTestVirtualMaster
`endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
vsim -voptargs="-O5 +notimingchecks" -L unisim -L XilinxCoreLib -t 1ns -nopsl -quiet work.main
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
#bp ../include/wb/if_wb_master.svh 388 ;# 1
do wave.do
radix -hexadecimal
run 3000 ms
\ No newline at end of file
This diff is collapsed.
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