OpenCores
URL https://opencores.org/ocsvn/wb2axip/wb2axip/trunk

Subversion Repositories wb2axip

[/] [wb2axip/] [trunk/] [bench/] [cpp/] [aximemsim.cpp] - Rev 15

Go to most recent revision | Compare with Previous | Blame | View Log

////////////////////////////////////////////////////////////////////////////////
//
// Filename: 	aximemsim.cpp
//
// Project:	Pipelined Wishbone to AXI converter
//
// Purpose:	
//
// Creator:	Dan Gisselquist, Ph.D.
//		Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): 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 3 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 MERCHANTIBILITY 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.  (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.)  If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License:	GPL, v3, as defined and found on www.gnu.org,
//		http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#include <stdio.h>
 
#include "aximemsim.h"
 
class	ADRFIFO {
	typedef	{
		int id; unsigned addr;
	} ADRFIFOELEMENT;
	int	m_head, m_tail, m_len;
	int	*m_mem;
public:
	ADRFIFO(int ln) {
		m_mem = new ADRFIFOELEMENT[ln];
		m_head = m_tail = 0;
		m_len = ln;
	}
 
	void	push(int id, unsigned addr) {
		int nhead = m_head + 1;
		if (nhead >= m_len)
			nhead = 0;
		assert(nhead != m_tail);
		m_mem[m_head].id   = id;
		m_mem[m_head].addr = addr;
		m_head = nhead;
	}
 
	bool	full(void) {
		int nhead = m_head + 1;
		if (nhead >= m_len)
			nhead = 0;
		return (nhead == m_tail);
	}
 
	bool	valid(void) {
		return (m_head != m_tail);
	}
 
	int	id(void)	{ return m_mem[m_tail].id; }
	int	addr(void)	{ return m_mem[m_tail].addr; }
	int	pop(void)	{
		if (m_tail == m_head)
			return;
		m_tail++;
		if (m_tail >= m_len)
			m_tail = 0;
	}
};
 
class	DATFIFO {
	typedef	{
		unsigned data[4];
		int	strb;
	} DATAFIFOELEMENT;
	int	m_head, m_tail, m_len;
	int	*m_mem;
public:
	DATAFIFO(int ln) {
		m_mem = new DATAFIFOELEMENT[ln];
		m_head = m_tail = 0;
		m_len = ln;
	}
 
	void	push(int strb, unsigned dat0, unsigned dat1,
			unsigned dat, unsigned dat3) {
		int nhead = m_head + 1;
		if (nhead >= m_len)
			nhead = 0;
		assert(nhead != m_tail);
		m_mem[m_head].strb   = id;
		m_mem[m_head].data[0] = dat0;
		m_mem[m_head].data[1] = dat1;
		m_mem[m_head].data[2] = dat2;
		m_mem[m_head].data[3] = dat3;
		m_head = nhead;
	}
 
	bool	full(void) {
		int nhead = m_head + 1;
		if (nhead >= m_len)
			nhead = 0;
		return (nhead == m_tail);
	}
 
	bool	valid(void) {
		return (m_head != m_tail);
	}
 
	int	strb(void)	{ return m_mem[m_tail].strb; }
	unsigned *data(void)	{ return &m_mem[m_tail].data[0]; }
	int	pop(void)	{
		if (m_tail == m_head)
			return;
		m_tail++;
		if (m_tail >= m_len)
			m_tail = 0;
	}
};
 
AXIMEMSIM::AXIMEMSIM(unsigned abits) {
	// abits is the number of bits in a memory address, referencing 8-bit
	// bytes, therefore we can size our memory properly.
	assert(abits>2);
	m_len = (1<<(abits-2));
	m_mask= m_len-1;
	m_mem = new unsigned[(1<<(abits-2))];
 
	memset(m_mem, 0, sizeof(unsigned)<<(abits-2));
}
 
void AXIMEMSIM::apply(AXIBUS &bus) {
	// First, let's validate our inputs ..., and queue up our outputs
	bus.ar.ready = (!m_readfifo.full());
	bus.aw.ready = (!m_writefifo.full());
	bus.w.ready  = (!m_wdata.full());
	if (bus.r.ready)
		bus.r.valid = false;
	if (bus.b.ready)
		bus.b.valid = false;
 
	if ((bus.ar.ready)&&(!m_readfifo.full())) {
		assert(bus.ar.len  == 0);
		assert(bus.ar.size  == 5);
		assert(bus.ar.burst == 1);
		assert(bus.ar.lock  == 0);
		assert(bus.ar.cache == 2);
		assert(bus.ar.prot  == 2);
		assert(bus.ar.qos   == 0);
 
		m_readfifo.push(bus.ar.id, bus.ar.addr);
	}
 
	if ((bus.aw.ready)&&(!m_writefifo.full())) {
		assert(bus.aw.len   == 0);
		assert(bus.aw.size  == 5);
		assert(bus.aw.burst == 1);
		assert(bus.aw.lock  == 0);
		assert(bus.aw.cache == 2);
		assert(bus.aw.prot  == 2);
		assert(bus.aw.qos   == 0);
 
		m_awfifo.push(bus.aw.id, bus.aw.addr);
	}
 
	if ((bus.w.ready)&&(!m_writedata.full())) {
		m_writefifo.push(bus.aw.strb, bus.aw.data[0], bus.aw.data[1],
			bus.aw.data[2], bus.aw.data[3]);
 
	if (m_respfifo[m_now].valid) {
		if (m_respfifo[m_now].read) {
			if ((!bus.r.valid)||(bus.r.ready)) {
				bus.r.data[0] = m_respfifo[m_now].data[0];
				bus.r.data[1] = m_respfifo[m_now].data[1];
				bus.r.data[2] = m_respfifo[m_now].data[2];
				bus.r.data[3] = m_respfifo[m_now].data[3];
				bus.r.valid = true;
				m_now++;
			}
		} else if ((!bus.b.valid)||(bus.b.ready)) {
			bus.b.resp = m_respfifo[m_now].resp;
			bus.b.id = m_respfifo[m_now].id;
			bus.b.valid = true;
			m_now++;
		}
	}
}
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.