#ifndef	__BOARD_H
#define __BOARD_H
#include <systemc.h>
#include "MAIN.h"
#include "top.h"
#include "EXTSRAM.h"
#include "SDRAM.h"

//#define SRAM	  SRAM_EMBED
//#define nSRAMADDR EMBEDSRAM_nA	//1Kx32
//#define nSRAMBITS 8
//#define nSRAMWORDS (CPUDATAWIDTH/8)

//#include "SRAM.H"
//#undef	SRAM

SC_MODULE(BOARD)
{
	sc_in_clk			clk;
	sc_in<sc_uint<1> >		reset;
	sc_out<sc_uint<1> >		suspend;
	//PCI bus
	sc_signal<sc_uint<1> >		pci_clk;    //out
	sc_signal<sc_uint<1> >		pci_reqn;
	sc_signal<sc_uint<1> >		pci_grantn;
	sc_signal<sc_uint<1> >		pci_frame;
	sc_signal<sc_uint<4> >		pci_cbe;
	sc_signal<sc_uint<1> >		pci_irdy;
	sc_signal<sc_uint<1> >		pci_dataoe;
	sc_signal<sc_uint<32> >		pci_wdata;
	sc_signal<sc_uint<32> >		pci_rdata;  //in
	sc_signal<sc_uint<1> >		pci_trdy;
	sc_signal<sc_uint<1> >		pci_devsel;

	sc_signal<sc_uint<1> >		pcid_trans;
	sc_signal<sc_uint<1> >		pcid_seq;
	sc_signal<sc_uint<4> >		pcid_we;
	sc_signal<sc_uint<32> >		pcid_addr;
	sc_signal<sc_uint<32> >		pcid_wdata;
	sc_signal<sc_uint<1> >		pcid_dataoe;
	sc_signal<sc_uint<1> >		dpciclk;
	char		pcidsts;
	char		pcidsel;
	char		pcidcmd;
	unsigned	pcidaddr;
	unsigned	pciddata;
	bool		pcidmode;
	bool		pcidtrans;
	bool		pcidtranswait;
	bool		pcidlast;
	bool		birdy;
	sc_signal<sc_uint<1> >		intreq;
	sc_signal<sc_uint<1> >		intack;

	sc_signal<sc_uint<1> >		extsram_trans;
	sc_signal<sc_uint<32> >		extsram_rdata;
	sc_signal<sc_uint<1> >		extsram_ready;

	sc_signal<sc_uint<32> >		sdram_addr;
	sc_signal<sc_uint<32> >		sdram_wdata[BurstLen];
	sc_signal<sc_uint<32> >		sdram_rdata[BurstLen];
	sc_signal<sc_uint<4> >		sdram_mask[BurstLen];
	sc_signal<sc_uint<1> >		sdram_we;
	sc_signal<sc_uint<1> >		sdram_re;
	sc_signal<sc_uint<1> >		sdram_ready;
	sc_signal<sc_uint<1> >		sdram_cmdvalid;

	char		dirtysource; //D=SDRAM, E=EMBSRAM, X=EXTSRAM

	TOP		*top;
	EXTSRAM		*extsram;
	SDRAM_IF	*sdram_if;

	void		pci_device();
	void		pci_device_neg();

	bool		loaddata(const char *filename,char *block,unsigned long startaddr);
	void		setdirtysource(char mname) {dirtysource=mname;}
	bool		isdirty(){ if (dirtysource=='D') return(sdram_if->isdirty()); else if (dirtysource=='E') return(top->sram->isdirty()); else if (dirtysource=='X') return(extsram->isdirty); else return(false);}
	void		clrdirty(){ if (dirtysource=='D') sdram_if->clrdirty(); else if (dirtysource=='E') top->sram->clrdirty(); else if (dirtysource=='X') extsram->clrdirty(); }

	SC_CTOR(BOARD)
	{	    
	    int i;
	    top=new TOP("top");
	    top->clk	    ( clk	);
	    top->reset	    ( reset	);
	    top->suspend    ( suspend	);
	    top->pci_clk    ( pci_clk	);
	    top->pci_reqn   ( pci_reqn	);
	    top->pci_grantn ( pci_grantn);
	    top->pci_frame  ( pci_frame	);
	    top->pci_cbe    ( pci_cbe	);
	    top->pci_irdy   ( pci_irdy	);
	    top->pci_dataoe ( pci_dataoe);
	    top->pci_wdata  ( pci_wdata	);
	    top->pci_rdata  ( pci_rdata	);
	    top->pci_trdy   ( pci_trdy	);
	    top->pci_devsel ( pci_devsel);
	    top->intreq		(intreq);
	    top->intack		(intack);

	    extsram=new EXTSRAM("extsram");
	    extsram->clk	(clk);
	    extsram->reset	(reset);
	    extsram->ram_trans	(extsram_trans);
	    extsram->ram_we	(pcid_we);
	    extsram->ram_addr	(pcid_addr);
	    extsram->ram_wdata	(pcid_wdata);
	    extsram->ram_rdata	(extsram_rdata);
	    extsram->ram_ready	(extsram_ready);
	    extsram->intreq	(intreq);
	    extsram->intack	(intack);

	    sdram_if=new SDRAM_IF("sdram_if");
	    sdram_if->clk	    ( clk	);
	    sdram_if->reset	    ( reset	);
	    sdram_if->suspend	    ( suspend	);
	    sdram_if->addr	    ( sdram_addr);
	    for(i=0;i<BurstLen;i++) sdram_if->wr_data[i]	(sdram_wdata[i]);
	    for(i=0;i<BurstLen;i++) sdram_if->rd_data[i]	(sdram_rdata[i]);
	    for(i=0;i<BurstLen;i++) sdram_if->mask[i]		(sdram_mask[i]);
	    sdram_if->we	    (sdram_we);
	    sdram_if->re	    (sdram_re);
	    sdram_if->mready	    (sdram_ready);
	    sdram_if->cmdvalid	    (sdram_cmdvalid);

	    //sts=0;

	    SC_METHOD(pci_device);
	    sensitive_pos<<clk;

	    SC_METHOD(pci_device_neg);
	    sensitive_neg<<clk;
	}
};
#endif
