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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [orpsocv2/] [bench/] [sysc/] [src/] [OrpsocMain.cpp] - Rev 478

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

/////////////////////////////////////////////////////////////////////
////                                                              ////
////  ORPSoC SystemC Testbench                                    ////
////                                                              ////
////  Description                                                 ////
////  ORPSoC Testbench file                                       ////
////                                                              ////
////  To Do:                                                      ////
////                                                              ////
////                                                              ////
////  Author(s):                                                  ////
////      - Jeremy Bennett jeremy.bennett@embecosm.com            ////
////      - Julius Baxter  julius@opencores.org                   ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG                 ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source 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 Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
 
#include "OrpsocMain.h"
 
#include "Vorpsoc_top.h"
#include "OrpsocAccess.h"
#include "MemoryLoad.h"
 
#include <verilated_vcd_c.h>
 
#include "ResetSC.h"
#include "Or1200MonitorSC.h"
 
// Include Verilog ORPSoC defines file, converted to C include format to be
// able to detect if the debug unit is to be built in or not.
#include "orpsoc-defines.h"
 
#ifdef JTAG_DEBUG
# include "GdbServerSC.h"
# include "JtagSC_includes.h"
#endif
 
#ifdef UART0
#  include "UartSC.h"
#endif
 
/* Global quiet variable */
bool gQuiet;
 
int gSimRunning;
 
int sc_main(int argc, char *argv[])
{
	sc_set_time_resolution(1, TIMESCALE_UNIT);
	// CPU clock (also used as JTAG TCK) and reset (both active high and low)
	sc_time clkPeriod(BENCH_CLK_HALFPERIOD * 2.0, TIMESCALE_UNIT);
	sc_clock clk("clk", clkPeriod);
 
	sc_signal < bool > rst;
	sc_signal < bool > rstn;
 
#ifdef JTAG_DEBUG
	sc_time jtagPeriod(JTAG_CLK_HALFPERIOD * 2.0, TIMESCALE_UNIT);
	sc_clock jtag_tck("jtag-clk", jtagPeriod, 0.5, SC_ZERO_TIME, false);
 
	sc_signal < bool > jtag_tdi;	// JTAG interface
	sc_signal < bool > jtag_tdo;
	sc_signal < bool > jtag_tms;
	sc_signal < bool > jtag_trst;
#endif
 
#ifdef UART0
	sc_signal < bool > uart_rx;	// External UART
	sc_signal < bool > uart_tx;
#endif
 
	gSimRunning = 0;
 
	// Are we running "quiet"?
	gQuiet = false;
	// Setup the name of the VCD dump file
	bool VCD_enabled = false;
	string dumpNameDefault("vlt-dump.vcd");
	string testNameString;
	string vcdDumpFile;
	// VCD dump controling vars
	bool dump_start_delay_set = false, dump_stop_set = false;
	bool dumping_now = false;
	int dump_depth = 99;	// Default dump depth
	sc_time dump_start, dump_stop, finish_time;
	bool finish_time_set = false;	// By default we will let the simulation 
	// finish naturally
	VerilatedVcdC *verilatorVCDFile;
 
	/*int */ double time_val;
	bool vcd_file_name_given = false;
 
#ifdef JTAG_DEBUG
	bool rsp_server_enabled = false;
	int rsp_server_port = DEFAULT_RSP_PORT;
#endif
 
	// Executable app load variables
	int do_program_file_load = 0;	// Default: we don't require a file, we use the
	// VMEM
	char *program_file;	// Old char* style for program name
 
	// Verilator accessor
	OrpsocAccess *accessor;
 
	// Modules
	Vorpsoc_top *orpsoc;	// Verilated ORPSoC
 
	MemoryLoad *memoryload;	// Memory loader
 
	ResetSC *reset;		// Generate a RESET signal
 
	Or1200MonitorSC *monitor;	// Handle l.nop x instructions
 
#ifdef JTAG_DEBUG
	JtagSC *jtag;		// Generate JTAG signals
	GdbServerSC *gdbServer;	// Map RSP requests to debug unit
#endif
 
#ifdef UART0
	UartSC *uart;		// Handle UART signals
#endif
 
	// Instantiate the Verilator model, VCD trace handler and accessor
	orpsoc = new Vorpsoc_top("orpsoc");
 
	accessor = new OrpsocAccess(orpsoc);
 
	memoryload = new MemoryLoad(accessor);
 
	monitor = new Or1200MonitorSC("monitor", accessor, memoryload,
				      argc, argv);
 
	// Instantiate the SystemC modules
	reset = new ResetSC("reset", BENCH_RESET_TIME);
 
#ifdef JTAG_DEBUG
	jtag = new JtagSC("jtag");
#endif
 
#ifdef UART0
	uart = new UartSC("uart");
#endif
 
	// Parse command line options
	// Default is for VCD generation OFF, only turned on if specified on command 
	// line
 
	// Search through the command line parameters for options  
	if (argc > 1) {
		for (int i = 1; i < argc; i++) {
			if ((strcmp(argv[i], "-e") == 0) ||
			    (strcmp(argv[i], "--endtime") == 0)) {
				time_val = strtod(argv[i + 1], NULL);
				sc_time opt_end_time(time_val, TIMESCALE_UNIT);
				finish_time = opt_end_time;
				finish_time_set = true;
			} else if ((strcmp(argv[i], "-q") == 0) ||
				   (strcmp(argv[i], "--quiet") == 0)) {
				gQuiet = true;
			} else if ((strcmp(argv[i], "-f") == 0) ||
				  (strcmp(argv[i], "--program") == 0)) {
				do_program_file_load = 1;	// Enable program loading - will be 
				// done after sim init.
				program_file = argv[i + 1];	// Old char* style for program name
			} else if ((strcmp(argv[i], "-d") == 0) ||
				   (strcmp(argv[i], "--vcdfile") == 0) ||
				   (strcmp(argv[i], "-v") == 0) ||
				   (strcmp(argv[i], "--vcdon") == 0)
			    ) {
				VCD_enabled = true;
				dumping_now = true;
				vcdDumpFile = dumpNameDefault;
				if (i + 1 < argc)
					if (argv[i + 1][0] != '-') {
						testNameString = argv[i + 1];
						vcdDumpFile = testNameString;
						i++;
					}
			} else if ((strcmp(argv[i], "-s") == 0) ||
				   (strcmp(argv[i], "--vcdstart") == 0)) {
				VCD_enabled = true;
				time_val = strtod(argv[i + 1], NULL);
				sc_time dump_start_time(time_val,
							TIMESCALE_UNIT);
				dump_start = dump_start_time;
				dump_start_delay_set = true;
				dumping_now = false;
			} else if ((strcmp(argv[i], "-t") == 0) ||
				   (strcmp(argv[i], "--vcdstop") == 0)) {
				VCD_enabled = true;
				time_val = strtod(argv[i + 1], NULL);
				sc_time dump_stop_time(time_val,
						       TIMESCALE_UNIT);
				dump_stop = dump_stop_time;
				dump_stop_set = true;
			}
#ifdef JTAG_DEBUG
			else if ((strcmp(argv[i], "-r") == 0) ||
				 (strcmp(argv[i], "--rsp") == 0)) {
				rsp_server_enabled = true;
				if (i + 1 < argc)
					if (argv[i + 1][0] != '-') {
						rsp_server_port =
						    atoi(argv[i + 1]);
						i++;
					}
			}
#endif
			else if ((strcmp(argv[i], "-h") == 0) ||
				   (strcmp(argv[i], "--help") == 0)) {
				printf("Usage: %s [options]\n", argv[0]);
				printf("\n  ORPSoCv2 cycle accurate model\n");
				printf
				    ("  For details visit http://opencores.org/openrisc,orpsocv2\n");
				printf("\n");
				printf("Options:\n");
				printf
				    ("  -h, --help\t\tPrint this help message\n");
				printf
				    ("  -q, --quiet\t\tDisable all except UART print out\n");
				printf("\nSimulation control:\n");
				printf
				    ("  -f, --program <file> \tLoad program from OR32 ELF <file>\n");
				printf
				    ("  -e, --endtime <val> \tStop the sim at <val> ns\n");
				printf("\nVCD generation:\n");
				printf
				    ("  -v, --vcdon\t\tEnable VCD generation\n");
				printf
				    ("  -d, --vcdfile <file>\tEnable and save VCD to <file>\n");
 
				printf
				    ("  -s, --vcdstart <val>\tEnable and delay VCD generation until <val> ns\n");
				printf
				    ("  -t, --vcdstop <val> \tEnable and terminate VCD generation at <val> ns\n");
#ifdef JTAG_DEBUG
				printf("\nRemote debugging:\n");
				printf
				    ("  -r, --rsp [<port>]\tEnable RSP debugging server, opt. specify <port>\n");
#endif
				monitor->printUsage();
				printf("\n");
				return 0;
			}
 
		}
	}
	// Determine if we're going to setup a VCD dump:
	// Pretty much setting any related option will enable VCD dumping.
	if (VCD_enabled) {
 
		cout << "* Enabling VCD trace";
 
		if (dump_start_delay_set)
			cout << ", on at time " << dump_start.to_string();
		if (dump_stop_set)
			cout << ", off at time " << dump_stop.to_string();
		cout << endl;
	}
#ifdef JTAG_DEBUG
	if (rsp_server_enabled)
		gdbServer =
		    new GdbServerSC("gdb-server", FLASH_START, FLASH_END,
				    rsp_server_port, jtag->tapActionQueue);
	else
		gdbServer = NULL;
#endif
 
	// Connect up ORPSoC
	orpsoc->clk_pad_i(clk);
	orpsoc->rst_n_pad_i(rstn);
 
#ifdef JTAG_DEBUG
	orpsoc->tck_pad_i(jtag_tck);	// JTAG interface
	orpsoc->tdi_pad_i(jtag_tdi);
	orpsoc->tms_pad_i(jtag_tms);
	orpsoc->tdo_pad_o(jtag_tdo);
#endif
 
#ifdef UART0
	orpsoc->uart0_srx_pad_i(uart_rx);	// External UART
	orpsoc->uart0_stx_pad_o(uart_tx);
#endif
 
	// Connect up the SystemC  modules
	reset->clk(clk);	// Reset
	reset->rst(rst);
	reset->rstn(rstn);
 
	monitor->clk(clk);	// Monitor
 
#ifdef JTAG_DEBUG
	jtag->sysReset(rst);	// JTAG
	jtag->tck(jtag_tck);
	jtag->tdi(jtag_tdi);
	jtag->tdo(jtag_tdo);
	jtag->tms(jtag_tms);
	jtag->trst(jtag_trst);
#endif
 
#ifdef UART0
	uart->clk(clk);		// Uart
	uart->uartrx(uart_rx);	// orpsoc's receive line
	uart->uarttx(uart_tx);	// orpsoc's transmit line
#endif
 
	// Tie off signals
#ifdef JTAG_DEBUG
	jtag_tdi = 1;		// Tie off the JTAG inputs
	jtag_tms = 1;
#endif
 
	if (VCD_enabled) {
		Verilated::traceEverOn(true);
 
		printf("* VCD dumpfile: %s\n", vcdDumpFile.c_str());
 
		// Establish a new trace with its correct time resolution, and trace to
		// great depth.
		verilatorVCDFile = new VerilatedVcdC();
 
		orpsoc->trace(verilatorVCDFile, dump_depth);
 
		if (dumping_now) {
			verilatorVCDFile->open(vcdDumpFile.c_str());
		}
	}
	//printf("* Beginning test\n");
 
#ifdef UART0
	// Init the UART function
	uart->initUart(50000000, 115200);
#endif
 
	if (do_program_file_load)	// Did the user specify a file to load?
	{
		if (!gQuiet)
			cout << "* Loading program from " << program_file << 
				endl;
		if (memoryload->loadcode(program_file, 0, 0) < 0) {
			cout << "* Error: executable file " << program_file <<
			    " not loaded" << endl;
			goto finish_up;
 
		}
	} else			
	{
		/* No ELF file specified, default is to load from  VMEM file */
		if (!gQuiet)
			cout <<
			    "* Loading memory with image from default file, sram.vmem"
			    << endl;
		accessor->do_ram_readmemh();
	}
 
	gSimRunning = 1;
 
	// First check how we should run the sim.
	if (VCD_enabled || finish_time_set) {	// We'll run sim with step
 
		if (!VCD_enabled && finish_time_set) {
			// We just run the sim until the set finish time
			sc_start((double)(finish_time.to_double()),
				 TIMESCALE_UNIT);
			gSimRunning = 0;
			sc_stop();
			// Print performance summary
			monitor->perfSummary();
			// Do memdump if enabled
			monitor->memdump();
		} else {
			if (dump_start_delay_set) {
				// Run the sim until we want to dump
				sc_start((double)(dump_start.to_double()),
					 TIMESCALE_UNIT);
				// Open the trace file
				verilatorVCDFile->open(vcdDumpFile.c_str());
				dumping_now = 1;
			}
 
			if (dumping_now) {
				// Step the sim and generate the trace
				// Execute until we stop
				while (!Verilated::gotFinish()) {
					// gSimRunning value changed by the
					// monitor when sim should finish.
					if (gSimRunning)
						// Step the sim
						sc_start(1, TIMESCALE_UNIT);
					else {
						verilatorVCDFile->close();
						break;
					}
 
					verilatorVCDFile->dump(sc_time_stamp().
							       to_double());
 
					if (dump_stop_set) {
						if (sc_time_stamp() >=
						    dump_stop) {
							// Close dump file
							verilatorVCDFile->close
								();
							// Now continue on again until the end
							if (!finish_time_set)
								sc_start();
							else {
								// Determine how long we should run for
								sc_time
								    sim_time_remaining
								    =
								    finish_time
								    -
								    sc_time_stamp
								    ();
								sc_start((double)(sim_time_remaining.to_double()), TIMESCALE_UNIT);
								// Officially stop the sim
								sc_stop();
								// Print performance summary
								monitor->
								    perfSummary
								    ();
								// Do memdump if enabled
								monitor->memdump
								    ();
							}
							break;
						}
					}
					if (finish_time_set) {
						if (sc_time_stamp() >=
						    finish_time) {
							// Officially stop the sim
							sc_stop();
							// Close dump file
							verilatorVCDFile->close
							    ();
							// Do memdump if enabled
							monitor->memdump();
							// Print performance summary
							monitor->perfSummary();
							break;
						}
					}
				}
			}
		}
	} else {
		// Simple run case
		// Ideally a "l.nop 1" will terminate the simulation gracefully.
		// Need to step at clock period / 4, otherwise model appears to skip the 
		// monitor and logging functions sometimes (?!?)
		while (gSimRunning)
			sc_start(BENCH_CLK_HALFPERIOD / 2, TIMESCALE_UNIT);
		//sc_start();
	}
 
 
finish_up:
	// Free memory
#ifdef JTAG_DEBUG
	if (rsp_server_enabled)
		delete gdbServer;
 
	delete jtag;
#endif
 
	delete monitor;
 
	delete reset;
 
	delete accessor;
 
	//delete trace;
 
	delete orpsoc;
 
	return 0;
 
}				/* sc_main() */
 

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.