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

Subversion Repositories wbscope

[/] [wbscope/] [trunk/] [sw/] [scopecls.h] - Rev 14

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

////////////////////////////////////////////////////////////////////////////////
//
// Filename: 	scopecls.h
//
// Project:	WBScope, a wishbone hosted scope
//
// Purpose:	After rebuilding the same code over and over again for every
//		"scope" I tried to interact with, I thought it would be simpler
//	to try to make a more generic interface, that other things could plug
//	into.  This file defines and describes that more generic interface.
//
//	More recent updates have added to this interface those things necessary
//	to create a .VCD file for viewing in GTKWave.
//
// Creator:	Dan Gisselquist, Ph.D.
//		Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2017, 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
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#ifndef	SCOPECLS_H
#define	SCOPECLS_H
 
#include <vector>
#include "devbus.h"
 
 
/*
 * TRACEINFO
 *
 * The TRACEINFO class describes a wire (or set of wires) internal to the
 * scope data word.  These wires are assumed to be contiguous, and given by:
 * ((data_word>>m_nshift)&((1<<m_nbits)-1).  That is, there are m_nbits bits
 * to this value, and a shift of m_nshift is required to bring them down to
 * zero.
 *
 * Other key pieces include the human readable name given to the signal, m_name,
 * as well as the VCD name, m_key.
 *
 */
class	TRACEINFO {
public:
	const char	*m_name;
	char		m_key[4];
	unsigned	m_nbits, m_nshift;
};
 
/*
 * SCOPE
 *
 * This class is designed to be a generic SCOPE class, one which has all of the
 * logic other scopes will require.  Hence, if more than one scope needs this
 * logic, I stuff it in here for all scopes to use.
 */
class	SCOPE {
	DEVBUS		*m_fpga;	// Access to the FPGA
	DEVBUS::BUSW	m_addr;		// The address of the scope control reg
			// Set m_compressed to be true if the scope is a
			// compressed scope, that is if it uses the wbscopc.v
			// core.
	bool		m_compressed,
			// Set m_vector_read if you trust the bus enough to
			// issue vector reads (multiple words at once)
			m_vector_read;
	unsigned	m_scoplen,	// Number of words in the scopes memory
			m_holdoff;	// The bias, or samples since trigger
	unsigned	*m_data;	// Data read from the scope
	unsigned	m_clkfreq_hz;
 
	// The m_traces variable holds a list of all of the various wire
	// definitions within the scope data word.
	std::vector<TRACEINFO *> m_traces;
 
public:
	SCOPE(DEVBUS *fpga, unsigned addr,
			bool compressed=false, bool vecread=true)
		: m_fpga(fpga), m_addr(addr),
			m_compressed(compressed), m_vector_read(vecread),
			m_scoplen(0), m_data(NULL) {
		//
		// First thing we want to do upon allocating a scope, is to
		// define the traces for that scope.  Sad thing is ... we can't
		// call it here, since the class inheriting from us isn't
		// defined yet.
		// define_traces();
 
 
		// Default clock frequency: 100MHz.
		m_clkfreq_hz = 100000000;
	}
 
	// Free up any of our allocated memory.
	~SCOPE(void) {
		for(unsigned i=0; i<m_traces.size(); i++)
			delete m_traces[i];
		if (m_data) delete[] m_data;
	}
 
	// Query the scope: Is it ready?  Has it primed, triggered, and stopped?
	// If so, this routine returns true, false otherwise.
	bool	ready();
 
	// Read the control word from the scope, and send to the standard output
	// a description of that.
	void	decode_control(void);
 
	// Read the scope's control word, decode the memory size of the scope,
	// and return that to our caller.
	int	scoplen(void);
 
	// Set the clock speed that we are referencing
	void	set_clkfreq_hz(unsigned clkfreq_hz) {
		m_clkfreq_hz = clkfreq_hz;
	}
 
	// Read any previously set clock speed.
	unsigned get_clkfreq_hz(void) { return m_clkfreq_hz; }
 
	// Read the data from the scope and place it into our m_data array.
	// Nothing more is done with it beyond that.
	virtual	void	rawread(void);
 
	// Walk through the data, and print out to the standard output, what is
	// in it.  If multiple lines have the same data, print() will avoid
	// printing those lines for the purpose of keeping the output from
	// getting cluttered, but it will print a **** spacer, so you know
	// lines were skipped.
		void	print(void);
 
	// decode() works together with print() above.  The print() routine
	// calls decode() for every memory word within the scope's buffer.
	// More than that, the print() routine starts each line with the
	// clock number of the item, followed by the 32-bit data word in hex and
	// a colon.  Then it calls decode() to fill in the line with whatever
	// useful information was in the scope's data word.  Then it prints
	// a "\n" and continues.  Hence ... the purpose of the decode()
	// function--and why it needs to be scope specific.
	virtual	void	decode(DEVBUS::BUSW v) const = 0;
 
	//
	//
	// The following routines are provided to enable the creation and
	// writing of VCD files.
	//
	//
 
	// Write the timescale line to a VCD file.
	virtual void	write_trace_timescale(FILE *fp);
 
	// Write the offset from the time within the file, to the time of the
	// trigger, into the file.
	virtual void	write_trace_timezero(FILE *fp, int offset);
 
	// Write the VCD file's header
	virtual void	write_trace_header(FILE *fp, int offset = 0);
 
	// Given a value, and the number of bits required to define that value,
	// write a single line to our VCD file.
	//
	// This is an internal call that you are not likely to need to modify.
		void	write_binary_trace(FILE *fp, const int nbits,
				unsigned val, const char *str);
 
	// Same as write_binary_trace above, but this time we are given the
	// trace definition and the un-decomposed word to decompose first before
	// writing to the file.
	//
	// This is also an internal call that you are not likely to need to
	// modify.
		void	write_binary_trace(FILE *fp, TRACEINFO *info,
				unsigned value);
 
	// This is the user entry point.  When you know the scope is ready,
	// you may call writevcd to start the VCD generation process.
		void	writevcd(const char *trace_file_name);
	// This is an alternate entry point, useful if you already have a
	// FILE *.  This will write the data to the file, but not close the
	// file.
		void	writevcd(FILE *fp);
 
	// Calculate the number of points the scope covers.  Nominally, this
	// will be m_scopelen, the length of the scope.  However, if the
	// scope is compressed, this could be greater.
	//
	unsigned	getaddresslen(void);
 
	// Your program needs to define a define_traces() function, which will
	// then be called before trying to write the VCD file.  This function
	// must call register_trace for each of the traces within your data
	// word.
	virtual	void	define_traces(void);
 
	// Register_trace() defines the elements of a TRACEINFO structure
	// above.  These are then inserted into the list of TRACEINFO
	// structures, for reference when writing the VCD file.
		void	register_trace(const char *varname,
				unsigned nbits, unsigned shift);
 
	unsigned operator[](unsigned addr) {
		if ((m_data)&&(m_scoplen > 0))
			return m_data[(addr)&(m_scoplen-1)];
		return 0;
	}
};
 
#endif	// SCOPECLS_H
 

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.