Commit 879d4875 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

simulation models: added Minic driver

parent 7bbebbf9
`include "simdrv_defs.svh"
`include "eth_packet.svh"
`include "minic_regs.vh"
`define MAX_PACKET_SIZE 1536
class CSimDrv_Minic;
const uint32_t TX_DESC_VALID = (1<<31);
const uint32_t TX_DESC_WITH_OOB = (1<<30);
const uint32_t TX_DESC_HAS_OWN_MAC = (1<<28);
`define RX_DESC_VALID(d) ((d) & (1<<31) ? 1 : 0)
`define RX_DESC_ERROR(d) ((d) & (1<<30) ? 1 : 0)
`define RX_DESC_HAS_OOB(d) ((d) & (1<<29) ? 1 : 0)
`define RX_DESC_SIZE(d) (((d) & (1<<0) ? -1 : 0) + (d & 'hfffe))
protected CBusAccessor acc_regs, acc_pmem;
protected uint32_t base_regs, base_pmem;
protected int pmem_size;
protected bit little_endian;
protected uint32_t tx_head, tx_base, tx_avail, tx_size, tx_count, tx_oob_val;
protected uint32_t rx_head, rx_base, rx_avail, rx_size, rx_count;
protected EthPacket rx_queue[$];
protected EthPacket tx_queue[$];
const int MINIC_MTU = 1536;
function new(int pmem_size_, CBusAccessor regs_, uint32_t base_regs_, CBusAccessor pmem_, uint32_t base_pmem_);
base_pmem = base_pmem_;
base_regs = base_regs_;
acc_regs = regs_;
acc_pmem = pmem_;
pmem_size = pmem_size_;
little_endian = 1;
endfunction // new
task minic_writel(uint32_t addr, uint32_t val);
acc_regs.write(base_regs + addr, val, 4);
endtask // minic_writel
task minic_readl(uint32_t addr, output uint32_t val);
uint64_t tmp;
acc_regs.read(base_regs + addr, tmp, 4);
val = tmp;
endtask // minic_writel
task new_tx_buffer();
tx_head = tx_base;
tx_avail = (tx_size - MINIC_MTU) >> 2;
minic_writel(`ADDR_MINIC_TX_ADDR, tx_base);
endtask // new_tx_buffer
task new_rx_buffer();
rx_head = rx_base;
minic_writel(`ADDR_MINIC_MCR, 0);
minic_writel(`ADDR_MINIC_RX_ADDR, rx_base);
minic_writel(`ADDR_MINIC_RX_AVAIL, (rx_size - MINIC_MTU) >> 2);
minic_writel(`ADDR_MINIC_MCR, `MINIC_MCR_RX_EN);
endtask // new_rx_buffer
task init();
minic_writel(`ADDR_MINIC_EIC_IDR, `MINIC_EIC_IDR_RX);
minic_writel(`ADDR_MINIC_EIC_ISR, `MINIC_EIC_ISR_RX);
rx_base = base_pmem;
rx_size = pmem_size / 4;
tx_base = base_pmem + pmem_size / 2;
tx_size = pmem_size / 4;
tx_oob_val = 12345;
tx_count = 0;
rx_count = 0;
new_rx_buffer();
minic_writel(`ADDR_MINIC_EIC_IER, `MINIC_EIC_IER_RX);
endtask // init
task tx_frame(byte payload[], uint32_t size, bit with_oob, int ts_id, output uint32_t ts, output int port_id);
int i;
uint32_t d_hdr, mcr, nwords;
u64_array_t buff;
byte tmp[];
byte oob[2];
new_tx_buffer();
if(size < 60) size = 60;
if(size & 1) size = size + 1;
tmp = new[size](payload);
buff = SimUtils.pack({0,0,0,0, tmp, 0,0,0,0}, 4, 1);
size = size / 2;
for(i=0;i<buff.size(); i++)
acc_pmem.write(tx_head + i*4, buff[i], 4);
acc_pmem.write(tx_head, TX_DESC_HAS_OWN_MAC | TX_DESC_VALID | (with_oob ? TX_DESC_WITH_OOB :0 )| size | (ts_id << 12), 4);
minic_readl(`ADDR_MINIC_MCR, mcr);
minic_writel(`ADDR_MINIC_MCR, mcr | `MINIC_MCR_TX_START);
endtask // tx_frame
task rx_frame(ref byte payload[], output uint32_t size, output bit with_ts, output uint32_t ts);
uint32_t payload_size, num_words;
uint64_t desc_hdr;
uint32_t raw_ts;
uint32_t rx_addr_cur, mcr;
u64_array_t pbuff;
int i;
int n_recvd;
uint32_t isr;
minic_readl(`ADDR_MINIC_EIC_ISR, isr);
if(! (isr & `MINIC_EIC_ISR_RX))
return;
acc_pmem.read(rx_head, desc_hdr);
if(!`RX_DESC_VALID(desc_hdr))
begin
$error("SimDRV_Minic::rx_frame: weird, invalid RX desc header");
$stop;
end
payload_size = `RX_DESC_SIZE(desc_hdr);
num_words = (payload_size + 3) >> 2;
pbuff = new [num_words];
if(!`RX_DESC_ERROR(desc_hdr))
begin
for(i=0; i<num_words;i++)
acc_pmem.read(rx_head + 4 + i * 4, pbuff[i]);
payload = SimUtils.unpack(pbuff, 4, payload_size);
end
size = payload_size;
rx_head = rx_head + 4 + num_words * 4;
minic_readl(`ADDR_MINIC_RX_ADDR, rx_addr_cur);
// $display("RxAddrCur: %x head %x\n", rx_addr_cur, rx_head);
if((rx_addr_cur & 'hffff) < rx_head)
begin
minic_readl(`ADDR_MINIC_MCR, mcr);
if(mcr & `MINIC_MCR_RX_FULL)
new_rx_buffer();
minic_writel(`ADDR_MINIC_EIC_ISR, `MINIC_EIC_ISR_RX);
end
endtask // rx_frame
task do_rx();
byte payload[];
uint32_t size, ts;
bit with_ts;
rx_frame(payload, size, with_ts, ts);
if(payload.size() > 0)
begin
EthPacket pkt;
pkt = new;
pkt.deserialize(payload);
rx_queue.push_back(pkt);
end
endtask // do_rx
task run();
uint32_t mcr;
if(tx_queue.size() > 0)
begin
minic_readl(`ADDR_MINIC_MCR, mcr);
// $display("mcr %x, Minic::q_not_empty %d", mcr, tx_queue.size());
if(mcr & `MINIC_MCR_TX_IDLE) begin
byte b[];
uint32_t ts;
int pid;
EthPacket pkt;
pkt = tx_queue.pop_front();
pkt.serialize(b);
tx_frame(b, b.size(), pkt.oob_type == TX_FID ? 1 : 0, pkt.ts.frame_id,ts, pid);
end
end // if (tx_queue.size() > 0)
do_rx();
endtask // run
task send(EthPacket pkt);
tx_queue.push_back(pkt);
endtask // send
function poll();
return rx_queue.size() > 0;
endfunction // poll
task recv(ref EthPacket pkt);
pkt = rx_queue.pop_front();
endtask // recv
endclass // CSimDrv_Minic
`define ADDR_MINIC_MCR 6'h0
`define MINIC_MCR_TX_START_OFFSET 0
`define MINIC_MCR_TX_START 32'h00000001
`define MINIC_MCR_TX_IDLE_OFFSET 1
`define MINIC_MCR_TX_IDLE 32'h00000002
`define MINIC_MCR_TX_ERROR_OFFSET 2
`define MINIC_MCR_TX_ERROR 32'h00000004
`define MINIC_MCR_RX_READY_OFFSET 8
`define MINIC_MCR_RX_READY 32'h00000100
`define MINIC_MCR_RX_FULL_OFFSET 9
`define MINIC_MCR_RX_FULL 32'h00000200
`define MINIC_MCR_RX_EN_OFFSET 10
`define MINIC_MCR_RX_EN 32'h00000400
`define MINIC_MCR_RX_CLASS_OFFSET 16
`define MINIC_MCR_RX_CLASS 32'h00ff0000
`define ADDR_MINIC_TX_ADDR 6'h4
`define ADDR_MINIC_RX_ADDR 6'h8
`define ADDR_MINIC_RX_AVAIL 6'hc
`define ADDR_MINIC_TSR0 6'h10
`define MINIC_TSR0_VALID_OFFSET 0
`define MINIC_TSR0_VALID 32'h00000001
`define MINIC_TSR0_PID_OFFSET 1
`define MINIC_TSR0_PID 32'h0000003e
`define MINIC_TSR0_FID_OFFSET 6
`define MINIC_TSR0_FID 32'h003fffc0
`define ADDR_MINIC_TSR1 6'h14
`define MINIC_TSR1_TSVAL_OFFSET 0
`define MINIC_TSR1_TSVAL 32'hffffffff
`define ADDR_MINIC_DBGR 6'h18
`define MINIC_DBGR_IRQ_CNT_OFFSET 0
`define MINIC_DBGR_IRQ_CNT 32'h00ffffff
`define MINIC_DBGR_WB_IRQ_VAL_OFFSET 24
`define MINIC_DBGR_WB_IRQ_VAL 32'h01000000
`define ADDR_MINIC_EIC_IDR 6'h20
`define MINIC_EIC_IDR_TX_OFFSET 0
`define MINIC_EIC_IDR_TX 32'h00000001
`define MINIC_EIC_IDR_RX_OFFSET 1
`define MINIC_EIC_IDR_RX 32'h00000002
`define MINIC_EIC_IDR_TXTS_OFFSET 2
`define MINIC_EIC_IDR_TXTS 32'h00000004
`define ADDR_MINIC_EIC_IER 6'h24
`define MINIC_EIC_IER_TX_OFFSET 0
`define MINIC_EIC_IER_TX 32'h00000001
`define MINIC_EIC_IER_RX_OFFSET 1
`define MINIC_EIC_IER_RX 32'h00000002
`define MINIC_EIC_IER_TXTS_OFFSET 2
`define MINIC_EIC_IER_TXTS 32'h00000004
`define ADDR_MINIC_EIC_IMR 6'h28
`define MINIC_EIC_IMR_TX_OFFSET 0
`define MINIC_EIC_IMR_TX 32'h00000001
`define MINIC_EIC_IMR_RX_OFFSET 1
`define MINIC_EIC_IMR_RX 32'h00000002
`define MINIC_EIC_IMR_TXTS_OFFSET 2
`define MINIC_EIC_IMR_TXTS 32'h00000004
`define ADDR_MINIC_EIC_ISR 6'h2c
`define MINIC_EIC_ISR_TX_OFFSET 0
`define MINIC_EIC_ISR_TX 32'h00000001
`define MINIC_EIC_ISR_RX_OFFSET 1
`define MINIC_EIC_ISR_RX 32'h00000002
`define MINIC_EIC_ISR_TXTS_OFFSET 2
`define MINIC_EIC_ISR_TXTS 32'h00000004
`define ADDR_SYSC_RSTR 5'h0
`define SYSC_RSTR_HRST_OFFSET 0
`define SYSC_RSTR_HRST 32'hffffffff
`define ADDR_SYSC_GPSR 5'h4
`define SYSC_GPSR_LED_STAT_OFFSET 0
`define SYSC_GPSR_LED_STAT 32'h00000001
`define SYSC_GPSR_LED_LINK_OFFSET 1
`define SYSC_GPSR_LED_LINK 32'h00000002
`define SYSC_GPSR_FMC_SCL_OFFSET 2
`define SYSC_GPSR_FMC_SCL 32'h00000004
`define SYSC_GPSR_FMC_SDA_OFFSET 3
`define SYSC_GPSR_FMC_SDA 32'h00000008
`define SYSC_GPSR_NET_RST_OFFSET 4
`define SYSC_GPSR_NET_RST 32'h00000010
`define SYSC_GPSR_BTN1_OFFSET 5
`define SYSC_GPSR_BTN1 32'h00000020
`define SYSC_GPSR_BTN2_OFFSET 6
`define SYSC_GPSR_BTN2 32'h00000040
`define ADDR_SYSC_GPCR 5'h8
`define SYSC_GPCR_LED_STAT_OFFSET 0
`define SYSC_GPCR_LED_STAT 32'h00000001
`define SYSC_GPCR_LED_LINK_OFFSET 1
`define SYSC_GPCR_LED_LINK 32'h00000002
`define SYSC_GPCR_FMC_SCL_OFFSET 2
`define SYSC_GPCR_FMC_SCL 32'h00000004
`define SYSC_GPCR_FMC_SDA_OFFSET 3
`define SYSC_GPCR_FMC_SDA 32'h00000008
`define ADDR_SYSC_HWFR 5'hc
`define SYSC_HWFR_MEMSIZE_OFFSET 0
`define SYSC_HWFR_MEMSIZE 32'h0000000f
`define ADDR_SYSC_TCR 5'h10
`define SYSC_TCR_TDIV_OFFSET 0
`define SYSC_TCR_TDIV 32'h00000fff
`define SYSC_TCR_ENABLE_OFFSET 31
`define SYSC_TCR_ENABLE 32'h80000000
`define ADDR_SYSC_TVR 5'h14
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