diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-19 18:45:49 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-19 18:45:49 +0000 |
commit | 09a528fd59d3ea5f69575a92574f7a87898dc068 (patch) | |
tree | 9e465c49fbbe65f70d4feca3fcfb2ab3a7cf00d4 /src | |
download | kpicosim-09a528fd59d3ea5f69575a92574f7a87898dc068.tar.gz kpicosim-09a528fd59d3ea5f69575a92574f7a87898dc068.zip |
Added old abandoned (but very good!) KDE3 KPicoSim application
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/kpicosim@1092928 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src')
48 files changed, 7182 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..26a6105 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,45 @@ +# set the include path for X, qt and KDE +INCLUDES = -I$(top_srcdir)/debian $(all_includes) + +# these are the headers for your project +noinst_HEADERS = kpicosim.h codeeditor.h ksimulator.h kserialview.h kportview.h \ + kport.h kexportdialog.h cassembler.h cinstruction.h cpicoblaze.h hexcodes.h \ + types.h kprocessorview.h jtagdevice.h kjtagdialog.h jtagprogrammer.h + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kpicosim.pot + +KDE_ICON = kpicosim + +######################################################################### +# APPLICATION SECTION +######################################################################### +# this is the program that gets installed. it's name is used for all +# of the other Makefile.am variables +bin_PROGRAMS = kpicosim + +# the application source, library search path, and link libraries +kpicosim_SOURCES = main.cpp kpicosim.cpp codeeditor.cpp ksimulator.cpp \ + kprocessorview.cpp kserialview.cpp kportview.cpp kscratchpadview.cpp kscratchpadview.h \ + kport.cpp kexportdialog.cpp cassembler.cpp cinstruction.cpp cpicoblaze.cpp \ + jtagdevice.cpp kjtagdialog.cpp jtag.cpp jtag.h jtagprogrammer.cpp +kpicosim_LDFLAGS = $(KDE_RPATH) $(all_libraries) +kpicosim_LDADD = -lkio $(LIB_KDEUI) + +# this is where the desktop file will go +shelldesktopdir = $(kde_appsdir)/Development +shelldesktop_DATA = kpicosim.desktop + +# this is where the shell's XML-GUI resource file goes +shellrcdir = $(kde_datadir)/kpicosim +shellrc_DATA = kpicosimui.rc + +katepartdir = $(kde_datadir)/katepart/syntax +katepart_DATA = psm.xml +icondirdir = $(kde_icondir) +kde_icon_KDEICON = hi22-action-dbgrun.png hi22-action-simrun.png \ + hi22-action-simrun.png hi22-action-dbgrun.png hi22-action-dbgrun.png +SUBDIRS = pics diff --git a/src/cassembler.cpp b/src/cassembler.cpp new file mode 100755 index 0000000..1175181 --- /dev/null +++ b/src/cassembler.cpp @@ -0,0 +1,754 @@ +/* The assembler works, but it ain't a pretty sight. + * Some day, I'll rewrite this part. + * -- M6 + */ + +#include "cassembler.h" +#include "cpicoblaze.h" + +#include <stdio.h> + +#define NO_LINE_NR 0xFFFFFFFF + +const char *instructions[] = { + "ADD", "ADDCY", "AND", "CALL", "COMPARE", "DISABLE", "ENABLE", "FETCH", "INPUT", + "JUMP", "LOAD", "OR", "OUTPUT", "RETURN", "RETURNI", "ROTATE", "RL", "RR", "SL0", + "SL1", "SLA", "SLX", "SR0", "SR1", "SRA", "SRX", "STORE", "SUB", "SUBCY", "TEST", + "XOR" +} ; + +/* Helper function to make a string uppercase */ +string toUpper( string str ) +{ + string upperStr ; + unsigned int i ; + + upperStr = "" ; + for ( i = 0 ; i < str.length() ; i++ ) + upperStr += toupper( str[ i ] ) ; + + return upperStr ; +} + +CAssembler::CAssembler() +{ + m_messageList = 0 ; +} + +CAssembler::~CAssembler() +{ +} + +void CAssembler::error( unsigned int line, const char *description ) +{ + cout << line << ": " << description << "\r\n" ; + + if ( m_messageList ) { + char str[ 128 ] ; + sprintf( str, "%u", line + 1 ) ; + QListViewItem *item = new QListViewItem( m_messageList, m_messageList->lastChild() ) ; + + if ( line != NO_LINE_NR ) + item->setText( 0, str ) ; + item->setText( 1, description ) ; + } +} + +int CAssembler::getRegister( string name ) +{ + if ( name[ 0 ] != 's' || name.length() <= 1 ) + return -1 ; + + int reg ; + + if ( sscanf( name.c_str() + 1, "%X", ® ) != 1 ) + return -1 ; + + if ( reg < 0 || reg > 15 ) + return -1 ; + + return reg ; + +} + +int CAssembler::getInstruction( string name ) +{ + unsigned int i ; + string str = toUpper( name ) ; + for ( i = 0 ; i < sizeof( instructions ) / sizeof( char *); i++ ) + if ( str == instructions[ i ] ) + return i ; + return -1 ; +} + +bool CAssembler::buildSymbolTable() +{ + list<CSourceLine*>::iterator it ; + unsigned int address = 0 ; + bool ret = TRUE ; + + for ( it = m_source.begin() ; it != m_source.end() ; it++ ) { + string name = toUpper( (*it)->getColumn( 0 ) ) ; // case insensitive + + if ( name == "NAMEREG" ) { + if ( !(*it)->isColumn( 3 ) ) { + error( (*it)->m_lineNr, "'NAMEREG registername, newname' expected" ) ; + ret = FALSE ; + } + + if ( (*it)->isColumn( 4 ) ) { + error( (*it)->m_lineNr, "Rubbish found at end of line" ) ; + ret = FALSE ; + } + + if ( (*it)->getColumn( 2 ) != "," ) { + error( (*it)->m_lineNr, "Comma expected" ) ; + ret = FALSE ; + } + + + CNamereg *nr = new CNamereg ; + nr->reg = (*it)->getColumn( 1 ) ; + nr->name = (*it)->getColumn( 3 ) ; + m_registerTable.push_back( nr ) ; + (*it)->m_type = CSourceLine::stNamereg ; + + } else if ( name == "CONSTANT" ) { + if ( !(*it)->isColumn( 3 ) ) { + error( (*it)->m_lineNr, "'CONSTANT name, valued' expected" ) ; + ret = FALSE ; + } + + if ( (*it)->isColumn( 4 ) ) { + error( (*it)->m_lineNr, "Rubbish found at end of line" ) ; + ret = FALSE ; + } + + + if ( (*it)->getColumn( 2 ) != "," ) { + error( (*it)->m_lineNr, "Comma expected" ) ; + ret = FALSE ; + } + + CConstant *nr = new CConstant ; + nr->value = (*it)->getColumn( 3 ) ; + nr->name = (*it)->getColumn( 1 ) ; ; + m_constantTable.push_back( nr ) ; + (*it)->m_type = CSourceLine::stConstant ; + } else if ( name == "ADDRESS" ) { + if ( !(*it)->isColumn( 1 ) ) { + error( (*it)->m_lineNr, "Value expected" ) ; + ret = FALSE ; + } + + if ( (*it)->isColumn( 4 ) ) { + error( (*it)->m_lineNr, "Rubbish found at end of line" ) ; + ret = FALSE ; + } + + if ( sscanf( (*it)->getColumn( 1 ).c_str(), "%X", &address ) != 1 ) { + error( (*it)->m_lineNr, "Invalid address" ) ; + ret = FALSE ; + } + (*it)->m_type = CSourceLine::stAddress ; + (*it)->m_address = address ; + + } else if ( getInstruction( (*it)->getColumn( 0 ) ) < 0 ) { + CLabel *label = new CLabel ; + label->name = (*it)->getColumn( 0 ) ; + char buf[ 32 ] ; + sprintf( buf, "%d", address ) ; + label->value = buf ; + m_labelTable.push_back( label ) ; + + (*it)->m_type = CSourceLine::stLabel ; + (*it)->m_address = address ; + if ( (*it)->isColumn( 1 ) && (*it)->getColumn( 1 ) == ":" ) { + if ( (*it)->isColumn( 2 ) ) { + if ( getInstruction( (*it)->getColumn( 2 ) ) < 0 ) { + error( (*it)->m_lineNr, "Instruction expected" ) ; + ret = FALSE ; + } else { + address = address + 1 ; + } + } + } else { + error( (*it)->m_lineNr, "Label or Instruction expected" ) ; + ret = FALSE ; + } + } else { + (*it)->m_address = address ; + address = address + 1 ; + } + } + + cout << "Constants :\r\n" ; + list<CConstant*>::iterator it0 ; + for ( it0 = m_constantTable.begin() ; it0 != m_constantTable.end() ; it0++ ) { + cout << (*it0)->name << " = " << (*it0)->value << "\r\n" ; + } + + cout << "Namereg :\r\n" ; + list<CNamereg*>::iterator it1 ; + for ( it1 = m_registerTable.begin() ; it1 != m_registerTable.end() ; it1++ ) { + cout << (*it1)->reg << " = " << (*it1)->name << "\r\n" ; + } + + cout << "labels :\r\n" ; + list<CLabel*>::iterator it2 ; + for ( it2 = m_labelTable.begin() ; it2 != m_labelTable.end() ; it2++ ) { + cout << (*it2)->name << " = " << (*it2)->value << "\r\n" ; + } + return ret ; +} + +string CAssembler::translateRegister( string name ) +{ + list<CNamereg*>::iterator it1 ; + for ( it1 = m_registerTable.begin() ; it1 != m_registerTable.end() ; it1++ ) { + if ( (*it1)->name == name ) + return (*it1)->reg ; + } + + return name ; + +} + +string CAssembler::translateConstant( string name ) +{ + list<CConstant*>::iterator it1 ; + for ( it1 = m_constantTable.begin() ; it1 != m_constantTable.end() ; it1++ ) { + if ( (*it1)->name == name ) + return (*it1)->value ; + } + + return name ; +} + +string CAssembler::translateLabel( string label ) +{ + list<CLabel*>::iterator it1 ; + for ( it1 = m_labelTable.begin() ; it1 != m_labelTable.end() ; it1++ ) { + if ( (*it1)->name == label ) + return (*it1)->value ; + } + + return label ; +} + +bool CAssembler::addInstruction( instrNumber instr, CSourceLine sourceLine, int offset ) +{ + char err_desc[ 256 ] ; + unsigned int address = sourceLine.m_address ; + int maxColumn = 0 ; + string s1 = sourceLine.getColumn( offset + 1 ) ; + string s2 = sourceLine.getColumn( offset + 2 ) ; + string s3 = sourceLine.getColumn( offset + 3 ) ; + int line = sourceLine.m_lineNr ; + + uint32_t code ; + string s ; + bool b ; + switch( instr ) { + + case ENABLE: + case DISABLE: + if ( toUpper( s1 ) != "INTERRUPT" ) { + error( line, "'INTERRUPT' expected" ) ; + return FALSE ; + } + if ( instr == ENABLE ) + code = instrENABLE_INTERRUPT ; + else + code = instrDISABLE_INTERRUPT ; + + maxColumn = 2 ; + + break ; + case RETURNI: + if ( toUpper( s1 ) == "ENABLE" ) { + code = instrRETURNI_ENABLE ; + } else if ( toUpper( s1 ) == "DISABLE" ) { + code = instrRETURNI_DISABLE ; + } else { + error( line, "'ENABLE' or 'DISABLE' expected" ) ; + } + maxColumn = 2 ; + + break ; + + // Almost the same instructions + case CALL: + case JUMP: + case RETURN: + b = TRUE ; + maxColumn= 2 ; + if ( toUpper( s1 ) == "C" ) { + switch( instr ) { + case CALL : code = instrCALLC ; break ; + case JUMP : code = instrJUMPC ; break ; + case RETURN : code = instrRETURNC ; break ; + default: error( line, "'CALL', 'JUMP' or 'RETURN' expected" ) ; return FALSE ; + } + } else if ( toUpper( s1 ) == "NC" ) { + switch( instr ) { + case CALL : code = instrCALLNC ; break ; + case JUMP : code = instrJUMPNC ; break ; + case RETURN : code = instrRETURNNC ; break ; + default: error( line, "'CALL', 'JUMP' or 'RETURN' expected" ) ; return FALSE ; + } + } else if ( toUpper( s1 ) == "NZ" ) { + switch( instr ) { + case CALL : code = instrCALLNZ ; break ; + case JUMP : code = instrJUMPNZ ; break ; + case RETURN : code = instrRETURNNZ ; break ; + default: error( line, "'CALL', 'JUMP' or 'RETURN' expected" ) ; return FALSE ; + } + } else if ( toUpper( s1 ) == "Z" ) { + switch( instr ) { + case CALL : code = instrCALLZ ; break ; + case JUMP : code = instrJUMPZ ; break ; + case RETURN : code = instrRETURNZ ; break ; + default: error( line, "'CALL', 'JUMP' or 'RETURN' expected" ) ; return FALSE ; + } + } else { + switch( instr ) { + case CALL : code = instrCALL ; break ; + case JUMP : code = instrJUMP ; break ; + case RETURN : code = instrRETURN ; break ; + default: error( line, "'CALL', 'JUMP' or 'RETURN' expected" ) ; return FALSE ; + } + b = FALSE ; + maxColumn = 1 ; + } + + + if ( instr != RETURN ) { + if ( b ) { + if ( s2 != "," ) { + error( line, "Comma expected" ) ; + return FALSE ; + } + s = s3 ; + } else + s = s1 ; + + maxColumn = b ? 4 : 2 ; + + s = translateLabel( s ) ; + int labelVal ; + + if ( sscanf( s.c_str(), "%d", &labelVal ) != 1 ) { + error( line, "Invalid label" ) ; + return FALSE ; + } + + code |= labelVal ; + } + break ; + + // Instruction that expect first an registername + default: + int reg = getRegister( translateRegister( s1 ) ) ; + if ( reg < 0 ) { + error( line, "Registername expected" ) ; + return FALSE ; + } + + code = instrROTATE | (reg<<8) ; + maxColumn = 2 ; + switch ( instr ) { + case RL: code |= instrRL_SX ; break ; + case RR: code |= instrRR_SX ; break ; + case SL0: code |= instrSL0_SX ; break ; + case SL1: code |= instrSL1_SX ; break ; + case SLA: code |= instrSLA_SX ; break ; + case SLX: code |= instrSLX_SX ; break ; + case SR0: code |= instrSR0_SX ; break ; + case SR1: code |= instrSR1_SX ; break ; + case SRA: code |= instrSRA_SX ; break ; + case SRX: code |= instrSRX_SX ; break ; + + // Instructions that expect a registername and then a comma + default: + if ( s2 != "," ) { + error( line, "Comma expected" ) ; + return FALSE ; + } + + switch( instr ) { + // Instruction Register Comma '(' or value + case STORE: + case OUTPUT: + case INPUT: + case FETCH: + if ( sourceLine.getColumn( offset + 3 ) == "(" ) { + if ( !sourceLine.isColumn( offset + 5 ) || sourceLine.getColumn( offset + 5 ) != ")" ) { + error( line, "')' expected" ) ; + return FALSE ; + } + + int reg2 = getRegister( translateRegister( sourceLine.getColumn( offset + 4 ) ) ) ; + if ( reg2 < 0 ) { + error( line, "Register expected" ) ; + return FALSE ; + } + code = (reg << 8) | (reg2 << 4) ; + switch( instr ) { + case STORE : code |= instrSTORE_SX_SY ; break ; + case OUTPUT: code |= instrOUTPUT_SX_SY ; break ; + case INPUT : code |= instrINPUT_SX_SY ; break ; + case FETCH : code |= instrFETCH_SX_SY ; break ; + default: error( line, "'STORE', 'OUTPUT', 'INPUT' or 'FETCH' expected" ) ; return FALSE ; + } + maxColumn = 6 ; + } else { + + unsigned int value ; + if ( sscanf( translateConstant( s3 ).c_str(), "%X", &value ) != 1 ) { + sprintf( err_desc, "Value or (regname) expected, but \"%s\" found.", s3.c_str() ) ; + error( line, err_desc ) ; + return FALSE ; + } + + code = (reg << 8) | value ; + switch( instr ) { + case STORE : code |= instrSTORE_SX_SS ; break ; + case OUTPUT: code |= instrOUTPUT_SX_PP ; break ; + case INPUT : code |= instrINPUT_SX_PP ; break ; + case FETCH : code |= instrFETCH_SX_SS ; break ; + default: error( line, "'STORE', 'OUTPUT', 'INPUT' or 'FETCH' expected" ) ; return FALSE ; + } + maxColumn = 4 ; + } + break ; + default: + // Instruction register comma register or value + int reg2 = getRegister( translateRegister( s3 ) ) ; + + maxColumn = 4 ; + if ( reg2 < 0 ) { + unsigned int value ; + if ( sscanf( translateConstant( s3 ).c_str(), "%X", &value ) != 1 ) { + sprintf( err_desc, "Value expected, but \"%s\" found.", s3.c_str() ) ; + error( line, err_desc ) ; + return FALSE ; + } + code = (reg << 8) | value ; + switch( instr ) { + case ADD : code |= instrADD_SX_KK ; break ; + case ADDCY : code |= instrADDCY_SX_KK ; break ; + case AND : code |= instrAND_SX_KK ; break ; + case COMPARE : code |= instrCOMPARE_SX_KK ; break ; + case LOAD : code |= instrLOAD_SX_KK ; break ; + case OR : code |= instrOR_SX_KK ; break ; + case SUB : code |= instrSUB_SX_KK ; break ; + case SUBCY : code |= instrSUBCY_SX_KK ; break ; + case TEST : code |= instrTEST_SX_KK ; break ; + case XOR : code |= instrXOR_SX_KK ; break ; + default : error( line, "Unknown instruction" ) ; return FALSE ; + } + } else { + code = ( reg << 8 ) | ( reg2 << 4 ) ; + switch( instr ) { + case ADD : code |= instrADD_SX_SY ; break ; + case ADDCY : code |= instrADDCY_SX_SY ; break ; + case AND : code |= instrAND_SX_SY ; break ; + case COMPARE: code |= instrCOMPARE_SX_SY ; break ; + case LOAD : code |= instrLOAD_SX_SY ; break ; + case OR : code |= instrOR_SX_SY ; break ; + case SUB : code |= instrSUB_SX_SY ; break ; + case SUBCY : code |= instrSUBCY_SX_SY ; break ; + case TEST : code |= instrTEST_SX_SY ; break ; + case XOR : code |= instrXOR_SX_SY ; break ; + default : error( line, "Unknown instruction" ) ; return FALSE ; + } + } + } + } + } + + // Check if there's is rubbish at the end of the line + if ( sourceLine.isColumn( maxColumn + offset ) ) { + sprintf( err_desc, "'%s' found at end of instruction", sourceLine.getColumn( maxColumn + offset ).c_str() ) ; + error( line, err_desc ) ; + return FALSE ; + } + + // Finally + m_code->setInstruction( address, code, line ) ; + + return TRUE ; +} + + +bool CAssembler::exportVHDL( string templateFile, string outputDir, string entityName ) +{ + int addr, i, j, k, l, n ; + unsigned char INIT[ 32 ][ 64 ] ; /* 32 * 64 = 2048 bytes */ + unsigned char INITP[ 32 ][ 8 ] ; /* 32 * 8 = 256 bytes (Parity Table)*/ + unsigned int d ; /* 2304 Bytes Total = (18b * 1024 ) / 8 (1 instr = 18 bits )*/ + + CInstruction *instr ; + + for ( i = 0 ; i < 32 ; i++ ) + for( j = 0 ; j < 32 ; j++ ) + INIT[ i ][ j ] = 0 ; + + for ( i = 0 ; i < 32 ; i++ ) + for ( j = 0 ; j < 8 ; j++ ) + INITP[ i ][ j ] = 0 ; + + /* Build up BRAM in memory */ + for ( addr = i = j = k = l = 0, n = 0 ; addr < 1024 ; addr++ ) { + instr = m_code->getInstruction( addr ) ; + + if ( instr == NULL ) d = 0 ; + else d = instr->getHexCode() ; + + + INIT[ i++ ][ j ] = d ; // instruction( 15 downto 0 ) + INIT[ i++ ][ j ] = d >> 8; + + INITP[ k ][ l ] |= ( ( d >> 16 ) & 0x3 ) << n ; // instruction( 17 downto 16 ) ; + n += 2 ; + + if ( n >= 8 ) { + n = 0 ; + k++ ; + if ( k >= 32 ) { + l++ ; + k = 0 ; + } + } + + if ( i >= 32 ) { + i = 0 ; + j++ ; + } + } + + FILE * infile = fopen( templateFile.c_str(), "r" ) ; + if ( infile == NULL ) { + error( NO_LINE_NR, string( "Unable to open VHDL template file '" + templateFile + "'" ).c_str() ) ; + return FALSE ; + } + + string exportFile = outputDir + "/" + entityName + ".vhd" ; + FILE * outfile = fopen( exportFile.c_str(), "w" ) ; + if ( outfile == NULL ) { + error( NO_LINE_NR , string( "Unable to open VHDL template file '%s'" + exportFile + ".vhd").c_str() ) ; + return FALSE ; + } + + bool store = false, copy = false; + char varname[ 64 ] ; + int p = 0 ; + int line, c ; + while ( ( c = fgetc( infile ) ) != EOF ) { + if ( store && p < 64 ) + varname[ p++ ] = c ; + + if ( c == '{' ) { + store = true ; + p = 0 ; + } + + if ( !store && copy ) + fputc( c, outfile ) ; + + if ( c == '}' ) { + store = false ; + if ( p > 0 ) + varname[ p - 1 ] = '\0' ; + else + varname[ 0 ] = '\0' ; + if ( strncmp( "INIT_", varname, 5 ) == 0 ) { + sscanf( varname, "INIT_%02X", &line ) ; + if ( line >= 0 && line < 64 ) { + for( j = 31 ; j >= 0 ; j-- ) + fprintf( outfile, "%02X", INIT[ j ][ line ] ) ; + } + } else if ( strncmp( "INITP_", varname, 6 ) == 0 ) { + sscanf( varname, "INITP_%02X", &line ) ; + if ( line >= 0 && line < 8 ) + for( j = 31 ; j >= 0 ; j-- ) + fprintf( outfile, "%02X", INITP[ j ][ line ] ) ; + } else if ( strcmp( "name", varname ) == 0 ) { + fprintf( outfile, entityName.c_str() ) ; + } else if ( strcmp( "begin template", varname ) == 0 ) { + copy = true ; + } + } + } + + fclose( infile ) ; + fclose( outfile ) ; + + return TRUE ; +} + +bool CAssembler::exportHEX( string filename, bool mem ) +{ + FILE * file = fopen( filename.c_str(), "w" ) ; + if ( file == NULL ) { + error( NO_LINE_NR , string( "Unable to write to file '" + filename + "'").c_str() ) ; + return FALSE ; + } + + CInstruction * instr ; + uint32_t d ; + uint32_t addr ; + + /* A mem file requires the @ sign */ + if ( mem ) + fprintf( file, "@0\r\n" ) ; + + for ( addr = 0 ; addr < 1024 ; addr++ ) { + instr = m_code->getInstruction( addr ) ; + + if ( instr == NULL ) d = 0 ; + else d = instr->getHexCode() ; + + fprintf( file, "%05X\r\n", d ) ; + } + + fclose( file ) ; + + return TRUE ; +} + + +bool CAssembler::createOpcodes() +{ + list<CSourceLine*>::iterator it ; + int columnOffset ; + bool ret = TRUE ; + + for ( it = m_source.begin() ; it != m_source.end() ; it++ ) { + if ( (*it)->m_type == CSourceLine::stNamereg || + (*it)->m_type == CSourceLine::stConstant || + (*it)->m_type == CSourceLine::stAddress ) + continue ; + + if ( (*it)->m_type == CSourceLine::stLabel ) + columnOffset = 2 ; + else + columnOffset = 0 ; + + if ( !(*it)->isColumn( columnOffset + 0 ) ) // just a label + continue ; + + int instr = getInstruction( (*it)->getColumn( columnOffset + 0 ) ) ; + + if ( instr < 0 ) { + error( (*it)->m_lineNr, "Unknown instruction" ) ; + ret = FALSE ; + } + + if ( addInstruction( (instrNumber) instr, **it, columnOffset ) == FALSE ) + ret = FALSE ; + + } + return ret ; +} + +bool CAssembler::assemble( ) +{ + bool r1, r2 ; + if ( loadFile() == FALSE ) + return FALSE ; + + r1 = buildSymbolTable() ; // Even continue if symbol table failed.. + r2 = createOpcodes() ; // .. this way we get the most errors/warnings in 1 compile cycle. + return ( r1 && r2 ) ; + +} + +char * CAssembler::getWord( char *s, char *word ) { + char *start, *end ; + + *word = '\0' ; + + while ( *s == ' ' || *s == '\t' ) // skip whitespaces + s++ ; + + start = s ; + + if ( *start == '\0' || *start == '\r' || *start == '\n' || *start == ';' ) // end of line + return NULL ; + + while ( *s != ' ' && *s != '\t' && *s != '\0' && *s != '\r' && *s != '\n' && + *s != ';' && *s != ',' && *s != ':' && *s != '(' && *s != ')' ) + s++ ; + + end = s ; + + if ( start != end ) { + while ( start < end ) + *word++ = *start++ ; + *word = '\0' ; + return end ; + } else if ( *s == ',' || *s == ':' || *s == '(' || *s == ')' ) { + *word++ = *s ; + *word = '\0' ; + return end + 1 ; + } else + return NULL ; +} + +CSourceLine * CAssembler::formatLine( int lineNr, char *s ) +{ + CSourceLine *sourceLine = new CSourceLine( lineNr ) ; + char *next, word[ 256 ] ; + + next = getWord( s, word ) ; + if ( word[ 0 ] == '\0' ) { // empty line + delete sourceLine ; + return NULL ; + } + + do { + sourceLine->addColumn( word ) ; + next = getWord( next, word ) ; + if ( word[ 0 ] == '\0' ) + break ; + } while ( next != NULL ) ; + + return sourceLine ; +} + +bool CAssembler::loadFile() +{ + FILE *f ; + + f = fopen( m_filename.c_str(), "r" ) ; + + if ( f == NULL ) { + string str = "Unable to load file '" + m_filename + "'"; + error( NO_LINE_NR, str.c_str() ) ; // No linenumber information + return FALSE ; + } + char buf[ 256 ] ; + int linenr = 0 ; + while( fgets( buf, sizeof( buf ), f ) ) { + CSourceLine *sourceLine = formatLine( linenr++, buf ) ; + if ( sourceLine != NULL ) + m_source.push_back( sourceLine ) ; + } + + list<CSourceLine*>::iterator it ; + + for ( it = m_source.begin() ; it != m_source.end() ; it++ ) { + cout << "(" << (*it)->m_lineNr << ")" ; + int j = 0 ; + while ( (*it)->isColumn( j ) ) + cout << "[" << (*it)->getColumn( j++ ) << "]"; + cout << "\r\n" ; + } + + cout << "File " << m_filename << " succesfully loaded\r\n" ; + + return TRUE ; +} + diff --git a/src/cassembler.h b/src/cassembler.h new file mode 100755 index 0000000..893569a --- /dev/null +++ b/src/cassembler.h @@ -0,0 +1,147 @@ +#include <iostream> +#include <string> +#include <list> +#include <vector> +#include <klistview.h> +#include <algorithm> +#include <cctype> + +#include "types.h" + +class CCode ; + +using namespace std ; + +enum instrNumber { + ADD, ADDCY, AND, CALL, COMPARE, DISABLE, ENABLE, FETCH, INPUT, + JUMP, LOAD, OR, OUTPUT, RETURN, RETURNI, ROTATE, RL, RR, SL0, + SL1, SLA, SLX, SR0, SR1, SRA, SRX, STORE, SUB, SUBCY, TEST, + XOR +} ; + +class CNamereg { + public: + CNamereg() {} ; + ~CNamereg() {} ; + + string reg ; + string name ; +} ; + +class CConstant { + public: + CConstant() {} + ~CConstant() {} + + string value ; + string name ; +} ; + +class CLabel { + public: + CLabel() {} + ~CLabel() ; + + string value ; + string name ; +} ; + +class CSourceLine { + public: + enum SymbolType { + stNone, + stLabel, + stNamereg, + stConstant, + stAddress + } ; + + CSourceLine( unsigned int lineNr ) : m_lineNr( lineNr ) + { + m_type = stNone ; + } + ~CSourceLine() {} ; + + void addColumn( string word ) + { +/* int i ; // Case sensitive + for ( i = 0 ; i < word.length(); i++ ) + word[ i ] = toupper( word[ i ] ) ; +*/ m_line.push_back( word ) ; + } + + bool isColumn( unsigned int index ) + { + return m_line.size() > index ; + } + + string getColumn( int index ) + { + if ( !isColumn( index ) ) + return "" ; + else + return m_line[index] ; + } + + unsigned int m_lineNr; + vector<string> m_line ; + unsigned int m_address ; + SymbolType m_type ; +} ; + + +class CAssembler { + public: + CAssembler() ; + ~CAssembler() ; + + void setCode( CCode *code ) + { + m_code = code ; + } + void setFilename( string filename ) + { + m_filename = filename ; + } + bool assemble() ; + + void clear() { + m_source.clear() ; + m_registerTable.clear() ; + m_labelTable.clear() ; + m_constantTable.clear() ; + } + void setMessageList( KListView *messageList ) + { + m_messageList = messageList ; + } + + bool exportVHDL( string templateFile, string outputDir, string entityName ) ; + bool exportHEX( string filename, bool mem ) ; + + protected: + list<CSourceLine*> m_source ; + list<CNamereg*> m_registerTable ; + list<CConstant*> m_constantTable ; + list<CLabel*> m_labelTable ; + string m_filename ; + bool buildSymbolTable() ; + bool loadFile() ; + + void error( unsigned int line, const char *description ) ; + int getRegister( string name ) ; + + char * getWord( char *s, char *word ) ; + CSourceLine * formatLine( int lineNr, char *s ) ; + + int getInstruction( string name ) ; + bool createOpcodes() ; + + string translateLabel( string name ) ; + string translateConstant( string name ) ; + string translateRegister( string name ) ; + bool addInstruction( instrNumber instr, CSourceLine sourceLine, int offset ) ; + + CCode * m_code ; + KListView *m_messageList ; +} ; diff --git a/src/cinstruction.cpp b/src/cinstruction.cpp new file mode 100755 index 0000000..9c6fba8 --- /dev/null +++ b/src/cinstruction.cpp @@ -0,0 +1,907 @@ + +#include "cinstruction.h" +#include "iostream" + +using namespace std ; + + +CInstruction::CInstruction() +{ + m_cpu = (CPicoBlaze*) 0 ; +} + +CInstruction::CInstruction( CPicoBlaze *cpu, uint32_t opcode ) +{ + m_cpu = cpu ; + + sX = ( opcode & 0x0f00 ) >> 8 ; + sY = ( opcode & 0x00f0 ) >> 4 ; + kk = ( opcode & 0x00ff ) >> 0 ; + pp = ( opcode & 0x00ff ) >> 0 ; + ss = ( opcode & 0x003f ) >> 0 ; + address = ( opcode & 0x03ff ) >> 0 ; + + hexcode = opcode ; +} + +CInstruction::~CInstruction() +{ +} + +void CInstruction::Print() +{ + cout << "Unknown instruction" ; +} + +void ADD_SX_KK::Execute() +{ + uint16_t val = m_cpu->s[ sX ] + kk ; + + m_cpu->flags.carry = ( val > 255 ) ; + m_cpu->flags.zero = ( val == 0 ) || ( val == 256 ) ; + + m_cpu->s[ sX ] = val ; + m_cpu->pc->Next() ; +} + +void ADD_SX_KK::Print() +{ + cout << "ADD " << "s" << sX << "," << kk ; +} + +void ADD_SX_SY::Execute() +{ + uint16_t val = m_cpu->s[ sX ] + m_cpu->s[ sY ] ; + + m_cpu->flags.carry = ( val > 255 ) ; + m_cpu->flags.zero = ( val == 0 ) || ( val == 256 ) ; + + m_cpu->s[ sX ] = val ; + m_cpu->pc->Next() ; + +} + +void ADD_SX_SY::Print() +{ + cout << "ADD " << "s" << sX << "," << "s" << sY ; +} + +void ADDCY_SX_KK::Execute() +{ + uint16_t val = m_cpu->s[ sX ] + 1 + kk ; + + if ( m_cpu->flags.carry ) + val = m_cpu->s[ sX ] + 1 + kk ; + else + val = m_cpu->s[ sX ] + kk ; + + m_cpu->s[ sX ] = val ; + m_cpu->flags.carry = (val > 255) ; + m_cpu->flags.zero = (val == 0) || (val == 256) ; + + m_cpu->pc->Next() ; +} + +void ADDCY_SX_KK::Print() +{ + cout << "ADDCY " << "s" << sX << "," << sY ; +} + +void ADDCY_SX_SY::Execute() +{ + uint16_t val ; + + if ( m_cpu->flags.carry ) + val = m_cpu->s[ sX ] + 1 + m_cpu->s[ sY ] ; + else + val = m_cpu->s[ sX ] + m_cpu->s[ sY ] ; + + m_cpu->s[ sX ] = val ; + m_cpu->flags.carry = (val > 255) ; + m_cpu->flags.zero = (val == 0) || (val == 256) ; + + m_cpu->pc->Next() ; +} + +void ADDCY_SX_SY::Print() +{ + cout << "ADDCY " << "s" << sX << "," << "s" << sY ; +} + +void AND_SX_KK::Execute() +{ + + m_cpu->s[ sX ] = m_cpu->s[ sX ] & kk ; + m_cpu->flags.carry = 0 ; + m_cpu->flags.zero = m_cpu->s[ sX ] == 0 ; + + m_cpu->pc->Next() ; +} + +void AND_SX_KK::Print() +{ + cout << "AND " << "s" << sX << "," << sY ; +} + +void AND_SX_SY::Execute() +{ + + m_cpu->s[ sX ] = m_cpu->s[ sX ] & m_cpu->s[ sY ] ; + m_cpu->flags.carry = 0 ; + m_cpu->flags.zero = m_cpu->s[ sX ] == 0 ; + + m_cpu->pc->Next() ; +} + +void AND_SX_SY::Print() +{ + cout << "AND " << "s" << sX << "," << "s" << sY ; +} + +void CALL::Execute() +{ + m_cpu->stack->Push( ( m_cpu->pc->Get() + 1) % 0x400 ) ; + m_cpu->pc->Set( address ) ; +} + +void CALL::Print() +{ + cout << "CALL " << address ; +} + +void CALLC::Execute() +{ + if ( m_cpu->flags.carry ) { + m_cpu->stack->Push( m_cpu->pc->Get() ) ; + m_cpu->pc->Set( address ) ; + } else + m_cpu->pc->Next() ; +} + +void CALLC::Print() +{ + cout << "CALL C " << address ; +} + +void CALLNC::Execute() +{ + if ( !m_cpu->flags.carry ) { + m_cpu->stack->Push( m_cpu->pc->Get() ) ; + m_cpu->pc->Set( address ) ; + } else + m_cpu->pc->Next() ; +} + +void CALLNC::Print() +{ + cout << "CALL NC " << address ; +} + +void CALLNZ::Execute() +{ + if ( !m_cpu->flags.zero ) { + m_cpu->stack->Push( m_cpu->pc->Get() ) ; + m_cpu->pc->Set( address ) ; + } else + m_cpu->pc->Next() ; +} + +void CALLNZ::Print() +{ + cout << "CALL NZ " << address ; +} + +void CALLZ::Execute() +{ + if ( m_cpu->flags.zero ) { + m_cpu->stack->Push( m_cpu->pc->Get() ) ; + m_cpu->pc->Set( address ) ; + } else + m_cpu->pc->Next() ; +} + +void CALLZ::Print() +{ + cout << "CALL Z " << address ; +} + + +void COMPARE_SX_KK::Execute() +{ + m_cpu->flags.carry = kk > m_cpu->s[ sX ] ; + m_cpu->flags.zero = kk == m_cpu->s[ sX ] ; + + m_cpu->pc->Next() ; +} + +void COMPARE_SX_KK::Print() +{ + cout << "COMPARE s" << sX << ", " << kk ; +} + +void COMPARE_SX_SY::Execute() +{ + m_cpu->flags.carry = m_cpu->s[ sY ] > m_cpu->s[ sX ] ; + m_cpu->flags.zero = m_cpu->s[ sY ] == m_cpu->s[ sX ] ; + + m_cpu->pc->Next() ; +} + +void COMPARE_SX_SY::Print() +{ + cout << "COMPARE s" << sX << ", s" << kk ; +} + +void DISABLE_INTERRUPT::Execute() +{ + m_cpu->flags.interrupt_enable = false ; + m_cpu->pc->Next() ; +} + +void DISABLE_INTERRUPT::Print() +{ + cout << "DISABLE INTERRUPT" ; +} + +void ENABLE_INTERRUPT::Execute() +{ + m_cpu->flags.interrupt_enable = true ; + m_cpu->pc->Next() ; +} + +void ENABLE_INTERRUPT::Print() +{ + cout << "ENABLE INTERRUPT" ; +} + +void FETCH_SX_SS::Execute() +{ + m_cpu->s[ sX ] = m_cpu->scratch->Get( ss ) ; + m_cpu->pc->Next() ; +} + +void FETCH_SX_SS::Print() +{ + cout << "FETCH " << "s" << sX << ", " << ss ; +} + +void FETCH_SX_SY::Execute() +{ + m_cpu->s[ sX ] = m_cpu->scratch->Get( m_cpu->s[ sY ] & 0x3f ) ; + m_cpu->pc->Next() ; + + +} + +void FETCH_SX_SY::Print() { + cout << "FETCH " << "s" << sX << ", " << "s" << sY ; +} + +void INPUT_SX_SY::Execute() +{ + m_cpu->port->PortID( m_cpu->s[ sY ] ) ; + m_cpu->s[ sX ] = m_cpu->port->PortIn() ; + m_cpu->pc->Next() ; +} + +void INPUT_SX_SY::Print() +{ + cout << "INPUT " << "s" << sX << ", " << "s" << sY ; +} + +void INPUT_SX_PP::Execute() +{ + m_cpu->port->PortID( pp ) ; + m_cpu->s[ sX ] = m_cpu->port->PortIn() ; + m_cpu->pc->Next() ; +} + +void INPUT_SX_PP::Print() +{ + cout << "INPUT " << "s" << sX << ", " << pp ; +} + +void JUMP::Execute() +{ + m_cpu->pc->Set( address ) ; +} + +void JUMP::Print() +{ + cout << "JUMP " << address ; +} + +void JUMPC::Execute() +{ + if ( m_cpu->flags.carry ) + m_cpu->pc->Set( address ) ; + else + m_cpu->pc->Next() ; +} + +void JUMPC::Print() +{ + cout << "JUMP C " << address ; +} + +void JUMPNC::Execute() +{ + if ( !m_cpu->flags.carry ) + m_cpu->pc->Set( address ) ; + else + m_cpu->pc->Next() ; +} + +void JUMPNC::Print() +{ + cout << "JUMP NC " << address ; +} + +void JUMPNZ::Execute() +{ + if ( !m_cpu->flags.zero ) + m_cpu->pc->Set( address ) ; + else + m_cpu->pc->Next() ; +} + +void JUMPNZ::Print() +{ + cout << "JUMP NZ " << address ; +} + +void JUMPZ::Execute() +{ + if ( m_cpu->flags.zero ) + m_cpu->pc->Set( address ) ; + else + m_cpu->pc->Next() ; +} + +void JUMPZ::Print() +{ + cout << "JUMP Z " << address ; +} + +void LOAD_SX_KK::Execute() +{ + m_cpu->s[ sX ] = kk ; + m_cpu->pc->Next() ; +} + +void LOAD_SX_KK::Print() +{ + cout << "LOAD " << "s" << sX << ", " << kk ; +} + +void LOAD_SX_SY::Execute() +{ + m_cpu->s[ sX ] = m_cpu->s[ sY ] ; + m_cpu->pc->Next() ; +} + +void LOAD_SX_SY::Print() +{ + cout << "LOAD " << "s" << sX << ", " << "s" << sY ; +} + +void OR_SX_KK::Execute() +{ + m_cpu->s[ sX ] = m_cpu->s[ sX ] | kk ; + m_cpu->flags.carry = 0 ; + m_cpu->flags.zero = m_cpu->s[ sX ] == 0 ; + m_cpu->pc->Next() ; +} + +void OR_SX_KK::Print() +{ + cout << "OR " << "s" << sX << ", " << kk ; +} + +void OR_SX_SY::Execute() +{ + m_cpu->s[ sX ] = m_cpu->s[ sX ] | m_cpu->s[ sY ] ; + m_cpu->flags.carry = 0 ; + m_cpu->flags.zero = m_cpu->s[ sX ] == 0 ; + m_cpu->pc->Next() ; +} + +void OR_SX_SY::Print() +{ + cout << "OR " << "s" << sX << ", " << "s" << sY ; +} + +void OUTPUT_SX_SY::Execute() +{ + m_cpu->port->PortID( m_cpu->s[ sY ] ) ; + m_cpu->port->PortOut( m_cpu->s[ sX ] ) ; + m_cpu->pc->Next() ; +} + +void OUTPUT_SX_SY::Print() +{ + cout << "OUTPUT " << "s" << sX << ", " << "s" << sY ; +} + +void OUTPUT_SX_PP::Execute() +{ + m_cpu->port->PortID( pp ) ; + m_cpu->port->PortOut( m_cpu->s[ sX ] ) ; + m_cpu->pc->Next() ; +} + +void OUTPUT_SX_PP::Print() +{ + cout << "OUTPUT " << "s" << sX << ", " << pp ; +} + +void RETURN::Execute() +{ + m_cpu->pc->Set( m_cpu->stack->Pop() ) ; +} + +void RETURN::Print() +{ + cout << "RETURN" ; +} + +void RETURNC::Execute() +{ + if ( m_cpu->flags.carry ) + m_cpu->pc->Set( m_cpu->stack->Pop() ) ; + else + m_cpu->pc->Next() ; +} + +void RETURNC::Print() +{ + cout << "RETURN C" ; +} + +void RETURNNC::Execute() +{ + if ( !m_cpu->flags.carry ) + m_cpu->pc->Set( m_cpu->stack->Pop() ) ; + else + m_cpu->pc->Next() ; +} + +void RETURNNC::Print() +{ + cout << "RETURN NC" ; +} + +void RETURNNZ::Execute() +{ + if ( !m_cpu->flags.zero ) + m_cpu->pc->Set( m_cpu->stack->Pop() ) ; + else + m_cpu->pc->Next() ; +} + +void RETURNNZ::Print() +{ + cout << "RETURN NZ" ; +} + +void RETURNZ::Execute() +{ + if ( m_cpu->flags.zero ) + m_cpu->pc->Set( m_cpu->stack->Pop() ) ; + else + m_cpu->pc->Next() ; +} + +void RETURNZ::Print() +{ + cout << "RETURN Z" ; +} + +void RETURNI_DISABLE::Execute() +{ + m_cpu->pc->Set( m_cpu->stack->Pop() ) ; + m_cpu->flags.carry = m_cpu->flags.preserved_carry ; + m_cpu->flags.zero = m_cpu->flags.preserved_zero ; + m_cpu->flags.interrupt_enable = false ; +} + +void RETURNI_DISABLE::Print() +{ + cout << "RETURNI DISABLE" ; +} + +void RETURNI_ENABLE::Execute() +{ + m_cpu->pc->Set( m_cpu->stack->Pop() ) ; + m_cpu->flags.carry = m_cpu->flags.preserved_carry ; + m_cpu->flags.zero = m_cpu->flags.preserved_zero ; + m_cpu->flags.interrupt_enable = true ; +} + +void RETURNI_ENABLE::Print() +{ + cout << "RETURNI ENABLE" ; +} + +void RL_SX::Execute() +{ + m_cpu->flags.carry = ( m_cpu->s[ sX ] & 0x80 ) != 0 ; + + m_cpu->s[ sX ] <<= 1 ; + if ( m_cpu->flags.carry ) + m_cpu->s[ sX ] |= 1 ; + + m_cpu->flags.zero = m_cpu->s[ sX ] == 0 ; + m_cpu->pc->Next() ; +} + +void RL_SX::Print() +{ + cout << "RL s" << sX ; +} + +void RR_SX::Execute() +{ + m_cpu->flags.carry = ( m_cpu->s[ sX ] & 0x01 ) != 0 ; + + m_cpu->s[ sX ] >>= 1 ; + if ( m_cpu->flags.carry ) + m_cpu->s[ sX ] |= 0x80 ; + + m_cpu->flags.zero = m_cpu->s[ sX ] == 0 ; + m_cpu->pc->Next() ; +} + +void RR_SX::Print() +{ + cout << "RR s" << sX ; +} + + +void SL0_SX::Execute() +{ + m_cpu->flags.carry = ( m_cpu->s[ sX ] & 0x80 ) != 0 ; + + m_cpu->s[ sX ] <<= 1 ; + + m_cpu->flags.zero = m_cpu->s[ sX ] == 0 ; + m_cpu->pc->Next() ; +} + +void SL0_SX::Print() +{ + cout << "SL0 s" << sX ; +} + +void SL1_SX::Execute() +{ + m_cpu->flags.carry = ( m_cpu->s[ sX ] & 0x80 ) != 0 ; + + m_cpu->s[ sX ] <<= 1 ; + m_cpu->s[ sX ] |= 1 ; + + m_cpu->flags.zero = m_cpu->s[ sX ] == 0 ; + m_cpu->pc->Next() ; +} + +void SL1_SX::Print() +{ + cout << "SL1 s" << sX ; +} + + +void SLA_SX::Execute() +{ + bool c ; + + c = m_cpu->flags.carry ; + + m_cpu->flags.carry = ( m_cpu->s[ sX ] & 0x80 ) != 0 ; + + m_cpu->s[ sX ] <<= 1 ; + if ( c ) + m_cpu->s[ sX ] |= 1 ; + + m_cpu->flags.zero = m_cpu->s[ sX ] == 0 ; + m_cpu->pc->Next() ; +} + +void SLA_SX::Print() +{ + cout << "SLA s" << sX ; +} + + +void SLX_SX::Execute() +{ + m_cpu->flags.carry = ( m_cpu->s[ sX ] & 0x80 ) != 0 ; + + m_cpu->s[ sX ] <<= 1 ; + if ( m_cpu->s[ sX ] & 0x02 ) + m_cpu->s[ sX ] |= 1 ; + + m_cpu->flags.zero = m_cpu->s[ sX ] == 0 ; + m_cpu->pc->Next() ; +} + +void SLX_SX::Print() +{ + cout << "SLX s" << sX ; +} + + +void SR0_SX::Execute() +{ + m_cpu->flags.carry = m_cpu->s[ sX ] & 0x01 ; + m_cpu->s[ sX ] >>= 1 ; + m_cpu->flags.zero = m_cpu->s[ sX ] == 0 ; + m_cpu->pc->Next() ; +} + +void SR0_SX::Print() +{ + cout << "SR0 s" << sX ; +} + + +void SR1_SX::Execute() +{ + m_cpu->flags.carry = m_cpu->s[ sX ] & 0x01 ; + m_cpu->s[ sX ] >>= 1 ; + m_cpu->s[ sX ] |= 0x80 ; + m_cpu->flags.zero = m_cpu->s[ sX ] == 0 ; + m_cpu->pc->Next() ; +} + +void SR1_SX::Print() +{ + cout << "SR1 s" << sX ; +} + + +void SRA_SX::Execute() +{ + bool c = m_cpu->flags.carry ; + m_cpu->flags.carry = m_cpu->s[ sX ] & 0x01 ; + m_cpu->s[ sX ] >>= 1 ; + if ( c ) + m_cpu->s[ sX ] |= 0x80 ; + m_cpu->flags.zero = m_cpu->s[ sX ] == 0 ; + m_cpu->pc->Next() ; +} + +void SRA_SX::Print() +{ + cout << "SRA s" << sX ; +} + + +void SRX_SX::Execute() +{ + m_cpu->flags.carry = m_cpu->s[ sX ] & 0x01 ; + m_cpu->s[ sX ] >>= 1 ; + if ( m_cpu->s[ sX ] & 0x40 ) + m_cpu->s[ sX ] |= 0x80 ; + m_cpu->flags.zero = m_cpu->s[ sX ] == 0 ; + m_cpu->pc->Next() ; +} + +void SRX_SX::Print() +{ + cout << "SRX s" << sX ; +} + + +void STORE_SX_SS::Execute() +{ + m_cpu->scratch->Set( ss, m_cpu->s[ sX ] ) ; + m_cpu->pc->Next() ; + +} + +void STORE_SX_SS::Print() +{ + cout << "STORE s" << sX << ", " << ss ; +} + + +void STORE_SX_SY::Execute() +{ + m_cpu->scratch->Set( m_cpu->s[ sY ], m_cpu->s[ sX ] ) ; + m_cpu->pc->Next() ; +} + +void STORE_SX_SY::Print() +{ + cout << "STORE s" << sX << ", s" << sY ; +} + +void SUB_SX_KK::Execute() +{ + int val ; + + val = m_cpu->s[ sX ] ; + val -= kk ; + + m_cpu->flags.carry = val < 0 ; + m_cpu->flags.zero = val == 0 ; + + m_cpu->s[ sX ] -= kk ; + + m_cpu->pc->Next() ; +} + +void SUB_SX_KK::Print() +{ + cout << "SUB s" << sX << ", " << kk ; +} + +void SUB_SX_SY::Execute() +{ + int val ; + + val = m_cpu->s[ sX ] ; + val -= m_cpu->s[ sY ] ; + + m_cpu->flags.carry = val < 0 ; + m_cpu->flags.zero = val == 0 ; + + m_cpu->s[ sX ] -= m_cpu->s[ sY ] ; + + m_cpu->pc->Next() ; +} + +void SUB_SX_SY::Print() +{ + cout << "SUB s" << sX << ", s" << sY ; +} + + +void SUBCY_SX_KK::Execute() +{ + int val ; + bool c = m_cpu->flags.carry ; + val = m_cpu->s[ sX ] ; + val -= kk ; + if ( c ) + val -= 1 ; + + m_cpu->flags.carry = val < 0 ; + m_cpu->flags.zero = val == 0 ; + + m_cpu->s[ sX ] = val ; + + m_cpu->pc->Next() ; +} + +void SUBCY_SX_KK::Print() +{ + cout << "SUBCY s" << sX << ", " << kk ; +} + +void SUBCY_SX_SY::Execute() +{ + int val ; + bool c = m_cpu->flags.carry ; + val = m_cpu->s[ sX ] ; + val -= m_cpu->s[ sY ] ; + if ( c ) + val -= 1 ; + + m_cpu->flags.carry = val < 0 ; + m_cpu->flags.zero = val == 0 ; + m_cpu->s[ sX ] = val ; + + m_cpu->pc->Next() ; +} + +void SUBCY_SX_SY::Print() +{ + cout << "SUBCY s" << sX << ", s" << sY ; +} + +void TEST_SX_KK::Execute() +{ + uint8_t and_test = ( m_cpu->s[ sX ] & kk ) ; + m_cpu->flags.zero = and_test == 0 ; + + int i ; + + uint8_t xor_test = 0, b ; + + for ( i = 0 ; i < 7 ; i++ ) { + b = ( and_test & ( 1 << i ) ) != 0 ; + xor_test = b ^ xor_test ; + } + + m_cpu->flags.carry = xor_test != 0 ; + m_cpu->pc->Next() ; +} + +void TEST_SX_KK::Print() +{ + cout << "TEST s" << sX << ", " << kk ; +} + +void TEST_SX_SY::Execute() +{ + uint8_t and_test = ( m_cpu->s[ sX ] & m_cpu->s[ sY ] ) ; + m_cpu->flags.zero = and_test == 0 ; + + int i ; + + uint8_t xor_test = 0, b ; + + for ( i = 0 ; i < 7 ; i++ ) { + b = ( and_test & ( 1 << i ) ) != 0 ; + xor_test = b ^ xor_test ; + } + + m_cpu->flags.carry = xor_test != 0 ; + m_cpu->pc->Next() ; +} + +void TEST_SX_SY::Print() +{ + cout << "TEST s" << sX << ", s" << sY ; +} + +void XOR_SX_KK::Execute() +{ + m_cpu->s[ sX ] ^= kk ; + + m_cpu->flags.carry = false ; + m_cpu->flags.zero = m_cpu->s[ sX ] == 0 ; + m_cpu->pc->Next() ; +} + +void XOR_SX_KK::Print() +{ + cout << "XOR s" << sX << ", " << kk ; +} + + +void XOR_SX_SY::Execute() +{ + m_cpu->s[ sX ] ^= m_cpu->s[ sY ] ; + + m_cpu->flags.carry = false ; + m_cpu->flags.zero = m_cpu->s[ sX ] == 0 ; + m_cpu->pc->Next() ; +} + +void XOR_SX_SY::Print() +{ + cout << "XOR s" << sX << ", s" << sY ; +} + +void RESET_EVENT::Execute() +{ + m_cpu->pc->Set( 0 ) ; + m_cpu->flags.interrupt_enable = false ; + m_cpu->flags.zero = false ; + m_cpu->flags.carry = false ; + m_cpu->stack->Reset() ; +} + +void RESET_EVENT::Print() +{ + cout << "(RESET EVENT)" ; +} + +void INTERRUPT_EVENT::Execute() +{ + if ( m_cpu->flags.interrupt_enable ) { + m_cpu->flags.interrupt_enable = false ; + m_cpu->stack->Push( m_cpu->pc->Get() ) ; + m_cpu->flags.preserved_carry = m_cpu->flags.carry ; + m_cpu->flags.preserved_zero = m_cpu->flags.zero ; + m_cpu->pc->Set( 0x3FF ) ; + } +} + +void INTERRUPT_EVENT::Print() +{ + cout << "(INTERRUPT EVENT)" ; +} + diff --git a/src/cinstruction.h b/src/cinstruction.h new file mode 100755 index 0000000..505eb25 --- /dev/null +++ b/src/cinstruction.h @@ -0,0 +1,607 @@ + +#ifndef CINSTRUCTION +#define CINSTRUCTION + +#include "types.h" +#include "cpicoblaze.h" + +//class CPicoBlaze ; + +// CInstruction members : +// adress = Absolute instruction address +// sX = Register sX +// sY = Register sY +// kk = Immediate constant +// pp = port +// ss = Scratchpad RAM address + +class CInstruction { + + public: + CInstruction() ; + CInstruction( CPicoBlaze *cpu, uint32_t opcode ) ; + virtual ~CInstruction() ; + + virtual void Execute() = 0 ; + virtual void Print() ; + + void setSourceLine( unsigned int line ) { sourceLine = line ; } + unsigned int getSourceLine() { return sourceLine ; } + + uint32_t getHexCode() { return hexcode ; } + protected: + CPicoBlaze *m_cpu ; + + uint16_t sX, sY, ss, pp, kk, address ; + uint32_t hexcode ; + unsigned int sourceLine ; +} ; + + +class ADD_SX_KK : public CInstruction { + + public: + ADD_SX_KK( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class ADD_SX_SY : public CInstruction { + + public: + ADD_SX_SY( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class ADDCY_SX_KK : public CInstruction { + + public: + ADDCY_SX_KK( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class ADDCY_SX_SY : public CInstruction { + + public: + ADDCY_SX_SY( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class AND_SX_KK : public CInstruction { + + public: + AND_SX_KK( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class AND_SX_SY : public CInstruction { + + public: + AND_SX_SY( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class CALL : public CInstruction { + + public: + CALL( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class CALLC : public CInstruction { + + public: + CALLC( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class CALLNC : public CInstruction { + + public: + CALLNC( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class CALLNZ : public CInstruction { + + public: + CALLNZ( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class CALLZ : public CInstruction { + + public: + CALLZ( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class COMPARE_SX_KK : public CInstruction { + + public: + COMPARE_SX_KK( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class COMPARE_SX_SY : public CInstruction { + + public: + COMPARE_SX_SY( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class DISABLE_INTERRUPT : public CInstruction { + + public: + DISABLE_INTERRUPT( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class ENABLE_INTERRUPT : public CInstruction { + + public: + ENABLE_INTERRUPT( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class FETCH_SX_SS : public CInstruction { + + public: + FETCH_SX_SS( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class FETCH_SX_SY : public CInstruction { + + public: + FETCH_SX_SY( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class INPUT_SX_SY : public CInstruction { + + public: + INPUT_SX_SY( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class INPUT_SX_PP : public CInstruction { + + public: + INPUT_SX_PP( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class JUMP : public CInstruction { + + public: + JUMP( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class JUMPC : public CInstruction { + + public: + JUMPC( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class JUMPNC : public CInstruction { + + public: + JUMPNC( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class JUMPNZ : public CInstruction { + + public: + JUMPNZ( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class JUMPZ : public CInstruction { + + public: + JUMPZ( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class LOAD_SX_KK : public CInstruction { + + public: + LOAD_SX_KK( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class LOAD_SX_SY : public CInstruction { + + public: + LOAD_SX_SY( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class OR_SX_KK : public CInstruction { + + public: + OR_SX_KK( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class OR_SX_SY : public CInstruction { + + public: + OR_SX_SY( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class OUTPUT_SX_SY : public CInstruction { + + public: + OUTPUT_SX_SY( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class OUTPUT_SX_PP : public CInstruction { + + public: + OUTPUT_SX_PP( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class RETURN : public CInstruction { + + public: + RETURN( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class RETURNC : public CInstruction { + + public: + RETURNC( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class RETURNNC : public CInstruction { + + public: + RETURNNC( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class RETURNNZ : public CInstruction { + + public: + RETURNNZ( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class RETURNZ : public CInstruction { + + public: + RETURNZ( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class RETURNI_DISABLE : public CInstruction { + + public: + RETURNI_DISABLE( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class RETURNI_ENABLE : public CInstruction { + + public: + RETURNI_ENABLE( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class RL_SX : public CInstruction { + + public: + RL_SX( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class RR_SX : public CInstruction { + + public: + RR_SX( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class SL0_SX : public CInstruction { + + public: + SL0_SX( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class SL1_SX : public CInstruction { + + public: + SL1_SX( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class SLA_SX : public CInstruction { + + public: + SLA_SX( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class SLX_SX : public CInstruction { + + public: + SLX_SX( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class SR0_SX : public CInstruction { + + public: + SR0_SX( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class SR1_SX : public CInstruction { + + public: + SR1_SX( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class SRA_SX : public CInstruction { + + public: + SRA_SX( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class SRX_SX : public CInstruction { + + public: + SRX_SX( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class STORE_SX_SS : public CInstruction { + + public: + STORE_SX_SS( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class STORE_SX_SY : public CInstruction { + + public: + STORE_SX_SY( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class SUB_SX_KK : public CInstruction { + + public: + SUB_SX_KK( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class SUB_SX_SY : public CInstruction { + + public: + SUB_SX_SY( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class SUBCY_SX_KK : public CInstruction { + + public: + SUBCY_SX_KK( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class SUBCY_SX_SY : public CInstruction { + + public: + SUBCY_SX_SY( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class TEST_SX_KK : public CInstruction { + + public: + TEST_SX_KK( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class TEST_SX_SY : public CInstruction { + + public: + TEST_SX_SY( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class XOR_SX_KK : public CInstruction { + + public: + XOR_SX_KK( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; + +} ; + +class XOR_SX_SY : public CInstruction { + + public: + XOR_SX_SY( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class RESET_EVENT : public CInstruction { + + public: + RESET_EVENT( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +class INTERRUPT_EVENT : public CInstruction { + + public: + INTERRUPT_EVENT( CPicoBlaze *cpu, uint32_t opcode ) : CInstruction( cpu, opcode ) {} ; + + void Execute() ; + void Print() ; +} ; + +#endif + diff --git a/src/codeeditor.cpp b/src/codeeditor.cpp new file mode 100755 index 0000000..2e5c086 --- /dev/null +++ b/src/codeeditor.cpp @@ -0,0 +1,426 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "codeeditor.h" +#include <klibloader.h> + +#include <qmessagebox.h> +#include <kmessagebox.h> +#include <qlayout.h> +#include <kfiledialog.h> + +CodeEditor::CodeEditor(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + QVBoxLayout *layout = new QVBoxLayout(this) ; + + KLibFactory *factory = KLibLoader::self()->factory( "libkatepart" ) ; + m_doc = ( Kate::Document* ) factory->create( 0L, "kate", "KTextEditor::Document" ) ; + m_view = ( Kate::View * ) m_doc->createView( this ) ; + m_view->setIconBorder( true ) ; + + connect( m_view, SIGNAL(cursorPositionChanged()), this, SLOT(slotCursorPositionChanged()) ); + + layout->addWidget( m_view ) ; + + m_exeLine = 0 ; + m_filename = "" ; + m_bFilename = false ; + m_doc->setModified( false ); + + m_doc->setDescription((KTextEditor::MarkInterface::MarkTypes)Breakpoint, "Breakpoint"); + m_doc->setPixmap((KTextEditor::MarkInterface::MarkTypes)Breakpoint, *inactiveBreakpointPixmap()); + m_doc->setPixmap((KTextEditor::MarkInterface::MarkTypes)ActiveBreakpoint, *activeBreakpointPixmap()); + m_doc->setPixmap((KTextEditor::MarkInterface::MarkTypes)ReachedBreakpoint, *reachedBreakpointPixmap()); + m_doc->setPixmap((KTextEditor::MarkInterface::MarkTypes)DisabledBreakpoint, *disabledBreakpointPixmap()); + m_doc->setPixmap((KTextEditor::MarkInterface::MarkTypes)ExecutionPoint, *executionPointPixmap()); + m_doc->setMarksUserChangable( Bookmark | Breakpoint ); + + setHighlightMode() ; + + + m_statusBar = new KStatusBar( this ) ; + layout->addWidget( m_statusBar ) ; + m_statusBar->insertItem( "", 0, 0, true ) ; + + slotCursorPositionChanged() ; +} + +CodeEditor::~CodeEditor() +{ + if ( m_view->document()->views().count() == 1) + delete m_view->document(); + + delete m_statusBar ; +} + +void CodeEditor::slotCursorPositionChanged() +{ + unsigned int line, column ; + m_view->cursorPosition( &line, &column ) ; + m_statusBar->changeItem( QString( " Line: %1 Col: %2 " ).arg( QString::number( line+1 ) ).arg( QString::number( column+1 ) ), 0 ) ; +} + +void CodeEditor::slotToggleBreakpoint() +{ + unsigned int line, col ; + + m_view->cursorPosition( &line, &col ) ; + + if ( !isBreakpoint( line ) ) + if ( m_doc->mark( m_exeLine ) & ExecutionPoint ) + m_doc->setMark( line, Breakpoint | ExecutionPoint) ; + else + m_doc->setMark( line, Breakpoint ) ; + else + m_doc->removeMark( line, Breakpoint ) ; +} + +void CodeEditor::clearExecutionMarker() +{ + m_doc->removeMark( m_exeLine, ExecutionPoint ) ; +} + +void CodeEditor::setCursor( unsigned int line ) +{ + m_view->setCursorPosition( line, 0 ) ; +} + +void CodeEditor::setExecutionMarker( unsigned int line ) +{ + m_doc->removeMark( m_exeLine,ExecutionPoint ) ; + m_exeLine = line ; + if ( isBreakpoint( line ) ) { + m_doc->setMark( m_exeLine, ExecutionPoint| Breakpoint ) ; + } else + m_doc->setMark( m_exeLine, ExecutionPoint ) ; + + setCursor( line ) ; // KDevelop does this too! + +} + +bool CodeEditor::isBreakpoint( unsigned int line ) +{ + return ( ( m_doc->mark( line ) & Breakpoint ) != 0 ) ; +} + +void CodeEditor::slotNewFile() +{ + m_doc->clear() ; + m_doc->setModified( false ) ; + m_filename = "" ; + m_bFilename = false ; +} + +void CodeEditor::slotSaveAs() +{ + if ( m_view->saveAs() == Kate::View::SAVE_OK ) { + m_filename = m_doc->url().path() ; + m_bFilename = true ; + } +} + +bool CodeEditor::save() +{ + slotSave() ; + return m_bFilename ; +} + +void CodeEditor::slotSave() +{ + if ( !m_bFilename ) + slotSaveAs() ; + else if ( m_view->save() == Kate::View::SAVE_OK ) { + m_filename = m_doc->url().path() ; + m_bFilename = true ; + } +} + +void CodeEditor::slotPrint() +{ + m_doc->print() ; +} + +void CodeEditor::slotFind() +{ + m_view->find() ; +} + +void CodeEditor::slotFindNext() +{ + m_view->findAgain() ; +} + +void CodeEditor::slotShowConfig() +{ + m_doc->configDialog() ; +} + +void CodeEditor::slotCut() +{ + m_view->cut() ; +} + +void CodeEditor::slotCopy() +{ + m_view->copy() ; +} + +void CodeEditor::slotPaste() +{ + m_view->paste() ; +} + +void CodeEditor::slotSelectAll() +{ + m_doc->selectAll() ; +} + +void CodeEditor::slotUndo() +{ + m_doc->undo() ; +} + +void CodeEditor::slotRedo() +{ + m_doc->redo() ; +} + +void CodeEditor::slotOpen() +{ + QString filename = KFileDialog::getOpenFileName( QString::null, QString( "*.psm|PicoBlaze assembly files" ) ) ; + if ( filename != "" ) { + m_filename = filename ; + m_bFilename = true ; + m_doc->openURL( filename ) ; + setHighlightMode() ; + } +} + +void CodeEditor::open( QString filename ) +{ + if ( filename != "" ) { + m_filename = filename ; + m_bFilename = true ; + m_doc->openURL( filename ) ; + setHighlightMode() ; + } +} + +QString CodeEditor::getFilename() +{ + return m_filename ; +} + + +void CodeEditor::setHighlightMode() +{ + int i = 0; + int hlModeCount = m_doc->hlModeCount(); + while ( i < hlModeCount ) { + if ( m_doc->hlModeName( i ) == "pblazeASM" ) { + m_doc->setHlMode( i ) ; + break ; + } + i++; + } +} + +bool CodeEditor::askSave() +{ + QString filename ; + if ( m_bFilename ) + filename = m_filename ; + else + filename = "Untitled" ; + + int choice = KMessageBox::warningYesNoCancel( this, QString( "The document \'%1\' has been modified.\nDo you want to save it?").arg( filename ), "Save Document?", KGuiItem( "Save" ), KGuiItem( "Discard" ) ); + + if ( choice == KMessageBox::Yes ) + save() ; + + return ( choice != KMessageBox::Cancel ) ; +} + +bool CodeEditor::close() +{ + if ( m_doc->isModified() ) + return askSave() ; + return true ; +} + +const QPixmap* CodeEditor::inactiveBreakpointPixmap() +{ + const char*breakpoint_gr_xpm[]={ + "11 16 6 1", + "c c #c6c6c6", + "d c #2c2c2c", + "# c #000000", + ". c None", + "a c #ffffff", + "b c #555555", + "...........", + "...........", + "...#####...", + "..#aaaaa#..", + ".#abbbbbb#.", + "#abbbbbbbb#", + "#abcacacbd#", + "#abbbbbbbb#", + "#abcacacbd#", + "#abbbbbbbb#", + ".#bbbbbbb#.", + "..#bdbdb#..", + "...#####...", + "...........", + "...........", + "..........."}; + static QPixmap pixmap( breakpoint_gr_xpm ); + return &pixmap; +} + + +const QPixmap* CodeEditor::activeBreakpointPixmap() +{ + const char* breakpoint_xpm[]={ + "11 16 6 1", + "c c #c6c6c6", + ". c None", + "# c #000000", + "d c #840000", + "a c #ffffff", + "b c #ff0000", + "...........", + "...........", + "...#####...", + "..#aaaaa#..", + ".#abbbbbb#.", + "#abbbbbbbb#", + "#abcacacbd#", + "#abbbbbbbb#", + "#abcacacbd#", + "#abbbbbbbb#", + ".#bbbbbbb#.", + "..#bdbdb#..", + "...#####...", + "...........", + "...........", + "..........."}; + static QPixmap pixmap( breakpoint_xpm ); + return &pixmap; +} + + + +const QPixmap* CodeEditor::reachedBreakpointPixmap() +{ + const char*breakpoint_bl_xpm[]={ + "11 16 7 1", + "a c #c0c0ff", + "# c #000000", + "c c #0000c0", + "e c #0000ff", + "b c #dcdcdc", + "d c #ffffff", + ". c None", + "...........", + "...........", + "...#####...", + "..#ababa#..", + ".#bcccccc#.", + "#acccccccc#", + "#bcadadace#", + "#acccccccc#", + "#bcadadace#", + "#acccccccc#", + ".#ccccccc#.", + "..#cecec#..", + "...#####...", + "...........", + "...........", + "..........."}; + static QPixmap pixmap( breakpoint_bl_xpm ); + return &pixmap; +} + + +const QPixmap* CodeEditor::disabledBreakpointPixmap() +{ + const char*breakpoint_wh_xpm[]={ + "11 16 7 1", + "a c #c0c0ff", + "# c #000000", + "c c #0000c0", + "e c #0000ff", + "b c #dcdcdc", + "d c #ffffff", + ". c None", + "...........", + "...........", + "...#####...", + "..#ddddd#..", + ".#ddddddd#.", + "#ddddddddd#", + "#ddddddddd#", + "#ddddddddd#", + "#ddddddddd#", + "#ddddddddd#", + ".#ddddddd#.", + "..#ddddd#..", + "...#####...", + "...........", + "...........", + "..........."}; + static QPixmap pixmap( breakpoint_wh_xpm ); + return &pixmap; +} + + +const QPixmap* CodeEditor::executionPointPixmap() +{ + const char*exec_xpm[]={ + "11 16 4 1", + "a c #00ff00", + "b c #000000", + ". c None", + "# c #00c000", + "...........", + "...........", + "...........", + "#a.........", + "#aaa.......", + "#aaaaa.....", + "#aaaaaaa...", + "#aaaaaaaaa.", + "#aaaaaaa#b.", + "#aaaaa#b...", + "#aaa#b.....", + "#a#b.......", + "#b.........", + "...........", + "...........", + "..........."}; + static QPixmap pixmap( exec_xpm ); + return &pixmap; +} + + + + +#include "codeeditor.moc" diff --git a/src/codeeditor.h b/src/codeeditor.h new file mode 100755 index 0000000..a3a57ce --- /dev/null +++ b/src/codeeditor.h @@ -0,0 +1,98 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef CODEEDITOR_H +#define CODEEDITOR_H + +#include <qwidget.h> +#include <kate/view.h> +#include <kate/document.h> +#include <kstatusbar.h> + +class CodeEditor : public QWidget +{ + Q_OBJECT + public: + CodeEditor(QWidget *parent = 0, const char *name = 0); + ~CodeEditor(); + + void clearExecutionMarker() ; + void setExecutionMarker( unsigned int line ) ; + + QString getFilename() ; + bool isBreakpoint( unsigned int line ) ; + void setCursor( unsigned int line ) ; + + void open( QString filename ) ; + bool close() ; + bool save() ; + + protected: + Kate::View * m_view ; + Kate::Document * m_doc ; + + KStatusBar *m_statusBar ; + + unsigned int m_exeLine ; + QString m_filename ; + bool m_bFilename ; + void setHighlightMode() ; + bool askSave() ; + + enum MarkType { + Bookmark = KTextEditor::MarkInterface::markType01, + Breakpoint = KTextEditor::MarkInterface::markType02, + ActiveBreakpoint = KTextEditor::MarkInterface::markType03, + ReachedBreakpoint = KTextEditor::MarkInterface::markType04, + DisabledBreakpoint = KTextEditor::MarkInterface::markType05, + ExecutionPoint = KTextEditor::MarkInterface::markType06 + }; + + + static const QPixmap* inactiveBreakpointPixmap(); + static const QPixmap* activeBreakpointPixmap(); + static const QPixmap* reachedBreakpointPixmap(); + static const QPixmap* disabledBreakpointPixmap(); + static const QPixmap* executionPointPixmap(); + + + public slots: + void slotToggleBreakpoint() ; // set breakpoint at current position + void slotSave() ; + void slotSaveAs() ; + void slotOpen() ; + void slotShowConfig() ; + void slotFind() ; + void slotFindNext() ; + void slotNewFile() ; + void slotPrint() ; + + void slotCut() ; + void slotCopy() ; + void slotPaste() ; + + void slotUndo() ; + void slotRedo() ; + void slotSelectAll() ; + + void slotCursorPositionChanged() ; + +}; + +#endif diff --git a/src/cpicoblaze.cpp b/src/cpicoblaze.cpp new file mode 100755 index 0000000..4b85b7e --- /dev/null +++ b/src/cpicoblaze.cpp @@ -0,0 +1,436 @@ +#include "cpicoblaze.h" + +#include <iostream> + +using namespace std ; + +CProgramCounter::CProgramCounter() +{ + pc = 0 ; +} + +CProgramCounter::~CProgramCounter() +{ + +} + +void CProgramCounter::Next() +{ + pc = ( pc + 1 ) % (MAX_ADDRESS); +} + +void CProgramCounter::Set( uint16_t address ) +{ + pc = address % (MAX_ADDRESS) ; +} + +uint16_t CProgramCounter::Get() +{ + return pc ; +} + +CScratchPad::CScratchPad() +{ + int i ; + for ( i = 0 ; i < sizeof( ram ) ; i++ ) + ram[ i ] = 0 ; +} + +CScratchPad::~CScratchPad() +{ +} + +CStack::CStack() +{ + int i ; + for ( i = 0 ; i < STACK_DEPTH ; i++ ) + stack[ i ] = 0 ; + ptr = 0 ; +} + +CStack::~CStack() +{ +} + +void CStack::Push( uint16_t data ) +{ + data &= 0x3FF ; + if ( ptr == STACK_DEPTH - 1 ) + cout << ">>>>Stack overflow!<<<<\r\n" ; + + stack[ ptr ] = data ; + ptr = ( ptr + 1 ) % STACK_DEPTH ; +} + +uint16_t CStack::Pop() +{ + if ( ptr == 0 ) + cout << ">>>>Stack underflow!<<<<\r\n" ; + + ptr = ( ptr - 1 ) % STACK_DEPTH ; + return stack[ ptr ] ; +} + +void CStack::Reset() +{ + ptr = 0 ; +} + +uint8_t CScratchPad::Get( uint8_t address ) +{ + return ram[ address % sizeof( ram ) ] ; +} + +void CScratchPad::Set( uint8_t address, uint8_t data ) +{ + ram[ address % sizeof( ram ) ] = data ; +} + +CPort::CPort() +{ +} + + +CPort::~CPort() +{ +} + +void CPort::addPort( CIOPort * port ) +{ + portList.push_back( port ) ; +} + +void CPort::deletePort( CIOPort * port ) +{ + portList.remove( port ) ; +} + +uint8_t CPort::PortIn() +{ + // find appropiate port + list<CIOPort*>::iterator i ; + + for ( i = portList.begin() ; i != portList.end() ; i++ ) + if ( (*i)->getID() == portid && (*i)->isReadable() ) + return (*i)->In() ; + + + // Nothing found return zero + return 0 ; +} + +void CPort::PortOut( uint8_t data ) +{ + // find appropiate port + list<CIOPort*>::iterator i ; + + for ( i = portList.begin() ; i != portList.end() ; i++ ) + if ( (*i)->getID() == portid && (*i)->isWriteable() ) + (*i)->Out( data ) ; +} + + +CCode::CCode( CPicoBlaze *cpu ) +{ + m_cpu = cpu ; + + int i ; + for ( i = 0 ; i < MAX_ADDRESS ; i++ ) + CodeMap[ i ] = NULL ; +} + +CCode::~CCode() +{ + ClearCode() ; +} + +void CCode::ClearCode() { + int i ; + for ( i = 0 ; i < MAX_ADDRESS ; i++ ) + if ( CodeMap[ i ] != NULL ) { + delete CodeMap[ i ] ; + CodeMap[ i ] = NULL ; + } +} + +CInstruction * CCode::Disassemble( uint32_t code ) +{ + uint32_t code_17_0 = (code & 0x3ffff) ; + uint32_t code_17_12 = (code & 0x3f000) ; + uint32_t code_17_10 = (code & 0x3fC00) ; + uint32_t code_7_0 = (code & 0x000ff) ; + + /* The picoBlaze-3 instruction set */ + if ( code_17_0 == instrRETURN ) return new RETURN( m_cpu, code ) ; + if ( code_17_0 == instrRETURNC ) return new RETURNC( m_cpu, code ) ; + if ( code_17_0 == instrRETURNNC ) return new RETURNNC( m_cpu, code ) ; + if ( code_17_0 == instrRETURNNZ ) return new RETURNNZ( m_cpu, code ) ; + if ( code_17_0 == instrRETURNZ ) return new RETURNZ( m_cpu, code ) ; + if ( code_17_0 == instrRETURNI_DISABLE ) return new RETURNI_DISABLE( m_cpu, code ) ; + if ( code_17_0 == instrRETURNI_ENABLE ) return new RETURNI_ENABLE( m_cpu, code ) ; + if ( code_17_0 == instrDISABLE_INTERRUPT ) return new DISABLE_INTERRUPT( m_cpu, code ) ; + if ( code_17_0 == instrENABLE_INTERRUPT ) return new ENABLE_INTERRUPT( m_cpu, code ) ; + if ( code_17_10 == instrCALL ) return new CALL( m_cpu, code ) ; + if ( code_17_10 == instrCALLC ) return new CALLC( m_cpu, code ) ; + if ( code_17_10 == instrCALLNC ) return new CALLNC( m_cpu, code ) ; + if ( code_17_10 == instrCALLNZ ) return new CALLNZ( m_cpu, code ) ; + if ( code_17_10 == instrCALLZ ) return new CALLZ( m_cpu, code ) ; + if ( code_17_10 == instrJUMP ) return new JUMP( m_cpu, code ) ; + if ( code_17_10 == instrJUMPC ) return new JUMPC( m_cpu, code ) ; + if ( code_17_10 == instrJUMPNC ) return new JUMPNC( m_cpu, code ) ; + if ( code_17_10 == instrJUMPNZ ) return new JUMPNZ( m_cpu, code ) ; + if ( code_17_10 == instrJUMPZ ) return new JUMPZ( m_cpu, code ) ; + if ( code_17_12 == instrADD_SX_KK ) return new ADD_SX_KK( m_cpu, code ) ; + if ( code_17_12 == instrADD_SX_SY ) return new ADD_SX_SY( m_cpu, code ) ; + if ( code_17_12 == instrADDCY_SX_KK ) return new ADDCY_SX_KK( m_cpu, code ) ; + if ( code_17_12 == instrADDCY_SX_SY ) return new ADDCY_SX_SY( m_cpu, code ) ; + if ( code_17_12 == instrAND_SX_KK ) return new AND_SX_KK( m_cpu, code ) ; + if ( code_17_12 == instrAND_SX_SY) return new AND_SX_SY( m_cpu, code ) ; + if ( code_17_12 == instrCOMPARE_SX_KK ) return new COMPARE_SX_KK( m_cpu, code ) ; + if ( code_17_12 == instrCOMPARE_SX_SY ) return new COMPARE_SX_SY( m_cpu, code ) ; + if ( code_17_12 == instrFETCH_SX_SS ) return new FETCH_SX_SS( m_cpu, code ) ; + if ( code_17_12 == instrFETCH_SX_SY ) return new FETCH_SX_SY( m_cpu, code ) ; + if ( code_17_12 == instrINPUT_SX_SY ) return new INPUT_SX_SY( m_cpu, code ) ; + if ( code_17_12 == instrINPUT_SX_PP ) return new INPUT_SX_PP( m_cpu, code ) ; + if ( code_17_12 == instrLOAD_SX_KK ) return new LOAD_SX_KK( m_cpu, code ) ; + if ( code_17_12 == instrLOAD_SX_SY ) return new LOAD_SX_SY( m_cpu, code ) ; + if ( code_17_12 == instrOR_SX_KK ) return new OR_SX_KK( m_cpu, code ) ; + if ( code_17_12 == instrOR_SX_SY ) return new OR_SX_SY( m_cpu, code ) ; + if ( code_17_12 == instrOUTPUT_SX_SY ) return new OUTPUT_SX_SY( m_cpu, code ) ; + if ( code_17_12 == instrOUTPUT_SX_PP ) return new OUTPUT_SX_PP( m_cpu, code ) ; + if ( code_17_12 == instrSTORE_SX_SS ) return new STORE_SX_SS( m_cpu, code ) ; + if ( code_17_12 == instrSTORE_SX_SY ) return new STORE_SX_SY( m_cpu, code ) ; + if ( code_17_12 == instrSUB_SX_KK ) return new SUB_SX_KK( m_cpu, code ) ; + if ( code_17_12 == instrSUB_SX_SY ) return new SUB_SX_SY( m_cpu, code ) ; + if ( code_17_12 == instrSUBCY_SX_KK ) return new SUBCY_SX_KK( m_cpu, code ) ; + if ( code_17_12 == instrSUBCY_SX_SY ) return new SUBCY_SX_SY( m_cpu, code ) ; + if ( code_17_12 == instrTEST_SX_KK ) return new TEST_SX_KK( m_cpu, code ) ; + if ( code_17_12 == instrTEST_SX_SY ) return new TEST_SX_SY( m_cpu, code ) ; + if ( code_17_12 == instrXOR_SX_KK ) return new XOR_SX_KK( m_cpu, code ) ; + if ( code_17_12 == instrXOR_SX_SY ) return new XOR_SX_SY( m_cpu, code ) ; + if ( code_7_0 == instrRL_SX ) return new RL_SX( m_cpu, code ) ; + if ( code_7_0 == instrRR_SX ) return new RR_SX( m_cpu, code ) ; + if ( code_7_0 == instrSL0_SX ) return new SL0_SX( m_cpu, code ) ; + if ( code_7_0 == instrSL1_SX ) return new SL1_SX( m_cpu, code ) ; + if ( code_7_0 == instrSLA_SX ) return new SLA_SX( m_cpu, code ) ; + if ( code_7_0 == instrSLX_SX ) return new SLX_SX( m_cpu, code ) ; + if ( code_7_0 == instrSR0_SX ) return new SR0_SX( m_cpu, code ) ; + if ( code_7_0 == instrSR1_SX ) return new SR1_SX( m_cpu, code ) ; + if ( code_7_0 == instrSRA_SX ) return new SRA_SX( m_cpu, code ) ; + if ( code_7_0 == instrSRX_SX ) return new SRX_SX( m_cpu, code ) ; +/* switch( code_17_0 ) { + case instrRETURN : return new RETURN( m_cpu, code ) ; + case instrRETURNC : return new RETURNC( m_cpu, code ) ; + case instrRETURNNC : return new RETURNNC( m_cpu, code ) ; + case instrRETURNNZ : return new RETURNNZ( m_cpu, code ) ; + case instrRETURNZ : return new RETURNZ( m_cpu, code ) ; + case instrRETURNI_DISABLE : return new RETURNI_DISABLE( m_cpu, code ) ; + case instrRETURNI_ENABLE : return new RETURNI_ENABLE( m_cpu, code ) ; + case instrDISABLE_INTERRUPT : return new DISABLE_INTERRUPT( m_cpu, code ) ; + case instrENABLE_INTERRUPT : return new ENABLE_INTERRUPT( m_cpu, code ) ; + default: + switch( code_17_10 ) { + case instrCALL : return new CALL( m_cpu, code ) ; + case instrCALLC : return new CALLC( m_cpu, code ) ; + case instrCALLNC : return new CALLNC( m_cpu, code ) ; + case instrCALLNZ : return new CALLNZ( m_cpu, code ) ; + case instrCALLZ : return new CALLZ( m_cpu, code ) ; + case instrJUMP : return new JUMP( m_cpu, code ) ; + case instrJUMPC : return new JUMPC( m_cpu, code ) ; + case instrJUMPNC : return new JUMPNC( m_cpu, code ) ; + case instrJUMPNZ : return new JUMPNZ( m_cpu, code ) ; + case instrJUMPZ : return new JUMPZ( m_cpu, code ) ; + default: + switch ( code_17_12 ) { + case instrADD_SX_KK : return new ADD_SX_KK( m_cpu, code ) ; + case instrADD_SX_SY : return new ADD_SX_SY( m_cpu, code ) ; + case instrADDCY_SX_KK : return new ADDCY_SX_KK( m_cpu, code ) ; + case instrADDCY_SX_SY : return new ADDCY_SX_SY( m_cpu, code ) ; + case instrAND_SX_KK : return new AND_SX_KK( m_cpu, code ) ; + case instrAND_SX_SY : return new AND_SX_SY( m_cpu, code ) ; + case instrCOMPARE_SX_KK : return new COMPARE_SX_KK( m_cpu, code ) ; + case instrCOMPARE_SX_SY : return new COMPARE_SX_SY( m_cpu, code ) ; + case instrFETCH_SX_SS : return new FETCH_SX_SS( m_cpu, code ) ; + case instrFETCH_SX_SY : return new FETCH_SX_SY( m_cpu, code ) ; + case instrINPUT_SX_SY : return new INPUT_SX_SY( m_cpu, code ) ; + case instrINPUT_SX_PP : return new INPUT_SX_PP( m_cpu, code ) ; + case instrLOAD_SX_KK : return new LOAD_SX_KK( m_cpu, code ) ; + case instrLOAD_SX_SY : return new LOAD_SX_SY( m_cpu, code ) ; + case instrOR_SX_KK : return new OR_SX_KK( m_cpu, code ) ; + case instrOR_SX_SY : return new OR_SX_SY( m_cpu, code ) ; + case instrOUTPUT_SX_SY : return new OUTPUT_SX_SY( m_cpu, code ) ; + case instrOUTPUT_SX_PP : return new OUTPUT_SX_PP( m_cpu, code ) ; + case instrSTORE_SX_SS : return new STORE_SX_SS( m_cpu, code ) ; + case instrSTORE_SX_SY : return new STORE_SX_SY( m_cpu, code ) ; + case instrSUB_SX_KK : return new SUB_SX_KK( m_cpu, code ) ; + case instrSUB_SX_SY : return new SUB_SX_SY( m_cpu, code ) ; + case instrSUBCY_SX_KK : return new SUBCY_SX_KK( m_cpu, code ) ; + case instrSUBCY_SX_SY : return new SUBCY_SX_SY( m_cpu, code ) ; + case instrTEST_SX_KK : return new TEST_SX_KK( m_cpu, code ) ; + case instrTEST_SX_SY : return new TEST_SX_SY( m_cpu, code ) ; + case instrXOR_SX_KK : return new XOR_SX_KK( m_cpu, code ) ; + case instrXOR_SX_SY : return new XOR_SX_SY( m_cpu, code ) ; + + case instrROTATE: + switch( code_7_0 ) { + case instrRL_SX : return new RL_SX( m_cpu, code ) ; + case instrRR_SX : return new RR_SX( m_cpu, code ) ; + case instrSL0_SX : return new SL0_SX( m_cpu, code ) ; + case instrSL1_SX : return new SL1_SX( m_cpu, code ) ; + case instrSLA_SX : return new SLA_SX( m_cpu, code ) ; + case instrSLX_SX : return new SLX_SX( m_cpu, code ) ; + case instrSR0_SX : return new SR0_SX( m_cpu, code ) ; + case instrSR1_SX : return new SR1_SX( m_cpu, code ) ; + case instrSRA_SX : return new SRA_SX( m_cpu, code ) ; + case instrSRX_SX : return new SRX_SX( m_cpu, code ) ; + } + } + } + } +*/ + cout << "Invalid code (" << code << ")\r\n" ; + + return NULL ; +} + +bool CCode::setInstruction( uint16_t address, uint32_t code, unsigned int sourceLine ) +{ + CInstruction *instr = Disassemble( code ) ; + if ( instr == NULL ) { + cout << ">>>>Unknown code at address " << address << "<<<<\r\n" ; + return FALSE ; + } + + if ( address >= MAX_ADDRESS ) { + cout << ">>>>Invalid address" << address << "<<<<\r\n" ; + delete instr ; + return FALSE ; + } + + + if ( CodeMap[ address ] != NULL ) { + cout << ">>>>Code is placed at same address (" << address << ")<<<<\r\n" ; + delete instr ; + return FALSE ; + } + + instr->setSourceLine( sourceLine ) ; + CodeMap[ address ] = instr ; + + return TRUE ; +} + +CInstruction * CCode::getInstruction( uint16_t address ) +{ + if ( address >= MAX_ADDRESS ) + return NULL ; + else + return CodeMap[ address ] ; +} + +void CCode::Print() +{ + int i ; + + cout << "----listing----\r\n" ; + for ( i = 0 ; i < MAX_ADDRESS ; i++ ) { + if ( CodeMap[ i ] != NULL ) { + cout << i << " : " ; + CodeMap[ i ]->Print() ; + cout << "\r\n" ; + } + } + cout << "----end listing----\r\n" ; + +} + +CPicoBlaze::CPicoBlaze() +{ + flags.zero = false ; + flags.carry = false ; + flags.interrupt_enable = false ; + + scratch = new CScratchPad ; + pc = new CProgramCounter ; + stack = new CStack ; + port = new CPort ; + code = new CCode( this ) ; +} + +CPicoBlaze::~CPicoBlaze() +{ + delete scratch ; + delete pc ; + delete stack ; + delete port ; + delete code ; +} + +void CPicoBlaze::Reset() +{ + RESET_EVENT resetEvent( this, 0 ) ; + + resetEvent.Print() ; cout << "\r\n" ; + resetEvent.Execute() ; +} + +void CPicoBlaze::Interrupt() +{ + INTERRUPT_EVENT interruptEvent( this, 0 ) ; + +// interruptEvent.Print() ; cout << "\r\n" ; + interruptEvent.Execute() ; +} + +void CPicoBlaze::Print() +{ + int i ; + + cout << "----CPU----\r\n" ; + cout << "regs|" ; + for ( i = 0 ; i < 15 ; i++ ) + cout << "s" << i << "=" << (int) s[ i ] << "|" ; + cout << "\r\n" ; + + cout << "flags|"; + cout << "c=" << flags.carry ; + cout << "|z=" << flags.zero ; + cout << "|ie=" << flags.interrupt_enable << "|\r\n" ; + cout << "----end CPU----\r\n" ; +} + +unsigned int CPicoBlaze::GetNextSourceLine() +{ + CInstruction *instr = code->getInstruction( pc->Get() ) ; + if ( instr == NULL ) { + cout << ">>>>Error in simulation (No code found at " << pc->Get() << ")<<<<\r\n" ; + return FALSE ; + } + + return instr->getSourceLine() ; +} + +bool CPicoBlaze::Next() +{ + CInstruction *instr = code->getInstruction( pc->Get() ) ; + if ( instr == NULL ) { + cout << ">>>>Error in simulation (No code found at " << pc->Get() << ")<<<<\r\n" ; + return FALSE ; + } + + instr->Execute() ; + + return TRUE ; +} + +void CPicoBlaze::addPort( CIOPort * ioport ) +{ + port->addPort( ioport ) ; +} + +void CPicoBlaze::deletePort( CIOPort * ioport ) +{ + port->deletePort( ioport ) ; +} + + diff --git a/src/cpicoblaze.h b/src/cpicoblaze.h new file mode 100755 index 0000000..f792f23 --- /dev/null +++ b/src/cpicoblaze.h @@ -0,0 +1,154 @@ + +#ifndef CPICOBLAZE +#define CPICOBLAZE + +#include <iostream> +#include <list> + +using namespace std ; + +class CPicoBlaze ; +class CInstruction ; + +#include "types.h" +#include "cinstruction.h" +#include "hexcodes.h" + +#define MAX_ADDRESS 0x400 +#define STACK_DEPTH 31 +#define SCRATCHPAD_SIZE 64 + +#define PortReadable 1 +#define PortWriteable 2 +class CIOPort +{ + public: + + CIOPort( uint8_t id ) { m_id = id ; m_mode = 0 ; } + + virtual void Out( uint8_t val ) = 0 ; + virtual uint8_t In() = 0 ; + + uint8_t getID() { return m_id ; } + void setID( uint8_t id ) { m_id = id ; } + void setMode( int mode ) { m_mode = mode ; } + int getMode() { return m_mode ; } + bool isReadable() { return (m_mode & PortReadable) != 0 ; } + bool isWriteable() { return (m_mode & PortWriteable) != 0 ; } + + private: + uint8_t m_id ; + int m_mode ; +} ; + +class CProgramCounter { + public: + CProgramCounter() ; + ~CProgramCounter() ; + + void Next() ; + void Set( uint16_t address ) ; + uint16_t Get() ; + + protected: + uint16_t pc ; +} ; + +class CScratchPad { + public: + CScratchPad() ; + ~CScratchPad() ; + + uint8_t Get( uint8_t address ) ; + void Set( uint8_t address, uint8_t data ) ; + + protected: + uint8_t ram[ SCRATCHPAD_SIZE ] ; +} ; + +class CStack { + public: + CStack() ; + ~CStack() ; + + void Push( uint16_t value ) ; + uint16_t Pop() ; + void Reset() ; + + protected: + uint16_t stack[ STACK_DEPTH ] ; + uint8_t ptr ; +} ; + +class CPort { + public: + CPort() ; + ~CPort() ; + + void PortID( uint8_t id ) { portid = id ; } ; + uint8_t PortIn() ; + void PortOut( uint8_t data ) ; + + void addPort( CIOPort * port ) ; + void deletePort( CIOPort * port ) ; + + protected: + uint16_t portid ; + + list<CIOPort*> portList ; + +} ; + +class CCode { + public: + CCode( CPicoBlaze *cpu ) ; + ~CCode() ; + + bool setInstruction( uint16_t address, uint32_t code, unsigned int sourceLine ) ; + CInstruction *getInstruction( uint16_t address ) ; + + void ClearCode() ; + void Print() ; + + CInstruction * Disassemble( uint32_t code ) ; + + protected: + CPicoBlaze *m_cpu ; + + CInstruction * CodeMap[ MAX_ADDRESS ] ; +} ; + +class CPicoBlaze { + + public: + CPicoBlaze() ; + ~CPicoBlaze() ; + + unsigned int GetNextSourceLine() ; + bool Next() ; + void Reset() ; + void Interrupt() ; + void Print() ; + + void addPort( CIOPort * ioport ) ; + void deletePort( CIOPort * ioport ) ; + + uint8_t s[ 16 ] ; + struct _flags { + bool zero ; + bool carry ; + bool interrupt_enable ; + + bool preserved_zero ; + bool preserved_carry ; + } flags ; + + CProgramCounter *pc ; + CScratchPad *scratch ; + CStack *stack ; + CPort *port ; + CCode *code ; +} ; + +#endif + diff --git a/src/hexcodes.h b/src/hexcodes.h new file mode 100755 index 0000000..ab326fc --- /dev/null +++ b/src/hexcodes.h @@ -0,0 +1,64 @@ +#ifndef HEXCODES +#define HEXCODES + +#define instrADD_SX_KK 0x18000 +#define instrADD_SX_SY 0x19000 +#define instrADDCY_SX_KK 0x1A000 +#define instrADDCY_SX_SY 0x1B000 +#define instrAND_SX_KK 0x0A000 +#define instrAND_SX_SY 0x0B000 +#define instrCALL 0x30000 +#define instrCALLC 0x31800 +#define instrCALLNC 0x31C00 +#define instrCALLNZ 0x31400 +#define instrCALLZ 0x31000 +#define instrCOMPARE_SX_KK 0x14000 +#define instrCOMPARE_SX_SY 0x15000 +#define instrDISABLE_INTERRUPT 0x3C000 +#define instrENABLE_INTERRUPT 0x3C001 +#define instrFETCH_SX_SS 0x06000 +#define instrFETCH_SX_SY 0x07000 +#define instrINPUT_SX_SY 0x05000 +#define instrINPUT_SX_PP 0x04000 +#define instrJUMP 0x34000 +#define instrJUMPC 0x35800 +#define instrJUMPNC 0x35C00 +#define instrJUMPNZ 0x35400 +#define instrJUMPZ 0x35000 +#define instrLOAD_SX_KK 0x00000 +#define instrLOAD_SX_SY 0x01000 +#define instrOR_SX_KK 0x0C000 +#define instrOR_SX_SY 0x0D000 +#define instrOUTPUT_SX_SY 0x2D000 +#define instrOUTPUT_SX_PP 0x2C000 +#define instrRETURN 0x2A000 +#define instrRETURNC 0x2B800 +#define instrRETURNNC 0x2BC00 +#define instrRETURNNZ 0x2B400 +#define instrRETURNZ 0x2B000 +#define instrRETURNI_DISABLE 0x38000 +#define instrRETURNI_ENABLE 0x38001 +#define instrROTATE 0x20000 +#define instrRL_SX 0x00002 +#define instrRR_SX 0x0000C +#define instrSL0_SX 0x00006 +#define instrSL1_SX 0x00007 +#define instrSLA_SX 0x00000 +#define instrSLX_SX 0x00004 +#define instrSR0_SX 0x0000E +#define instrSR1_SX 0x0000F +#define instrSRA_SX 0x00008 +#define instrSRX_SX 0x0000A +#define instrSTORE_SX_SS 0x2E000 +#define instrSTORE_SX_SY 0x2F000 +#define instrSUB_SX_KK 0x1C000 +#define instrSUB_SX_SY 0x1D000 +#define instrSUBCY_SX_KK 0x1E000 +#define instrSUBCY_SX_SY 0x1F000 +#define instrTEST_SX_KK 0x12000 +#define instrTEST_SX_SY 0x13000 +#define instrXOR_SX_KK 0x0E000 +#define instrXOR_SX_SY 0x0F000 + +#endif + diff --git a/src/hi16-app-kpicosim.png b/src/hi16-app-kpicosim.png Binary files differnew file mode 100755 index 0000000..74b759f --- /dev/null +++ b/src/hi16-app-kpicosim.png diff --git a/src/hi32-app-kpicosim.png b/src/hi32-app-kpicosim.png Binary files differnew file mode 100755 index 0000000..3f0c83f --- /dev/null +++ b/src/hi32-app-kpicosim.png diff --git a/src/jtag.cpp b/src/jtag.cpp new file mode 100644 index 0000000..461b511 --- /dev/null +++ b/src/jtag.cpp @@ -0,0 +1,326 @@ +#include "jtag.h" +#include <errno.h> +#include <string.h> +#include <iostream> +#include <linux/lp.h> +#include <sys/ioctl.h> +#include <errno.h> +#include <unistd.h> + +#include <linux/ppdev.h> +#include <linux/parport.h> + +using namespace std ; + + +#define JTAG_TDO PARPORT_STATUS_SELECT +#define JTAG_TDI ( 1 << 0 ) +#define JTAG_CLK ( 1 << 1 ) +#define JTAG_TMS ( 1 << 2 ) +#define XILINX_PROG ( 1 << 4 ) + +const char *jtag_states[] = { + "UNDEFINED", "TEST_LOGIC_RESET", "RUN_TEST_IDLE", "SELECT_DR_SCAN", "CAPTURE_DR", "SHIFT_DR", "EXIT_DR", "PAUSE_DR", + "EXIT2_DR", "UPDATE_DR", "SELECT_IR_SCAN", "CAPTURE_IR", "SHIFT_IR", "EXIT_IR", "PAUSE_IR", "EXIT2_IR", "UPDATE_IR" +} ; + +CJTAG::CJTAG() +{ + m_state = ST_UNDEFINED ; + m_fd = -1 ; + m_open = false ; + m_verbose = false ; + +} + +CJTAG::~CJTAG() +{ + if ( m_open ) + close() ; +} + +void CJTAG::error( char *str ) +{ + cout << "JTAG ERROR: " << str << "\r\n" ; +} + +bool CJTAG::open( char *dev ) +{ + if ( m_open ) + close() ; + +// m_fd = ::open( dev, O_WRONLY | O_NONBLOCK ) ; + + m_fd = ::open( dev, O_RDWR ) ; + if ( m_fd < 0 ) { + cerr << "Please check if you have read/write right to device '" << dev << "'" << endl ; + error( strerror( errno ) ) ; + return false ; + } + +// cout << "Successfully opened \"" << dev << "\"\r\n" ; + + if ( ioctl( m_fd, PPCLAIM ) ) + cout << "Unable to claim parallel port" << endl ; + +// if ( ioctl( m_fd, LPRESET, 0 ) ) +// cout << "reset returned non-zero" << endl ; + + int i ; + for ( i = 0 ; i < 10 ; i++ ) + execute( 1, 0 ) ; + + m_state = ST_TEST_LOGIC_RESET ; + + execute( 0, 0 ) ; + + m_open = true ; + + return true ; +} + +bool CJTAG::isOpen() +{ + return m_open ; +} + +void CJTAG::close() +{ + if ( m_open && m_fd >= 0 ) { + char c = 0 ; + ioctl( m_fd, PPWDATA, &c ) ; + ioctl( m_fd, PPRELEASE ) ; + ::close( m_fd ) ; + m_open = false ; + } +} + +void CJTAG::selectIR() +{ + if ( m_state == ST_TEST_LOGIC_RESET ) + execute( 0, 0 ) ; + + while ( m_state != ST_SELECT_IR_SCAN ) + execute( 1, 0 ) ; + + // capture ir + execute( 0, 0 ) ; + + // shift ir + execute( 0, 0 ) ; +} + +void CJTAG::setIR( bool *instruction, int len ) +{ + while ( len-- ) + execute( 0, *instruction++ ) ; + +} + +void CJTAG::exitIR( bool b ) +{ + // exit ir + execute( 1, b ) ; + + // update ir + execute( 1, 0 ) ; +} + +void CJTAG::selectRunTestIdle() +{ + if ( m_state != ST_RUN_TEST_IDLE ) { + if ( m_state == ST_SELECT_IR_SCAN || m_state == ST_SELECT_DR_SCAN ) + execute( 0, 0 ) ; + while ( m_state != ST_UPDATE_DR && m_state != ST_UPDATE_IR ) + execute( 1, 0 ) ; + execute( 0, 0 ) ; + } +} + +void CJTAG::selectTestLogicReset() +{ + while ( m_state != ST_TEST_LOGIC_RESET ) + execute( 1, 0 ) ; +} + +void CJTAG::selectDR() +{ + if ( m_state == ST_TEST_LOGIC_RESET ) + execute( 0, 0 ) ; + + while ( m_state != ST_SELECT_DR_SCAN ) + execute( 1, 0 ) ; + + // capture dr + execute( 0, 0 ) ; + + // shift dr + execute( 0, 0 ) ; +} + +void CJTAG::setDR( bool *data, bool *out, int len ) +{ + // shift dr in, and get data + if ( m_verbose ) { + while ( len-- ) { + cout << (*data ? "1" : "0") ; + *out++ = execute( 0, *data++ ) ; + } + cout << endl ; + } else { + while ( len-- ) + *out++ = execute( 0, *data++ ) ; + } +} + +void CJTAG::setVerbose( bool verbose ) +{ + m_verbose = verbose ; +} + +bool CJTAG::exitDR( bool data ) +{ + // exit dr + return execute( 1, data ) ; +} + + +inline bool CJTAG::step( bool TMS, bool TDI ) +{ + uint8_t c ; + int status ; + + c = XILINX_PROG ; // output enable + if ( TMS ) c |= JTAG_TMS ; + if ( TDI ) c |= JTAG_TDI ; + + c |= JTAG_CLK ; + ioctl( m_fd, PPWDATA, &c ) ; + c &= ~JTAG_CLK ; + ioctl( m_fd, PPWDATA, &c ) ; + + // read TDO + ioctl( m_fd, PPRSTATUS, &status ) ; + + c |= JTAG_CLK ; + ioctl( m_fd, PPWDATA, &c ) ; + + return (status & JTAG_TDO) != 0 ; +} + +bool CJTAG::execute( bool TMS, bool TDI ) +{ + bool TDO ; + + TDO = step( TMS , TDI ) ; + + switch ( m_state ) { + case ST_TEST_LOGIC_RESET: + if ( TMS ) + m_state = ST_TEST_LOGIC_RESET ; + else + m_state = ST_RUN_TEST_IDLE ; + break ; + case ST_RUN_TEST_IDLE: + if ( TMS ) + m_state = ST_SELECT_DR_SCAN ; + else + m_state = ST_RUN_TEST_IDLE ; + break ; + case ST_SELECT_DR_SCAN: + if ( TMS ) + m_state = ST_SELECT_IR_SCAN ; + else + m_state = ST_CAPTURE_DR ; + break ; + case ST_CAPTURE_DR: + if ( TMS ) + m_state = ST_EXIT_DR ; + else + m_state = ST_SHIFT_DR ; + break ; + case ST_SHIFT_DR: + if ( TMS ) + m_state = ST_EXIT_DR ; + else + m_state = ST_SHIFT_DR ; + break ; + case ST_EXIT_DR: + if ( TMS ) + m_state = ST_UPDATE_DR ; + else + m_state = ST_PAUSE_DR ; + break ; + case ST_PAUSE_DR: + if ( TMS ) + m_state = ST_EXIT2_DR ; + else + m_state = ST_PAUSE_DR ; + break ; + case ST_EXIT2_DR: + if ( TMS ) + m_state = ST_UPDATE_DR ; + else + m_state = ST_SHIFT_DR ; + break ; + case ST_UPDATE_DR: + if ( TMS ) + m_state = ST_SELECT_DR_SCAN ; + else + m_state = ST_RUN_TEST_IDLE ; + break ; + case ST_SELECT_IR_SCAN: + if ( TMS ) + m_state = ST_TEST_LOGIC_RESET ; + else + m_state = ST_CAPTURE_IR ; + break ; + case ST_CAPTURE_IR: + if ( TMS ) + m_state = ST_EXIT_IR ; + else + m_state = ST_SHIFT_IR ; + break ; + case ST_SHIFT_IR: + if ( TMS ) + m_state = ST_EXIT_IR ; + else + m_state = ST_SHIFT_IR ; + break ; + case ST_EXIT_IR: + if ( TMS ) + m_state = ST_UPDATE_IR ; + else + m_state = ST_PAUSE_IR ; + break ; + case ST_PAUSE_IR: + if ( TMS ) + m_state = ST_EXIT2_IR ; + else + m_state = ST_PAUSE_IR ; + break ; + case ST_EXIT2_IR: + if ( TMS ) + m_state = ST_UPDATE_IR ; + else + m_state = ST_SHIFT_IR ; + break ; + case ST_UPDATE_IR: + if ( TMS ) + m_state = ST_SELECT_DR_SCAN ; + else + m_state = ST_RUN_TEST_IDLE ; + break ; + default: + break ; + } + +// cout << "state( " << (TMS != 0) << ", " << (TDI != 0) << "): " << jtag_states[ m_state ] << "\r\n" ; + + return TDO ; +} + +void CJTAG::printState() +{ + cout << "State = " << jtag_states[ m_state ] << endl ; +} diff --git a/src/jtag.h b/src/jtag.h new file mode 100644 index 0000000..2bdb322 --- /dev/null +++ b/src/jtag.h @@ -0,0 +1,63 @@ +#include <stdint.h> +#include <fcntl.h> + + +class CJTAG { + public: + enum JTAG_STATE { + ST_UNDEFINED, + ST_TEST_LOGIC_RESET, + ST_RUN_TEST_IDLE, + ST_SELECT_DR_SCAN, + ST_CAPTURE_DR, + ST_SHIFT_DR, + ST_EXIT_DR, + ST_PAUSE_DR, + ST_EXIT2_DR, + ST_UPDATE_DR, + ST_SELECT_IR_SCAN, + ST_CAPTURE_IR, + ST_SHIFT_IR, + ST_EXIT_IR, + ST_PAUSE_IR, + ST_EXIT2_IR, + ST_UPDATE_IR + } ; + CJTAG() ; + ~CJTAG() ; + + bool open( char *dev ) ; + void close() ; + + void selectIR() ; + void setIR( bool *instruction, int len ) ; + void exitIR( bool b ) ; + + void selectDR() ; + void setDR( bool *data, bool *out, int len ) ; // 'data' is replaced by data that is read. + bool exitDR( bool data ) ; + + + void selectRunTestIdle() ; + void selectTestLogicReset() ; + + bool execute( bool TMS, bool TDI ) ; + + void setVerbose( bool verbose ) ; + + void printState() ; + + bool isOpen() ; + private: + void error( char *str ) ; + bool step( bool TMS, bool TDI ) ; + + int m_fd ; + bool m_open ; + enum JTAG_STATE m_state ; + + bool m_verbose ; + +} ; + + diff --git a/src/jtagdevice.cpp b/src/jtagdevice.cpp new file mode 100644 index 0000000..22dd43d --- /dev/null +++ b/src/jtagdevice.cpp @@ -0,0 +1,31 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "jtagdevice.h" + +JTAGDevice::JTAGDevice() +{ +} + + +JTAGDevice::~JTAGDevice() +{ +} + + diff --git a/src/jtagdevice.h b/src/jtagdevice.h new file mode 100644 index 0000000..6701acc --- /dev/null +++ b/src/jtagdevice.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef JTAGDEVICE_H +#define JTAGDEVICE_H + +/* JTAG IDCODE's for Spartan-3 Devices */ +#define XC3S50 0x0140C093 +#define XC3S200 0x01414093 +#define XC3S400 0x0141C093 +#define XC3S1000 0x01428093 +#define XC3S1500 0x01434093 +#define XC3S2000 0x01440093 +#define XC3S4000 0x01448093 +#define XC3S5000 0x01450093 + + +class JTAGDevice{ + public: + JTAGDevice(); + ~JTAGDevice(); +}; + +#endif diff --git a/src/jtagprogrammer.cpp b/src/jtagprogrammer.cpp new file mode 100644 index 0000000..f825fd7 --- /dev/null +++ b/src/jtagprogrammer.cpp @@ -0,0 +1,233 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +/* FIXME + * + * This source is still a mess. + * I will clean it in the (near?) future. + * + */ + +#include "jtagprogrammer.h" +#include <iostream> +#include <qapplication.h> +#include <qeventloop.h> + +bool IDCODE_PROM[] = { 0, 1, 1, 1, 1, 1, 1, 1 } ; +bool BYPASS_PROM[] = { 1, 1, 1, 1, 1, 1, 1, 1 } ; +bool IDCODE[] = { 1, 0, 0, 1, 0, 0 } ; +bool CFG_IN[] = { 1, 0, 1, 0, 0, 0 } ; +bool JSTART[] = { 0, 0, 1, 1, 0, 0 } ; +bool JPROGRAM[] = { 1, 1, 0, 1, 0, 0 } ; +bool JSHUTDOWN[] = { 1, 0, 1, 1, 0, 0 } ; +bool USER1[] = { 0, 1, 0, 0, 0, 0 } ; +bool USER2[] = { 1, 1, 0, 0, 0, 0 } ; + +#define XCF02S 0x05045093 +#define XC3S50 0x0140C093 +#define XC3S200 0x01414093 +#define XC3S400 0x0141C093 +#define XC3S1000 0x01428093 +#define XC3S1500 0x01434093 +#define XC3S2000 0x01440093 +#define XC3S4000 0x01448093 +#define XC3S5000 0x01450093 + +#define ID_LEN 32 + +const char *id_string[] = +{ + "XS3S50", "XS3S200", "XS3S400", "XS3S1000", "XS3S1500", "XS3S2000", "XS3S4000", "XS3S5000", + "XCF02S" +} ; + +const unsigned int id_code[] = +{ + XC3S50, XC3S200, XC3S400, XC3S1000, XC3S1500, XC3S2000, XC3S4000, XC3S5000, + XCF02S +} ; + +#define MAX_IDS ( sizeof( id_code ) / sizeof( int ) ) + +JTAGProgrammer::JTAGProgrammer( QObject *parent ) +{ + m_parent = parent ; + m_bitFilename = "" ; + + m_dev = new CJTAG ; +} + + +JTAGProgrammer::~JTAGProgrammer() +{ + m_dev->close() ; + delete m_dev ; +} + +int JTAGProgrammer::getDevice( bool *id ) { + unsigned int j, dev_id ; + + for ( j = 0, dev_id = 0 ; j < ID_LEN ; j++ ) { + dev_id |= id[ j ] << j ; + } + + for ( j = 0 ; j < MAX_IDS ; j++ ) { + if ( id_code[j] == dev_id ) { + std::string s ; + s = std::string( "Found Device : ") + id_string[j] + std::string( "\n" ); + emit message( s.c_str() ) ; + return dev_id ; + } + } + + std::cout << "Unknown ID: " << std::hex << dev_id << "\n" ; + + return 0 ; +} + +void JTAGProgrammer::program() +{ + if ( m_bitFilename == "" ) { + emit message( "No filename given\n" ) ; + return ; + } + + bool id[ ID_LEN], ones[ ID_LEN ], dummy[ 32 ] ; + int device0, device1 ; + bool prom_present = true ; + + for ( int i = 0 ; i < ID_LEN ; i++ ) + ones[i] = 1 ; + + if ( m_dev->isOpen() ) + return ; + + if ( !m_dev->open( (char*) "/dev/parport0" ) ) { + emit message( "/dev/parport0 could not be opened; check permissions\n" ) ; + return ; + } +/* ...Get device(s)... */ + m_dev->selectIR() ; + m_dev->setIR( IDCODE_PROM, 8 ) ; + m_dev->setIR( IDCODE, 5 ) ; + m_dev->exitIR( IDCODE[5] ) ; + + m_dev->selectDR() ; + m_dev->setDR( ones, id, ID_LEN ) ; + + device0 = getDevice( id ) ; + + if ( !device0 ) { + emit message( "Unknown device in JTAG chain\n" ) ; + goto exit ; + } + m_dev->setDR( ones, id, ID_LEN-1 ) ; + id[ 31 ] = m_dev->exitDR( 1 ) ; + + device1 = getDevice( id ) ; + if ( !device1 ) { + emit message( "Second device is unknown (I will try to continue)\n" ) ; + prom_present = false ; + } + +/* ....Setup for configuration..... */ + m_dev->selectIR() ; + m_dev->setIR( JPROGRAM, 5 ) ; /* Clear configuration memory */ + m_dev->exitIR( JPROGRAM[5] ) ; /* Although this is not documented?? */ + + m_dev->selectIR(); + if ( prom_present ) m_dev->setIR( BYPASS_PROM, 8 ) ; + m_dev->setIR( JSHUTDOWN, 5 ) ; + m_dev->exitIR( JSHUTDOWN[5] ) ; + + m_dev->selectRunTestIdle() ; + for ( int i = 0 ; i < 20 ; i++ ) /* Shutdown sequence */ + m_dev->execute( 0, 0 ) ; + + m_dev->selectIR() ; + if ( prom_present ) m_dev->setIR( BYPASS_PROM, 8 ) ; + m_dev->setIR( CFG_IN, 5 ) ; + m_dev->exitIR( CFG_IN[5] ) ; + +/* ....Send bit file.....*/ + FILE *bit_file ; + bit_file = fopen( m_bitFilename.c_str(), "r" ) ; + if ( bit_file == NULL ) { + emit message( "Could not read bit file\n" ) ; + goto exit ; + } + + int size ; + bool frame[ 8 ] ; + unsigned int cur, next ; + size = 0 ; + + m_dev->selectDR() ; + fread( &cur, 1, 1, bit_file ) ; + + int prog, prev_prog, total ; + fseek( bit_file, 0, SEEK_END ) ; + total = ftell( bit_file ) ; + rewind( bit_file ) ; + + emit message( "Programming..." ) ; + for (prog=prev_prog=0;;) { + for ( int i = 0 ; i < 8; i++, cur <<= 1 ) + frame[i] = (cur & 0x80 ) != 0 ; + + size += 1; + + emit progress( size*100/total ) ; + + if ( fread( &next, 1, 1, bit_file ) == 0 ) + break ; + m_dev->setDR( frame, dummy, 8 ) ; + cur = next ; + + QApplication::eventLoop()->processEvents( QEventLoop::AllEvents ) ; + } + std::cout << std::endl ; + + m_dev->setDR( frame, dummy, 7 ) ; + m_dev->exitDR( frame[7] ) ; + fclose( bit_file ) ; + +/*....Start FPGA.....*/ + m_dev->selectTestLogicReset() ; + + m_dev->selectIR() ; + if ( prom_present ) m_dev->setIR( BYPASS_PROM, 8 ) ; + m_dev->setIR( JSTART, 5 ) ; + m_dev->exitIR( JSTART[5] ) ; + + m_dev->selectRunTestIdle() ; + for ( int i = 0 ; i < 20 ; i++ ) /* Start up sequence */ + m_dev->execute( 0, 0 ) ; + + emit message( "done.\n" ) ; +exit: + m_dev->close() ; +} + +void JTAGProgrammer::setBitFile( std::string filename ) +{ + m_bitFilename = filename ; +} + diff --git a/src/jtagprogrammer.h b/src/jtagprogrammer.h new file mode 100644 index 0000000..becb368 --- /dev/null +++ b/src/jtagprogrammer.h @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef JTAGPROGRAMMER_H +#define JTAGPROGRAMMER_H + +#include <qobject.h> +#include <string.h> +#include "jtag.h" +class JTAGProgrammer : public QObject +{ + Q_OBJECT + + public: + JTAGProgrammer( QObject *parent ); + ~JTAGProgrammer(); + + void setBitFile( std::string filename ) ; + + void program() ; + + signals: + void progress( int percent ) ; + void message( const char *msg ) ; + + + protected: + int getDevice( bool *id ) ; + + std::string m_bitFilename ; + + CJTAG *m_dev ; + QObject *m_parent ; + +}; + +#endif diff --git a/src/kexportdialog.cpp b/src/kexportdialog.cpp new file mode 100755 index 0000000..ae5a444 --- /dev/null +++ b/src/kexportdialog.cpp @@ -0,0 +1,158 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "kexportdialog.h" +#include <kfiledialog.h> + +KExportDialog::KExportDialog( QWidget *parent, const char *name ) : QDialog(parent, name) +{ + m_templateFile = "" ; + m_outputDir = "" ; + + QLabel *label = new QLabel( this ) ; + label->setText( "Template file" ) ; + label->move( 10, 10 ) ; + + label = new QLabel( this ) ; + label->setText( "Output directory" ) ; + label->move( 10, 35 ) ; + + label = new QLabel( this ) ; + label->setText( "Entity name" ) ; + label->move( 10, 60 ) ; + + m_lineTemplateFile = new KLineEdit( this ) ; + m_lineTemplateFile->setText( "" ) ; + m_lineTemplateFile->setFixedSize( 150, 20 ) ; + m_lineTemplateFile->move( 110, 10 ) ; + + m_lineOutputDir = new KLineEdit( this ) ; + m_lineOutputDir->setText( "" ) ; + m_lineOutputDir->setFixedSize( 150, 20 ) ; + m_lineOutputDir->move( 110, 35 ) ; + + m_lineEntityName = new KLineEdit( this ) ; + m_lineEntityName->setText( "" ) ; + m_lineEntityName->setFixedSize( 150, 20 ) ; + m_lineEntityName->move( 110, 60 ) ; + + QPushButton *button = new QPushButton( this ) ; + button->setText( "OK" ) ; + button->setFixedSize( 60, 25 ) ; + button->move( 100, 90 ) ; + connect( button, SIGNAL( clicked() ), this, SLOT( btnOKClicked() ) ) ; + + button = new QPushButton( this ) ; + button->setText( "Cancel" ) ; + button->setFixedSize( 60, 25 ) ; + button->move( 200, 90 ) ; + connect( button, SIGNAL( clicked() ), this, SLOT( btnCancelClicked() ) ) ; + + button = new QPushButton( this ) ; + button->setText( "..." ) ; + button->setFixedSize( 25, 20 ) ; + button->move( 270, 10 ) ; + connect( button, SIGNAL( clicked() ), this, SLOT( showFileDialog() ) ) ; + + button = new QPushButton( this ) ; + button->setText( "..." ) ; + button->setFixedSize( 25, 20 ) ; + button->move( 270, 35 ) ; + connect( button, SIGNAL( clicked() ), this, SLOT( showDirDialog() ) ) ; + + setFixedSize( 340, 130 ) ; + setCaption( "Export to VHDL" ) ; + m_bCanceled = true ; +} + +KExportDialog::~KExportDialog() +{ +} + +void KExportDialog::modal() +{ + exec() ; +} + +void KExportDialog::showFileDialog() +{ + KFileDialog dlg( QString::null, "*.vhd|vhdl template file", this, "template dlg", true ) ; + dlg.exec() ; + + if ( dlg.selectedFile() != "" ) + m_lineTemplateFile->setText( dlg.selectedFile() ) ; +} + +void KExportDialog::showDirDialog() +{ + QString dir = KFileDialog::getExistingDirectory ( QString::null, this, "Export directory" ) ; + if ( dir != "" ) + m_lineOutputDir->setText( dir ) ; +} + +void KExportDialog::btnOKClicked() +{ + m_templateFile = m_lineTemplateFile->text() ; + m_outputDir = m_lineOutputDir->text() ; + m_entityName = m_lineEntityName->text() ; + m_bCanceled = false ; + close() ; +} + +void KExportDialog::btnCancelClicked() +{ + m_outputDir = "" ; + m_templateFile = "" ; + m_entityName = "" ; + + close() ; +} + +void KExportDialog::setTemplateFile( QString file ) +{ + m_lineTemplateFile->setText( file ) ; +} + +void KExportDialog::setOutputDir( QString dir ) +{ + m_lineOutputDir->setText( dir ) ; +} + +void KExportDialog::setEntityName( QString name ) +{ + m_lineEntityName->setText( name ) ; +} + +QString KExportDialog::getTemplateFile() +{ + return m_templateFile ; +} + +QString KExportDialog::getOutputDir() +{ + return m_outputDir ; +} + +QString KExportDialog::getEntityName() +{ + return m_entityName ; +} + + +#include "kexportdialog.moc" diff --git a/src/kexportdialog.h b/src/kexportdialog.h new file mode 100755 index 0000000..2069ae8 --- /dev/null +++ b/src/kexportdialog.h @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef KEXPORTDIALOG_H +#define KEXPORTDIALOG_H + +#include <qobject.h> +#include <klineedit.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qstring.h> +#include <qdialog.h> + +class KExportDialog : public QDialog +{ + Q_OBJECT + public: + KExportDialog(QWidget *parent = 0, const char *name = 0 ); + ~KExportDialog(); + + void setOutputDir( QString dir ) ; + void setTemplateFile( QString file ) ; + void setEntityName( QString name ) ; + + QString getTemplateFile() ; + QString getOutputDir() ; + QString getEntityName() ; + + void modal() ; + + bool isCanceled() { return m_bCanceled ; } + protected: + QString m_outputDir ; + QString m_templateFile ; + QString m_entityName ; + + KLineEdit * m_lineTemplateFile, * m_lineOutputDir, *m_lineEntityName ; + bool m_bCanceled ; + + public slots: + void btnOKClicked() ; + void btnCancelClicked() ; + void showFileDialog() ; + void showDirDialog() ; +}; + +#endif diff --git a/src/kjtagdialog.cpp b/src/kjtagdialog.cpp new file mode 100644 index 0000000..a8d445e --- /dev/null +++ b/src/kjtagdialog.cpp @@ -0,0 +1,117 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "kjtagdialog.h" +#include <qmessagebox.h> +#include <kfiledialog.h> +#include <kiconloader.h> + +KJTAGDialog::KJTAGDialog( QWidget *parent ) + : QDialog( parent ) +{ + + setFixedSize( 330, 300 ) ; + m_groupConfigure = new QGroupBox( "Configure", this ) ; + m_groupConfigure->setFixedSize( 310, 45 ) ; + m_groupConfigure->move( 10, 10 ) ; + + m_selectFileBtn = new QPushButton( m_groupConfigure ) ; + m_selectFileBtn->setFixedSize( 30, 25 ) ; + m_selectFileBtn->move( 205, 15 ) ; + m_selectFileBtn->setPixmap( KGlobal::iconLoader()->loadIcon( "fileopen", KIcon::Small ) ) ; + connect( m_selectFileBtn, SIGNAL( clicked() ), this, SLOT( selectFileName() ) ) ; + + m_configureBtn = new QPushButton( "Configure", m_groupConfigure ) ; + m_configureBtn->setFixedSize( 60, 25 ) ; + m_configureBtn->move( 240, 15 ) ; + + connect( m_configureBtn, SIGNAL( clicked() ), this, SLOT( configure() ) ) ; + + m_bitFileLabel = new QLabel( "Bit file", m_groupConfigure ) ; + m_bitFileLabel->setFixedSize( 50, 25 ) ; + m_bitFileLabel->move( 10, 15 ) ; + + m_bitFileEdit = new KLineEdit( m_groupConfigure ) ; + m_bitFileEdit->setFixedSize( 150, 25 ) ; + m_bitFileEdit->move( 50, 15 ) ; + + m_progress = new KProgress( this ) ; + m_progress->setFixedSize( width(), 20 ) ; + m_progress->move( 0, 280 ) ; + m_progress->setTotalSteps( 100 ) ; + + m_debug = new KTextEdit( this ) ; + m_debug->setFixedSize( 310, 200 ) ; + m_debug->move( 10, 60 ) ; + + m_programmer = new JTAGProgrammer( this ) ; + connect( m_programmer, SIGNAL( progress(int) ), this, SLOT( progress(int) ) ) ; + connect( m_programmer, SIGNAL( message(const char*) ), this, SLOT( addMessage(const char*) ) ) ; + + m_debug->insert( "This option is still very experimental!!\n" + "The code is tested with the Spartan-3 Development Board.\n" + "Assuming the following setup:\n" + " TDI--->[XC3SXXX]--->[XCF]--->TDO\n" + "========================================================\n" ) ; +} + +KJTAGDialog::~KJTAGDialog() +{ + delete m_programmer ; +} + +void KJTAGDialog::configure() +{ + m_debug->clear() ; + m_programmer->setBitFile( m_bitFileEdit->text() ) ; + m_programmer->program() ; + m_progress->setProgress( 0 ) ; +} + +void KJTAGDialog::progress( int percent ) +{ + m_progress->setProgress( percent ) ; +} + +void KJTAGDialog::setFilename( QString filename ) +{ + m_bitFileEdit->setText( filename ) ; +} + +QString KJTAGDialog::getFilename() +{ + return m_bitFileEdit->text() ; +} + +void KJTAGDialog::selectFileName() +{ + QString filename = KFileDialog::getOpenFileName( QString::null, + "*.bit|bit files\n*|All files", + this, + "Select configuration file" ) ; + if ( filename != "" ) + m_bitFileEdit->setText( filename ) ; +} + +void KJTAGDialog::addMessage( const char *msg ) +{ + m_debug->insert( msg ) ; +} + + diff --git a/src/kjtagdialog.h b/src/kjtagdialog.h new file mode 100644 index 0000000..7bc25a5 --- /dev/null +++ b/src/kjtagdialog.h @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef KJTAGDIALOG_H +#define KJTAGDIALOG_H + +#include <qdialog.h> +#include <qpushbutton.h> +#include <klineedit.h> +#include <kprogress.h> +#include <qlabel.h> +#include <qgroupbox.h> +#include <ktextedit.h> + +#include "jtagprogrammer.h" + + + + +class KJTAGDialog : public QDialog +{ + Q_OBJECT + public: + KJTAGDialog(QWidget *parent); + ~KJTAGDialog(); + + void setFilename( QString filename ) ; + QString getFilename() ; + + public slots: + void configure() ; + void progress( int progress ) ; + void selectFileName() ; + void addMessage( const char *msg ) ; + + protected: + QPushButton *m_configureBtn, *m_selectFileBtn ; + KLineEdit *m_bitFileEdit ; + KProgress *m_progress ; + QLabel *m_bitFileLabel ; + QGroupBox *m_groupConfigure ; + KTextEdit *m_debug ; + + JTAGProgrammer *m_programmer ; +}; + +#endif diff --git a/src/kpicosim.cpp b/src/kpicosim.cpp new file mode 100755 index 0000000..cf3eb13 --- /dev/null +++ b/src/kpicosim.cpp @@ -0,0 +1,631 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +/* Revision History + * V0.1: - Initial Version + * V0.2: + * ADDED + * - Improved debugging. Added Execution and Breakpoint icons in border. + * - Show more compiler messages. + * - Improved Syntax Highlighting (Now automatically installed). + * - Improved the assembler. (Code is still a mess!) + * - Added icons. + * - Installation of the .desktop file is now in 'Development' + * V0.3: + * ADDED + * - Export to HEX and MEM files + * V0.4: + * ADDED + * - Expanded the debug toolbar. + * V0.5: + * BUG FIX + * - Assembler: 'ORR sX, sY' assembled to 'ORR sX, kk' where kk was undefined + * - Simulator: SUBCY sX, sY simulated wrongly (undefined behaviour) + * SUBCY sX, kk simulated wrongly (undefined behaviour) + * IMPROVED + * - Change port ID per port and in serial window. + * ADDED + * - Save/Restore settings. + * - Clear serial view popupmenu + * + * V0.6: + * ADDED + * - Debian packaging support by "Adrian Knoth" + * - Initial JTAG support + * - Initial Help + * + * IDEAS (Oct 9, 2005) + * - Multiple picoblaze support + * - IO ports (and irq) can be changed from other software. + * - Download mem file with JTAG + */ + + +#include "kpicosim.h" + +#include <qlabel.h> + +#include <kmainwindow.h> +#include <klocale.h> + +#include <kmenubar.h> +#include <qlayout.h> +#include <qkeysequence.h> +#include <knuminput.h> +#include <qnamespace.h> +#include <kportview.h> +#include <qdockwindow.h> +#include <kstatusbar.h> +#include <kiconloader.h> +#include "kexportdialog.h" +#include "kjtagdialog.h" +#include <kfiledialog.h> +#include <kmessagebox.h> +#include <qlayout.h> +#include <ksimpleconfig.h> +#include <khelpmenu.h> +#include <kaboutdata.h> + +const char version[] = "0.6" ; + +enum IDs { + START_SIM_ID = 0, + COMPILE_ID, + RUN_ID, + NEXT_ID, + INTERRUPT_ID, + RESET_ID, + + VIEW_SERIAL_ID, + VIEW_SCRATCHPAD_ID +} ; + + +KPicoSim::KPicoSim() : KMainWindow( 0, "KPicoSim" ) +{ +// set the shell's ui resource file +// setXMLFile("kpicosimui.rc"); + + m_splitter = new QSplitter( this ) ; + m_tabWidget = new QTabWidget( m_splitter ) ; + m_editor = new CodeEditor( m_tabWidget ) ; + m_messages = new KListView( m_splitter, "messages" ) ; + m_simulator = new KSimulator( this ) ; + m_processorView = new KProcessorView( this ) ; + + m_tabWidget->addTab( m_editor, "Source" ) ; + addDockWindow( m_processorView, DockLeft ) ; + + m_splitter->setOrientation( QSplitter::Vertical ) ; + setCentralWidget( m_splitter ) ; + m_messages->setAllColumnsShowFocus( true ) ; + m_messages->setFullWidth( true ) ; + m_messages->resize( m_messages->width(), m_splitter->height() / 5 ) ; + + buildMenu() ; + + KToolBar *toolbar = new KToolBar( this ) ; + addDockWindow( toolbar ) ; + + toolbar->insertButton( "filenew", -1, SIGNAL( clicked() ), m_editor, SLOT( slotNewFile() ), true, "New" ) ; + toolbar->insertButton( "fileopen", -1, SIGNAL( clicked() ), m_editor, SLOT( slotOpen() ), true, "Open" ) ; + toolbar->insertButton( "filesave", -1, SIGNAL( clicked() ), m_editor, SLOT( slotSave() ), true, "Save" ) ; + toolbar->insertButton( "filesaveas", -1, SIGNAL( clicked() ), m_editor, SLOT( slotSaveAs() ), true, "Save As" ) ; + + m_debugBar = new KToolBar( this ) ; + addDockWindow( m_debugBar ) ; + m_debugBar->insertButton( UserIcon( "rebuild" ), COMPILE_ID, SIGNAL( clicked() ), this, SLOT( compile() ), true, "Compile" ) ; + m_debugBar->insertButton( "run", START_SIM_ID, SIGNAL( clicked() ), this, SLOT( startSim() ), true, "Start/Stop Debug" ) ; + m_debugBar->insertSeparator() ; + m_debugBar->insertButton( UserIcon( "continue" ), RUN_ID, SIGNAL( clicked() ), this, SLOT( startStop() ), false, "Continue" ) ; + + m_debugBar->insertButton( UserIcon( "next" ), NEXT_ID, SIGNAL( clicked() ), m_simulator, SLOT( next() ), false, "Next" ) ; + m_debugBar->insertButton( UserIcon( "interrupt" ), INTERRUPT_ID, SIGNAL( clicked() ), m_simulator, SLOT( interrupt() ), false, "Interrupt" ) ; + m_debugBar->insertButton( UserIcon( "reset" ), RESET_ID, SIGNAL( clicked() ), m_simulator, SLOT( reset() ), false, "Reset" ) ; + + connect( this, SIGNAL( run() ), m_simulator, SLOT( run() ) ); + connect( this, SIGNAL( stop() ), m_simulator, SLOT( stop() ) ) ; + connect( m_simulator, SIGNAL( stepped( unsigned int ) ), this, SLOT( stepped( unsigned int ) ) ) ; + connect( m_processorView, SIGNAL( processorRegsChanged() ), this, SLOT( updateProcessorRegs() ) ) ; + connect( m_processorView, SIGNAL( processorFlagsChanged() ), this, SLOT( updateProcessorFlags() ) ) ; + connect( m_messages, SIGNAL( clicked( QListViewItem * ) ), this, SLOT( messageListClicked( QListViewItem * ) ) ) ; + + m_messages->addColumn( "Line" ) ; + m_messages->addColumn( "Description" ) ; + m_messages->setSorting( -1, FALSE ) ; + m_simulator->setMessageList( m_messages ) ; + + m_simulationMode = false ; + m_scratchpadView = NULL ; + m_serialView = NULL ; + + statusBar()->insertItem( QString( "Mode: Edit" ), 0 ) ; + statusBar()->insertItem( QString( "Status: Stopped" ), 1 ) ; + statusBar()->insertItem( QString( "Instructions: 0" ), 2 ) ; + + m_templateFile = "" ; + m_outputDir = "" ; + m_entityName = "mpu_rom" ; + + + openGUI() ; +} + + +void KPicoSim::buildMenu() +{ + KIconLoader * ldr = KGlobal::iconLoader() ; + + KPopupMenu * exportMenu = new KPopupMenu( this ) ; + + exportMenu->insertItem( "VHDL", this, SLOT( fileExportVHDL() ) ) ; +// exportMenu->insertItem( "COE", this, SLOT( fileExportCOE() ) ) ; + exportMenu->insertItem( "MEM", this, SLOT( fileExportMEM() ) ) ; + exportMenu->insertItem( "HEX", this, SLOT( fileExportHEX() ) ) ; + + m_fileMenu = new KPopupMenu( this ) ; + m_fileMenu->insertItem( ldr->loadIcon( "filenew", KIcon::Small ), "New", this, SLOT( slotFileNew() ) ) ; + m_fileMenu->insertItem( ldr->loadIcon( "fileopen", KIcon::Small ), "Open", m_editor, SLOT( slotOpen() ) ) ; + m_fileMenu->insertSeparator() ; + m_fileMenu->insertItem( ldr->loadIcon( "filesave", KIcon::Small ), "Save", m_editor, SLOT( slotSave() ), QKeySequence::QKeySequence( "CTRL+S" ) ) ; + m_fileMenu->insertItem( ldr->loadIcon( "filesaveas", KIcon::Small ), "Save As...", m_editor, SLOT( slotSaveAs() ) ) ; + m_fileMenu->insertSeparator() ; + m_fileMenu->insertItem( ldr->loadIcon( "fileprint", KIcon::Small ), "Print...", m_editor, SLOT( slotPrint() ), QKeySequence::QKeySequence( "CTRL+P" ) ) ; + m_fileMenu->insertSeparator() ; + m_fileMenu->insertItem( "Export", exportMenu ) ; + m_fileMenu->insertSeparator() ; + m_fileMenu->insertItem( ldr->loadIcon( "fileclose", KIcon::Small ), "Quit", this, SLOT( slotClose() ) ) ; + + m_editMenu = new KPopupMenu( this ) ; + m_editMenu->insertItem( ldr->loadIcon( "undo", KIcon::Small ), "Undo", m_editor, SLOT( slotUndo() ),QKeySequence::QKeySequence( "CTRL+Z" ) ) ; + m_editMenu->insertItem( ldr->loadIcon( "redo", KIcon::Small ), "Redo", m_editor, SLOT( slotRedo() ),QKeySequence::QKeySequence( "CTRL+SHIFT+Z" ) ) ; + m_editMenu->insertSeparator() ; + m_editMenu->insertItem( "Select All", m_editor, SLOT( slotSelectAll() ),QKeySequence::QKeySequence( "CTRL+A" ) ) ; + m_editMenu->insertSeparator() ; + m_editMenu->insertItem( ldr->loadIcon( "editcut", KIcon::Small ), "Cut", m_editor, SLOT( slotCut() ),QKeySequence::QKeySequence( "CTRL+X" ) ) ; + m_editMenu->insertItem( ldr->loadIcon( "editcopy", KIcon::Small ), "Copy", m_editor, SLOT( slotCopy() ),QKeySequence::QKeySequence( "CTRL+C" ) ) ; + m_editMenu->insertItem( ldr->loadIcon( "editpaste", KIcon::Small ), "Paste", m_editor, SLOT( slotPaste() ),QKeySequence::QKeySequence( "CTRL+V" ) ) ; + m_editMenu->insertSeparator() ; + m_editMenu->insertItem( ldr->loadIcon( "find", KIcon::Small ), "Find...", m_editor, SLOT( slotFind() ), QKeySequence::QKeySequence( "CTRL+F" ) ) ; + m_editMenu->insertItem( "Find Next", m_editor, SLOT( slotFindNext() ), QKeySequence::QKeySequence( "F3" ) ) ; + + + m_debugMenu = new KPopupMenu( this ) ; + m_debugMenu->insertSeparator() ; + m_debugMenu->insertItem( ldr->loadIcon( "rebuild", KIcon::Small ), "Compile", this, SLOT( compile() ), QKeySequence::QKeySequence( "SHIFT+F9" ) ) ; + m_debugMenu->insertItem( ldr->loadIcon( "run", KIcon::Small ), "Start Debug", this, SLOT( startSim() ), QKeySequence::QKeySequence( "F9" ) , START_SIM_ID ) ; + + m_debugMenu->insertSeparator() ; + m_debugMenu->insertItem( "Continue", this, SLOT( startStop() ), QKeySequence::QKeySequence( "F10" ) , RUN_ID ) ; + m_debugMenu->insertItem( "Next", m_simulator, SLOT( next() ), QKeySequence::QKeySequence( "F5" ) , NEXT_ID ) ; + m_debugMenu->insertItem( "Interrupt", m_simulator, SLOT( interrupt() ), QKeySequence::QKeySequence( "F4" ) , INTERRUPT_ID ) ; + m_debugMenu->insertItem( "Reset", m_simulator, SLOT( reset() ), QKeySequence::QKeySequence( "F11" ) , RESET_ID ) ; + + m_debugMenu->insertSeparator() ; + m_debugMenu->insertItem( "Toggle Breakpoint", m_editor, SLOT( slotToggleBreakpoint() ), QKeySequence::QKeySequence( "F8" ) ) ; + + m_settingsMenu = new KPopupMenu( this ) ; + m_settingsMenu->insertItem( "Configure Editor...", m_editor, SLOT( slotShowConfig() ) ) ; + + m_peripheralMenu = new KPopupMenu( this ) ; + m_peripheralMenu->insertItem( "I/O Port", this, SLOT( newIOPort() ) ) ; + m_peripheralMenu->insertItem( "Scratchpad", this, SLOT( showScratchpad() ), 0, VIEW_SCRATCHPAD_ID ) ; + m_peripheralMenu->insertItem( "Serial port", this, SLOT( showSerialPort() ), 0, VIEW_SERIAL_ID ) ; + + m_jtagMenu = new KPopupMenu( this ) ; + m_jtagMenu->insertItem( "Download", this, SLOT( jtagDownload() ) ) ; + + KAboutData *aboutData = new KAboutData( + "kpicosim", + "kpicosim", + version, + "IDE for the picoblaze\n\nCopyright (c) 2005 Mark Six", + KAboutData::License_GPL, + 0, + 0, + "http://www.xs4all.nl/~marksix", + "m6@xs4all.nl" + ) ; + aboutData->addAuthor( "Mark Six", "m6@xs4all.nl", "http://www.xs4all.nl/~marksix" ) ; + + KHelpMenu *helpMenu = new KHelpMenu( this, aboutData, false ) ; + KPopupMenu *help = helpMenu->menu() ; + + menuBar()->insertItem( "File", m_fileMenu ) ; + menuBar()->insertItem( "Edit", m_editMenu ) ; + menuBar()->insertItem( "Debug", m_debugMenu ) ; + menuBar()->insertItem( "Peripheral", m_peripheralMenu ) ; + menuBar()->insertItem( "JTAG", m_jtagMenu ) ; + menuBar()->insertItem( "Settings", m_settingsMenu ) ; + menuBar()->insertItem( "Help", help ) ; + + m_debugMenu->setItemEnabled( RUN_ID, false ) ; + m_debugMenu->setItemEnabled( NEXT_ID, false ) ; + m_debugMenu->setItemEnabled( INTERRUPT_ID, false ) ; + m_debugMenu->setItemEnabled( RESET_ID, false ) ; + + m_peripheralMenu->setCheckable( true ); + m_peripheralMenu->setItemChecked( VIEW_SERIAL_ID, false ) ; + m_peripheralMenu->setItemChecked( VIEW_SCRATCHPAD_ID, false ) ; + + + menuBar()->show() ; +} + +void KPicoSim::jtagDownload() +{ + /* JTAG is still in its infancy. This code works for me. I'm using the Xilinx Spartan-3 + * development board. If it works for you, great, if not too bad... + */ + + KJTAGDialog dlg( this ) ; + dlg.setFilename( m_bitfile ) ; + dlg.exec() ; + m_bitfile = dlg.getFilename() ; +} + +void KPicoSim::fileExportCOE() +{ + KMessageBox::information( this, "This function is not supported yet", "Export COE" ) ; + +// if ( compile() ) { + //m_simulator->exportCOE() ; +// } +} + +void KPicoSim::fileExportHEX() +{ + + QString filename = KFileDialog::getSaveFileName( QString::null, + "*.hex|HEX files\n*|All files", + this, + "Export HEX" ) ; + if ( filename != "" && compile() ) { + m_simulator->exportHEX( filename, FALSE ) ; + } +} + +void KPicoSim::fileExportMEM() +{ + + QString filename = KFileDialog::getSaveFileName( QString::null, + "*.mem|MEM files\n*|All files", + this, + "Export MEM" ) ; + if ( filename != "" && compile() ) { + m_simulator->exportHEX( filename, TRUE ) ; + } +} + +void KPicoSim::fileExportVHDL() +{ + KExportDialog dlg( this ) ; + + dlg.setTemplateFile( m_templateFile ) ; + dlg.setOutputDir( m_outputDir ) ; + dlg.setEntityName( m_entityName ) ; + dlg.modal() ; + + if ( dlg.isCanceled() ) + return ; + + m_templateFile = dlg.getTemplateFile() ; + m_outputDir = dlg.getOutputDir() ; + m_entityName = dlg.getEntityName() ; + + if ( compile() && m_simulator->exportVHDL( m_templateFile, m_outputDir, m_entityName ) ) { + appendMessage( "File '" + m_outputDir + "/" + m_entityName + ".vhd' exported" ) ; + appendMessage( "Template file '" + m_templateFile + "' used" ) ; + appendMessage( "***Export Success***" ) ; + } else { + appendMessage( "***Export failed***" ) ; + } +} + +void KPicoSim::slotFileNew() +{ + if ( m_editor->close() ) + m_editor->slotNewFile() ; +} + +void KPicoSim::slotClose() +{ + close() ; +} + +void KPicoSim::closeEvent( QCloseEvent * e ) +{ + if ( m_editor->close() ) + e->accept() ; + + + // Save filename last opened + // Save windows IO Ports, peripherals et al. + closeGUI() ; +} + +void KPicoSim::newIOPort() +{ + KPortView * ioport = new KPortView( m_simulator->getCpu(), 0 ) ; /* port id is 0 */ +// m_ioList.append( ioport ) ; + addDockWindow( ioport, DockRight ) ; +// connect( ioport, SIGNAL( closing( KPortView* ) ), this, SLOT( removeIOPort( KPortView* ) ) ) ; +} + +void KPicoSim::showSerialPort() +{ + if ( m_serialView == NULL ) { + m_serialView = new KSerialView( m_simulator->getCpu(), m_tabWidget ) ; + m_tabWidget->addTab( m_serialView, "Serial" ) ; + m_peripheralMenu->setItemChecked( VIEW_SERIAL_ID, true ) ; + } else { + m_peripheralMenu->setItemChecked( VIEW_SERIAL_ID, false ) ; + delete m_serialView ; + m_serialView = NULL ; + } +} + +void KPicoSim::showScratchpad() +{ + if ( m_scratchpadView == NULL ) { + m_scratchpadView = new KScratchpadView( this ) ; + updateScratchpadView() ; + addDockWindow( m_scratchpadView, DockRight ) ; + m_peripheralMenu->setItemChecked( VIEW_SCRATCHPAD_ID, true ) ; + } else { + m_peripheralMenu->setItemChecked( VIEW_SCRATCHPAD_ID, false ) ; + delete m_scratchpadView ; + m_scratchpadView = NULL ; + } +} + +KPicoSim::~KPicoSim() +{ + // Delete dockwindows + // These are the IO ports, scratchpad and the processorview + dockWindows().setAutoDelete( true ) ; + dockWindows().clear() ; + + if ( m_serialView ) + delete m_serialView ; + + delete m_simulator ; + + delete m_debugMenu ; + delete m_editMenu ; + delete m_peripheralMenu ; + delete m_fileMenu ; + delete m_settingsMenu ; +} + +void KPicoSim::startStop() +{ + if ( m_simulationMode ) { + + if ( !m_simulator->isRunning() ) { + m_debugMenu->changeItem( RUN_ID, "Stop" ) ; + m_editor->clearExecutionMarker() ; + m_simulator->run() ; + statusBar()->changeItem( QString( "Status: Running" ), 1 ) ; + m_debugBar->setButton( RUN_ID, true ) ; + } else { + m_simulator->stop() ; + updateViews() ; + m_debugMenu->changeItem( RUN_ID, "Continue" ) ; + m_editor->setExecutionMarker( m_simulator->getNextSourceLine() ) ; + statusBar()->changeItem( QString( "Status: Stopped" ), 1 ) ; + QString str ; + str.sprintf( "Instructions: %u", m_nrInstructions ) ; + statusBar()->changeItem( str, 2 ) ; + m_debugBar->setButton( RUN_ID, false ) ; + } + } +} + +void KPicoSim::messageListClicked( QListViewItem *item ) +{ + if ( item ) { + bool ok ; + int line = item->text(0).toInt( &ok, 10 ) ; + + if ( ok ) + m_editor->setCursor( line - 1 ) ; // C-programmers do it from zero + } +} + +void KPicoSim::updateProcessorRegs() +{ + unsigned char regValues[ 16 ] ; + m_processorView->getRegisterValues( regValues ) ; + m_simulator->setRegisterValues( regValues ) ; +} + +void KPicoSim::updateProcessorFlags() +{ + m_simulator->setFlags( m_processorView->getFlags() ) ; +} + +void KPicoSim::updateViews() +{ + unsigned char regValues[ 16 ] ; + m_simulator->getRegisterValues( regValues ) ; + m_processorView->setRegisterValues( regValues ) ; + m_processorView->setFlags( m_simulator->getFlags() ) ; + + updateScratchpadView() ; + + QString str ; + str.sprintf( "Instructions: %u", m_nrInstructions ) ; + statusBar()->changeItem( str, 2 ) ; +} + +void KPicoSim::updateScratchpadView() +{ + if ( m_scratchpadView != NULL ) { + unsigned char sp_ram[ 64 ] ; + m_simulator->getScratchpad( sp_ram ) ; + m_scratchpadView->setContent( sp_ram, sizeof( sp_ram ) ) ; + } +} + +void KPicoSim::stepped( unsigned int line ) +{ + m_nrInstructions++ ; + if ( m_simulator->isRunning() ) { + if ( m_editor->isBreakpoint( line ) ) { ; + startStop() ; + m_editor->setExecutionMarker( line ) ; + } else if ( (m_nrInstructions % 100 ) == 0 ) { + updateViews() ; + } + } else { + m_editor->setExecutionMarker( line ) ; + updateViews() ; + } +} + +void KPicoSim::appendMessage( QString str ) +{ + QListViewItem *item = new QListViewItem( m_messages, m_messages->lastChild() ) ; + item->setText( 0, "" ) ; + item->setText( 1, str ) ; + +} + +bool KPicoSim::compile() +{ + m_simulator->clear() ; + m_messages->clear() ; + + if ( !m_editor->save() ) + return FALSE; + + appendMessage( "File '" + m_editor->getFilename() + "' saved" ) ; + m_simulator->setFilename( m_editor->getFilename() ) ; + + if ( m_simulator->compile() == TRUE ) { + appendMessage( "***Compile Success*** " ) ; + return TRUE ; + } else { + appendMessage( "***Compile Failed*** " ) ; + return FALSE ; + } +} + + +void KPicoSim::startSim() +{ + KIconLoader * ldr = KGlobal::iconLoader() ; + + if ( !m_simulationMode ) { + if ( compile() ) { + setCaption( m_editor->getFilename() + " [Debugging]" ) ; + m_debugMenu->changeItem( START_SIM_ID, ldr->loadIcon( "stop", KIcon::Small ), "Stop Debug" ) ; + m_debugBar->setButton( START_SIM_ID, true ) ; + + m_simulator->reset() ; + m_nrInstructions = 0 ; + m_simulationMode = TRUE ; + } + } else { + if ( m_simulator->isRunning() ) + startStop() ; + + setCaption( m_editor->getFilename() ) ; + m_debugMenu->changeItem( START_SIM_ID, ldr->loadIcon( "run", KIcon::Small ), "Start Debug" ) ; + m_debugBar->setButton( START_SIM_ID, false ) ; + m_editor->clearExecutionMarker() ; + m_simulationMode = FALSE ; + } + + if ( m_simulationMode ) { + statusBar()->changeItem( QString( "Mode: Debug" ), 0 ) ; + } else { + statusBar()->changeItem( QString( "Mode: Edit" ), 0 ) ; + } + + m_debugMenu->setItemEnabled( RUN_ID, m_simulationMode ) ; + m_debugMenu->setItemEnabled( NEXT_ID, m_simulationMode ) ; + m_debugMenu->setItemEnabled( INTERRUPT_ID, m_simulationMode ) ; + m_debugMenu->setItemEnabled( RESET_ID, m_simulationMode ) ; + + m_debugBar->setItemEnabled( RUN_ID, m_simulationMode ) ; + m_debugBar->setItemEnabled( NEXT_ID, m_simulationMode ) ; + m_debugBar->setItemEnabled( INTERRUPT_ID, m_simulationMode ) ; + m_debugBar->setItemEnabled( RESET_ID, m_simulationMode ) ; + +} +/* +void KPicoSim::removeIOPort( KPortView* ioport ) +{ + m_ioList.removeRef( ioport ) ; +} +*/ +void KPicoSim::closeGUI() +{ + KSimpleConfig config( "kpicosim" ) ; + + config.setGroup( "Peripherals" ) ; + + config.writeEntry( "serial", m_serialView != NULL ) ; + config.writeEntry( "scratchpad", m_scratchpadView != NULL ) ; + config.writeEntry( "filename", m_editor->getFilename() ) ; + config.writeEntry( "bitfile", m_bitfile ) ; + +/* + config.writeEntry( "numIOPorts", m_ioList.count() ) ; + for ( int i = 0 ; i < m_ioList.count() ; i++ ) { + QString group ; + group.sprintf( "IO Port %d", i ) ; + m_ioList.at(i)->writeConfig( config, group ) ; + } +*/ +} + +void KPicoSim::openGUI() +{ + KSimpleConfig config( "kpicosim" ) ; + + config.setGroup( "Peripherals" ) ; + + if ( config.readPropertyEntry( "serial", QVariant::Bool ).toBool() ) + showSerialPort() ; + if ( config.readPropertyEntry( "scratchpad", QVariant::Bool ).toBool() ) + showScratchpad() ; + m_editor->open( config.readEntry( "filename" ) ) ; + m_bitfile = config.readEntry( "bitfile" ) ; + +/* + int nports = config.readPropertyEntry( "numIOPorts", QVariant::Int ).toInt() ; + + for ( int i = 0 ; i < nports ; i++ ) { + QString group ; + group.sprintf( "IO Port %d", i ) ; + KPortView * ioport = new KPortView( m_simulator->getCpu(), 0 ) ; + ioport->readConfig( config, group ) ; + m_ioList.append( ioport ) ; + addDockWindow( ioport, DockRight ) ; + connect( ioport, SIGNAL( closing( KPortView* ) ), this, SLOT( removeIOPort( KPortView* ) ) ) ; + } +*/ +} + +#include "kpicosim.moc" diff --git a/src/kpicosim.desktop b/src/kpicosim.desktop new file mode 100755 index 0000000..0547660 --- /dev/null +++ b/src/kpicosim.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=KPicosim +Exec=kpicosim +Icon=kpicosim +Type=Application +Comment=PicoBlaze IDE +Comment[nl]=PicoBlaze Ontwikkelomgeving diff --git a/src/kpicosim.h b/src/kpicosim.h new file mode 100755 index 0000000..5ed9893 --- /dev/null +++ b/src/kpicosim.h @@ -0,0 +1,119 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +#ifndef _KPICOSIM_H_ +#define _KPICOSIM_H_ + +#include "codeeditor.h" +#include "ksimulator.h" + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <kmainwindow.h> +#include <klistview.h> +#include <qsplitter.h> +#include <kpopupmenu.h> +#include <ktoolbar.h> +#include <qtabwidget.h> +#include "kprocessorview.h" +#include "kserialview.h" +#include "kscratchpadview.h" +#include "kportview.h" + +class KPicoSim : public KMainWindow +{ + Q_OBJECT + public: + KPicoSim(); + virtual ~KPicoSim(); + + protected: + CodeEditor * m_editor ; + KListView * m_messages ; + QSplitter * m_splitter ; + KProcessorView * m_processorView ; + KSerialView *m_serialView ; + KScratchpadView *m_scratchpadView ; + QTabWidget *m_tabWidget ; + + KPopupMenu * m_fileMenu, * m_debugMenu, * m_settingsMenu, * m_editMenu, * m_peripheralMenu, *m_jtagMenu, *m_helpMenu ; + + KSimulator * m_simulator ; + + // Export to VHDL + QString m_templateFile, m_outputDir, m_entityName ; + + bool m_simulationMode ; + unsigned int m_nrInstructions ; + + void appendMessage( QString str ) ; + void updateViews() ; + void updateScratchpadView() ; + + virtual void closeEvent( QCloseEvent *e ) ; + + void buildMenu() ; + + void openGUI() ; + void closeGUI() ; + +// QPtrList<KPortView> m_ioList ; + QString m_bitfile ; + + QPixmap m_runPxp, m_stopPxp ; + KToolBar *m_debugBar ; + + signals: + void run() ; + void stop() ; + + public slots: + void startSim() ; + void startStop() ; + void stepped( unsigned int line ) ; + void messageListClicked( QListViewItem * item ) ; + + void updateProcessorRegs() ; + void updateProcessorFlags() ; + + void newIOPort() ; + void showSerialPort() ; + void showScratchpad() ; + void slotClose() ; + + /* The export functions */ + void fileExportVHDL() ; + void fileExportCOE() ; + void fileExportMEM() ; + void fileExportHEX() ; + + bool compile() ; + void slotFileNew() ; + +// void removeIOPort( KPortView* ioport ) ; + + /* JTAG */ + void jtagDownload() ; +}; + +#endif // _KPICOSIM_H_ diff --git a/src/kpicosimconfig.h b/src/kpicosimconfig.h new file mode 100755 index 0000000..13b9d6a --- /dev/null +++ b/src/kpicosimconfig.h @@ -0,0 +1,37 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef KPICOSIMCONFIG_H +#define KPICOSIMCONFIG_H + +#include <kconfigskeleton.h> + +/** +@author Mark Six +*/ +class kpicosimconfig : public KConfigSkeleton +{ +public: + kpicosimconfig(); + + ~kpicosimconfig(); + +}; + +#endif diff --git a/src/kpicosimui.rc b/src/kpicosimui.rc new file mode 100755 index 0000000..39df4cb --- /dev/null +++ b/src/kpicosimui.rc @@ -0,0 +1,8 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui name="kpicosim" version="1"> +<MenuBar> + <Menu name="custom"><text>C&ustom</text> + <Action name="custom_action" /> + </Menu> +</MenuBar> +</kpartgui> diff --git a/src/kport.cpp b/src/kport.cpp new file mode 100755 index 0000000..d158cfd --- /dev/null +++ b/src/kport.cpp @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "kport.h" + +unsigned char KPort::In() { // Called by Picoblaze + emit read() ; + return m_readValue ; +} + +void KPort::Out( unsigned char value ) { // Called by Picoblaze + m_writeValue = value ; + emit write( value ) ; +} + +unsigned char KPort::getWriteValue() { + return m_writeValue ; +} + +unsigned char KPort::getReadValue() { + return m_readValue ; +} + +void KPort::setWriteValue( uint8_t value ) { + m_writeValue = value ; +} + +void KPort::setReadValue( uint8_t value ) { + m_readValue = value ; +} + + diff --git a/src/kport.h b/src/kport.h new file mode 100755 index 0000000..6038826 --- /dev/null +++ b/src/kport.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef KPORT_H +#define KPORT_H + +#include <qobject.h> +#include "cpicoblaze.h" + +class KPort : public QObject, public CIOPort +{ + Q_OBJECT + public: + KPort( unsigned char portID ) : CIOPort( portID ) {} + virtual ~KPort() {} ; + + unsigned char In() ; // Called by Picoblaze + void Out( unsigned char value ) ; // Called by Picoblaze + + unsigned char getWriteValue() ; + unsigned char getReadValue() ; + + void setWriteValue( uint8_t value ) ; + void setReadValue( uint8_t value ) ; + + signals: + void write( unsigned char value ) ; + void read() ; + + private: + unsigned char m_readValue, m_writeValue ; +} ; + + +#endif diff --git a/src/kportview.cpp b/src/kportview.cpp new file mode 100755 index 0000000..7bf410e --- /dev/null +++ b/src/kportview.cpp @@ -0,0 +1,185 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "kportview.h" +#include <qlayout.h> +#include <qlabel.h> + +KPortView::KPortView( CPicoBlaze *cpu, QWidget *parent, const char *name) + : KToolBar(parent, name) +{ + m_cpu = cpu ; + + QWidget *widget = new QWidget( this ) ; + widget->setMinimumSize( 200, 65 ) ; + + QLabel *label = new QLabel( "ID", widget ) ; + label->move( 3, 0 ) ; + + label = new QLabel( "b7", widget ) ; + label->move( 32, 0 ) ; + + label = new QLabel( "b0", widget ) ; + label->move( 137, 0 ) ; + + label = new QLabel( "I", widget ) ; + label->move( 160, 0 ) ; + + label = new QLabel( "O", widget ) ; + label->move( 175, 0 ) ; + + m_editID = new KLineEdit( widget ) ; + m_editID->setText( "0" ) ; + m_editID->setFixedSize( 30, 20 ) ; + m_editID->move( 2, 22 ); + connect( m_editID, SIGNAL( textChanged( const QString &) ), this, SLOT( setID( const QString &) ) ) ; + + int i ; + for ( i = 0 ; i < 8 ; i++ ) { + m_bits[ i ] = new QCheckBox( widget ) ; + m_bits[ i ]->move( 35 + i * 15, 22 ) ; + } + + m_readable = new QCheckBox( widget ) ; + m_readable->move( 160, 22 ) ; + + m_writeable = new QCheckBox( widget ) ; + m_writeable->move( 175, 22 ) ; + + m_port = new KPort( 0 ) ; + m_cpu->addPort( m_port ) ; + + connect( m_port, SIGNAL( read() ), this, SLOT( read() ) ) ; + connect( m_port, SIGNAL( write(unsigned char) ), this, SLOT( write(unsigned char) ) ) ; + connect( m_readable, SIGNAL( toggled(bool) ), this, SLOT( readableToggled(bool) ) ) ; + connect( m_writeable, SIGNAL( toggled(bool) ), this, SLOT( writeableToggled(bool) ) ) ; + + setWidget( widget ) ; + setCloseMode( Always ) ; + + m_writeable->setChecked( true ) ; + writeableToggled( true ) ; + m_readable->setChecked( true ) ; + readableToggled( true ) ; + + setResizeEnabled( true ) ; + + m_backgroundColor = m_editID->backgroundColor() ; +} + +KPortView::~KPortView() +{ + m_cpu->deletePort( m_port ) ; +} +/* +void KPortView::closeEvent ( QCloseEvent * e ) +{ + emit closing( this ) ; +} +*/ +void KPortView::setID( const QString &newID ) +{ + QString str ; + bool ok ; + int id ; + + id = newID.toInt( &ok ) ; + + if ( ok && id >= 0 && id <= 255 ) { + m_port->setID( id ) ; // change it back to the old id + m_editID->setText( newID ) ; + m_editID->setBackgroundColor( m_backgroundColor ) ; + } else { + m_editID->setBackgroundColor( QColor( 255, 128, 128 ) ) ; + } + + + /*else { + str.sprintf( "%d", m_port->getID() ) ; + m_editID->setText( str ) ; + }*/ +} + +QString KPortView::id() +{ + return m_editID->text() ; +} + +void KPortView::read() +{ + unsigned char value = 0 ; + int i ; + + for ( i = 0 ; i < 8 ; i++ ) + if ( m_bits[ i ]->isChecked() ) + value |= ( 0x80 >> i ) ; + + m_port->setReadValue( value ) ; +} + +void KPortView::write( unsigned char value ) +{ + int i; + for ( i = 0 ; i < 8 ; i++ ) + if ( value & ( 0x80 >> i ) ) + m_bits[ i ]->setChecked( true ) ; + else + m_bits[ i ]->setChecked( false ) ; +} + +void KPortView::readableToggled( bool on ) +{ + int mode = m_port->getMode() ; + if ( on ) mode |= PortReadable ; + else mode &= ~PortReadable ; + m_port->setMode( mode ) ; +} + +void KPortView::writeableToggled( bool on ) +{ + int mode = m_port->getMode() ; + if ( on ) mode |= PortWriteable ; + else mode &= ~PortWriteable ; + m_port->setMode( mode ) ; +} + +void KPortView::readConfig( KSimpleConfig &config, QString group ) +{ + config.setGroup( group ) ; + + int mode = config.readPropertyEntry( "Mode", QVariant::Int ).toInt() ; + m_port->setMode( mode ) ; + m_readable->setChecked( (mode & PortReadable) != 0 ) ; + m_writeable->setChecked( (mode & PortWriteable ) != 0 ) ; + + QString id = config.readEntry( "Id" ) ; + setID( id ) ; +} + +void KPortView::writeConfig( KSimpleConfig &config, QString group ) +{ + config.setGroup( group ) ; + + config.writeEntry( "Mode", m_port->getMode() ) ; + config.writeEntry( "Id", m_port->getID() ) ; +} + + + +#include "kportview.moc" diff --git a/src/kportview.h b/src/kportview.h new file mode 100755 index 0000000..b4f2f0c --- /dev/null +++ b/src/kportview.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef KPORTVIEW_H +#define KPORTVIEW_H + +#include <ktoolbar.h> +#include <qcheckbox.h> +#include <klineedit.h> +#include "kport.h" +#include <ksimpleconfig.h> + +class KPortView : public KToolBar +{ + Q_OBJECT + public: + KPortView( CPicoBlaze *cpu, QWidget *parent = 0, const char *name = 0); + ~KPortView(); + + KPort * m_port ; + + public slots: + void read() ; + void write( unsigned char value ) ; + + void writeableToggled( bool on ) ; + void readableToggled( bool on ) ; + + void setID( const QString & newID ) ; + QString id() ; + + void readConfig( KSimpleConfig &config, QString group ) ; + void writeConfig( KSimpleConfig &config, QString group ) ; + + signals: +// void closing( KPortView *ioport ) ; + + protected: +// virtual void closeEvent ( QCloseEvent * e ) ; + + QCheckBox * m_bits[ 8 ], * m_readable, * m_writeable ; + KLineEdit * m_editID ; + + CPicoBlaze * m_cpu ; + + QColor m_backgroundColor ; + +}; + +#endif diff --git a/src/kprocessorview.cpp b/src/kprocessorview.cpp new file mode 100755 index 0000000..f54469a --- /dev/null +++ b/src/kprocessorview.cpp @@ -0,0 +1,208 @@ +#include "kprocessorview.h" + +#include <qlabel.h> +#include <qlayout.h> +#include <qscrollview.h> +#include <qsize.h> +#include <qmessagebox.h> +#include <qpopupmenu.h> +#include <qcursor.h> + +MyListView::MyListView(QWidget *parent) : KListView(parent) +{ + connect( this, SIGNAL( contextMenu( KListView *, QListViewItem *, const QPoint & ) ), + SLOT( slotContextMenu( KListView *, QListViewItem *, const QPoint & ) ) ); +} + +MyListView::~MyListView() +{ +} + +void MyListView::slotContextMenu( KListView *, QListViewItem *, const QPoint & ) +{ +// mousePressEvent( NULL ) ; + emit showPopupMenu() ; +} +/* +void MyListView::mousePressEvent( QMouseEvent * event ) +{ + //QMessageBox::information( this, "information", "mouse pressed" ) ; + +// if ( event->button() == RightButton ) + emit showPopupMenu() ; +// else +// KListView::mousePressEvent( event ) ; +} +*/ + +KProcessorView::KProcessorView(QWidget *parent, const char *name) + : KToolBar(parent) +{ + name = name ; // avoid compiler warning + + view = new MyListView( this ) ; + + connect( view, SIGNAL( itemRenamed( QListViewItem*) ), this, SLOT( slotItemRenamed(QListViewItem*) ) ) ; + connect( view, SIGNAL( showPopupMenu() ), this, SLOT( showPopupMenu() ) ) ; + + view->addColumn( "Register" ) ; + view->addColumn( "Value" ) ; + view->setRootIsDecorated( true ) ; + view->setRenameable( 1, true ) ; // Column 1 is renameable + view->setRenameable( 0, false ) ; // Column 1 is renameable + view->setItemsRenameable( true ) ; + setWidget( view ) ; + setResizeEnabled( true ) ; + + int i ; + char str[ 128 ] ; + + QListViewItem *cpu = new QListViewItem( view ) ; + cpu->setText( 0, "CPU" ) ; + + QListViewItem *flags = new QListViewItem( cpu ) ; + flags->setText( 0, "Flags" ) ; + + zeroFlag = new QListViewItem( flags ) ; + zeroFlag->setText( 0, "Zero" ) ; + zeroFlag->setText( 1, "0" ) ; + + carryFlag = new QListViewItem( flags ) ; + carryFlag->setText( 0, "Carry" ) ; + carryFlag->setText( 1, "0" ) ; + + ieFlag = new QListViewItem( flags ) ; + ieFlag->setText( 0, "IE" ) ; + ieFlag->setText( 1, "0" ) ; + + QListViewItem *reg = new QListViewItem( cpu ) ; + reg->setText( 0, "Registers" ) ; + + for ( i = 0 ; i < 16 ; i++ ) { + regs[ i ] = new QListViewItem( reg ) ; + sprintf( str, "s%X", i ) ; + regs[ i ]->setText( 0, str ) ; + regs[ i ]->setText( 1, "0" ) ; + } + + view->setOpen( cpu, true ) ; + view->setOpen( flags, true ) ; + view->setOpen( reg, true ) ; + + m_bHexMode = false ; +} + +void KProcessorView::slotHexMode() +{ + unsigned char regs[ 16 ] ; + + getRegisterValues(regs) ; + m_bHexMode = !m_bHexMode ; + setRegisterValues(regs) ; +} + +void KProcessorView::showPopupMenu() +{ + QPopupMenu *menu = new QPopupMenu( this ) ; + menu->insertItem( "Hexadecimal", this, SLOT( slotHexMode() ), 0, 1 ) ; + menu->setItemChecked( 1, m_bHexMode ) ; + menu->exec( QCursor::pos() ); +} + +void KProcessorView::slotItemRenamed( QListViewItem * item ) +{ + int i, value, base ; + bool ok ; + + if ( m_bHexMode ) base = 16 ; + else base = 10 ; + + if ( !item ) + return ; + + for ( i = 0 ; i < 16 ; i++ ) { + if ( item == regs[ i ] ) { + value = item->text(1).toInt( &ok, base ) ; + + if ( !ok || value < 0 || value > 255 ) { + QMessageBox::warning( parentWidget(), "Modify register", "Value should be between 0-255" ) ; + view->rename( item, 1 ) ; + } else { + emit processorRegsChanged() ; + } + return ; + } + } + + if ( zeroFlag == item || carryFlag == item || ieFlag == item ) { + value = item->text(1).toInt( &ok ) ; + if ( !ok || value < 0 || value > 1 ) { + QMessageBox::warning( parentWidget(), "Modify flag", "Value should be between 0-1" ) ; + } else + emit processorFlagsChanged() ; + } +} + +void KProcessorView::resizeEvent( QResizeEvent *event ) +{ + event = event ; +// view->resize( width() - 10, height() - 10 ) ; +} + +void KProcessorView::getRegisterValues( unsigned char *values ) +{ + int i, base ; + bool ok ; + + if ( m_bHexMode ) base = 16 ; + else base = 10 ; + + for ( i = 0 ; i < 16 ; i++ ) { + values[ i ] = regs[ i ]->text(1).toInt( &ok, base ) ; + } +} + +void KProcessorView::setRegisterValues( unsigned char *values ) +{ + int i, base ; + + if ( m_bHexMode ) base = 16 ; + else base = 10 ; + + QString str; + for ( i = 0 ; i < 16 ; i++ ) { + str.setNum( values[ i ], base ) ; + regs[ i ]->setText( 1, str ) ; + } +} + +void KProcessorView::setFlags( unsigned char flags ) +{ + if ( flags & 0x01 ) zeroFlag->setText( 1, "1" ) ; + else zeroFlag->setText( 1, "0" ) ; + + if ( flags & 0x02 ) carryFlag->setText( 1, "1" ) ; + else carryFlag->setText( 1, "0" ) ; + + if ( flags & 0x04 ) ieFlag->setText( 1, "1" ) ; + else ieFlag->setText( 1, "0" ) ; +} + +unsigned char KProcessorView::getFlags() +{ + unsigned char flags = 0 ; + + if ( zeroFlag->text(1).toInt() == 1 ) flags |= 0x01 ; + if ( carryFlag->text(1).toInt() == 1 ) flags |= 0x02 ; + if ( ieFlag->text(1).toInt() == 1 ) flags |= 0x04 ; + + return flags ; +} + +KProcessorView::~KProcessorView() +{ + delete view ; +} + + + diff --git a/src/kprocessorview.h b/src/kprocessorview.h new file mode 100755 index 0000000..ae4b6fc --- /dev/null +++ b/src/kprocessorview.h @@ -0,0 +1,61 @@ +#ifndef KPROCESSORVIEW_H +#define KPROCESSORVIEW_H + + +#include <ktoolbar.h> +#include <knuminput.h> +#include <qcheckbox.h> +#include <klistview.h> + +class MyListView : public KListView +{ + Q_OBJECT + public: + MyListView(QWidget *parent) ; + ~MyListView() ; + + protected: +// virtual void mousePressEvent( QMouseEvent *event ) ; + + + public slots: + void slotContextMenu( KListView *, QListViewItem *, const QPoint & ) ; + + signals: + void showPopupMenu() ; +} ; + + +class KProcessorView : public KToolBar +{ + Q_OBJECT + public: + KProcessorView(QWidget *parent = 0, const char *name = 0); + ~KProcessorView(); + + void setRegisterValues( unsigned char *values ) ; + void getRegisterValues( unsigned char *values ) ; + + void setFlags( unsigned char flags ); + unsigned char getFlags() ; + + public slots: + void slotItemRenamed( QListViewItem * item ) ; + void slotHexMode() ; + void showPopupMenu() ; + + signals: + void processorRegsChanged() ; + void processorFlagsChanged() ; + + private: + virtual void resizeEvent( QResizeEvent *event ) ; + + protected: + MyListView *view ; + QListViewItem * regs[ 16 ] ; + QListViewItem * zeroFlag, * carryFlag, * ieFlag ; + bool m_bHexMode ; +}; + +#endif diff --git a/src/kscratchpadview.cpp b/src/kscratchpadview.cpp new file mode 100755 index 0000000..fffe989 --- /dev/null +++ b/src/kscratchpadview.cpp @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "kscratchpadview.h" + +KScratchpadView::KScratchpadView( QWidget *parent, const char *name) + : KToolBar(parent, name) +{ + view = new KTextEdit( this ) ; + view->setFont( QFont( "Courier", view->font().pointSize() ) ) ; + view->setReadOnly( true ) ; + + setWidget( view ) ; + setResizeEnabled( true ) ; +} + +KScratchpadView::~KScratchpadView() +{ + delete view ; +} + +void KScratchpadView::setContent( unsigned char *values, unsigned int len ) +{ + unsigned int i, val ; + + QString text, str ; + + text = "Scratchpad" ; + for ( i = 0 ; i < len ; i++ ) { + if ( (i % 8) == 0 ) { // Show address + str.sprintf( "\n%02X:", i ) ; + text += str ; + } + val = values[ i ] ; + str.sprintf( " %02X", val ) ; // values + text += str ; + } + + view->setText( text ) ; +} + + +#include "kscratchpadview.moc" diff --git a/src/kscratchpadview.h b/src/kscratchpadview.h new file mode 100755 index 0000000..eebc00c --- /dev/null +++ b/src/kscratchpadview.h @@ -0,0 +1,39 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef KSCRATCHPADVIEW_H +#define KSCRATCHPADVIEW_H + +#include <ktoolbar.h> +#include <ktextedit.h> + +class KScratchpadView : public KToolBar +{ + Q_OBJECT + public: + KScratchpadView(QWidget *parent = 0, const char *name = 0); + ~KScratchpadView(); + + void setContent( unsigned char *values, unsigned int len ) ; + + protected: + KTextEdit * view ; +}; + +#endif diff --git a/src/kserialview.cpp b/src/kserialview.cpp new file mode 100755 index 0000000..6ce0457 --- /dev/null +++ b/src/kserialview.cpp @@ -0,0 +1,321 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "kserialview.h" +#include <qlabel.h> +#include <qlayout.h> +#include <qgroupbox.h> +#include <qframe.h> + +KSerialView::KSerialView( CPicoBlaze *cpu, QWidget * parent ) : QWidget( parent ) +{ + m_cpu = cpu ; + + txPort = new KPort( 1 ) ; + txPort->setMode( PortWriteable ) ; + + rxPort = new KPort( 1 ) ; + rxPort->setMode( PortReadable ) ; + + statusPort = new KPort( 0 ) ; + statusPort->setMode( PortReadable ) ; + + view = new KSerialWindow( this ) ; + QWidget *settings = new QWidget( this ) ; + settings->setMinimumSize( 90, 90 ) ; + + QVBoxLayout *layout = new QVBoxLayout( this ) ; + layout->addWidget( view ) ; + layout->addWidget( settings ) ; + + QGroupBox *groupBox = new QGroupBox( "Serial Settings", settings ) ; + groupBox->setFixedSize( 200, 80 ) ; + groupBox->move( 10, 0 ) ; + + QLabel *label = new QLabel( groupBox ) ; + label->setText( "Transmit" ) ; + label->move( 5, 15 ) ; + label->setFixedSize( 55, 18 ) ; + + label = new QLabel( groupBox ) ; + label->setText( "Receive" ) ; + label->move( 5, 35 ) ; + label->setFixedSize( 55, 18 ) ; + + label = new QLabel( groupBox ) ; + label->setText( "Status" ) ; + label->move( 5, 55 ) ; + label->setFixedSize( 55, 18 ) ; + + txPortID = new KLineEdit( groupBox ) ; + txPortID->move( 65, 15 ) ; + txPortID->setFixedSize( 40, 18 ) ; + txPortID->setText( "1" ) ; + + rxPortID = new KLineEdit( groupBox ) ; + rxPortID->move( 65, 35 ) ; + rxPortID->setText( "1" ) ; + rxPortID->setFixedSize( 40, 18 ) ; + + statusPortID = new KLineEdit( groupBox ); + statusPortID->move( 65, 55 ) ; + statusPortID->setText( "0" ) ; + statusPortID->setFixedSize( 40, 18 ) ; + + statusPort->setReadValue( 0 ) ; // Buffers are empty, nothing received. + connect( txPort, SIGNAL( write( unsigned char ) ), this, SLOT( transmit( unsigned char ) ) ) ; + connect( rxPort, SIGNAL( read() ), this, SLOT( receive() ) ) ; + connect( view, SIGNAL( keyPressed( int ) ), this, SLOT( keyPressed( int ) ) ) ; + + connect( txPortID, SIGNAL( textChanged( const QString & ) ), this, SLOT( updateTxId( const QString & ) ) ) ; + connect( rxPortID, SIGNAL( textChanged( const QString & ) ), this, SLOT( updateRxId( const QString & ) ) ) ; + connect( statusPortID, SIGNAL( textChanged( const QString & ) ), this, SLOT( updateStatusId( const QString & ) ) ) ; + + groupBox = new QGroupBox( "Status Register", settings ) ; + groupBox->setFixedSize( 200, 80 ) ; + groupBox->move( 250, 0 ) ; + + label = new QLabel( groupBox ) ; + label->setText( "RX" ) ; + label->move( 106, 15 ) ; + label->setFixedSize( 20, 20 ) ; + + label = new QLabel( groupBox ) ; + label->setText( "TX" ) ; + label->move( 168, 15 ) ; + label->setFixedSize( 20, 20 ) ; + + label = new QLabel( groupBox ) ; + label->setText( "DR" ) ; + label->move( 80, 30 ) ; + label->setFixedSize( 20, 20 ) ; + + label = new QLabel( groupBox ) ; + label->setText( "F" ) ; + label->move( 110, 30 ) ; + label->setFixedSize( 20, 20 ) ; + + label = new QLabel( groupBox ) ; + label->setText( "HF" ) ; + label->move( 130, 30 ) ; + label->setFixedSize( 20, 20 ) ; + + label = new QLabel( groupBox ) ; + label->setText( "F" ) ; + label->move( 160, 30 ) ; + label->setFixedSize( 20, 20 ) ; + + label = new QLabel( groupBox ) ; + label->setText( "HF" ) ; + label->move( 179, 30 ) ; + label->setFixedSize( 20, 20 ) ; + + int i ; + for ( i = 0 ; i < 8 ; i++ ) { + m_statusBits[ i ] = new QCheckBox( groupBox ) ; + m_statusBits[ i ]->move( 5 + i * 25, 50 ) ; + m_statusBits[ i ]->setFixedSize( 15, 20 ) ; + } + + for ( i = 0 ; i < 6 ; i++ ) { + m_statusBits[ i ]->setEnabled( false ) ; + } + + QFrame *frame = new QFrame( groupBox ) ; + frame->setFrameRect( QRect( 0, 0, 1, 50 ) ) ; + frame->setFrameShape( QFrame::VLine ) ; + frame->move( 73, 20 ) ; + frame->setFixedSize( 1, 50 ) ; + + frame = new QFrame( groupBox ) ; + frame->setFrameRect( QRect( 0, 0, 1, 50 ) ) ; + frame->setFrameShape( QFrame::VLine ) ; + frame->move( 149, 20 ) ; + frame->setFixedSize( 1, 50 ) ; + + connect( m_statusBits[ 6 ], SIGNAL( toggled( bool ) ), this, SLOT( txFlagsChanged( bool ) ) ) ; + connect( m_statusBits[ 7 ], SIGNAL( toggled( bool ) ), this, SLOT( txFlagsChanged( bool ) ) ) ; + + fifoPtr = 0 ; + + m_cpu->addPort( txPort ) ; + m_cpu->addPort( rxPort ) ; + m_cpu->addPort( statusPort ) ; + + m_backgroundColor = rxPortID->backgroundColor() ; +} + + +KSerialView::~KSerialView() +{ + m_cpu->deletePort( txPort ) ; + m_cpu->deletePort( rxPort ) ; + m_cpu->deletePort( statusPort ) ; + + delete txPort ; + delete rxPort ; + delete statusPort ; + delete view ; +} + +void KSerialView::updateTxId( const QString & str ) +{ + bool ok ; + int val ; + QString s ; + + val = str.toInt( &ok ) ; + if ( ok && val >= 0 && val <= 255 ) { + txPortID->setBackgroundColor( m_backgroundColor ) ; + txPort->setID( val ) ; + } else { + txPortID->setBackgroundColor( QColor( 255, 128, 128 ) ) ; + } + + + /*else { + s.sprintf( "%u", txPort->getID() ) ; + txPortID->setText( s ) ; + } + */ +} + +void KSerialView::updateRxId( const QString & str ) +{ + bool ok ; + int val ; + QString s ; + + val = str.toInt( &ok ) ; + if ( ok && val >= 0 && val <= 255 ) { + rxPortID->setBackgroundColor( m_backgroundColor ) ; + rxPort->setID( val ) ; + } else { + rxPortID->setBackgroundColor( QColor( 255, 128, 128 ) ) ; + } + + /*else { + s.sprintf( "%u", rxPort->getID() ) ; + rxPortID->setText( s ) ; + } + */ +} + +void KSerialView::updateStatusId( const QString & str ) +{ + bool ok ; + int val ; + QString s ; + + val = str.toInt( &ok ) ; + if ( ok && val >= 0 && val <= 255 ) { + statusPort->setID( val ) ; + statusPortID->setBackgroundColor( m_backgroundColor ) ; + } else { + statusPortID->setBackgroundColor( QColor( 255, 128, 128 ) ) ; + } + /*else { + s.sprintf( "%u", statusPort->getID() ) ; + statusPortID->setText( s ) ; + } +*/ +} + +void KSerialView::transmit( unsigned char b ) +{ + if ( b == '\r' ) + b = '\n' ; + + if ( b == 0x08 ) { // Backspace + view->doKeyboardAction( QTextEdit::ActionBackspace ) ; + } else { + QString str ; + view->insert( (str+=b) ) ; + } +} + +unsigned char KSerialView::getReceiveFlags() +{ + unsigned char flags = 0 ; + if ( fifoPtr != 0 ) flags |= 0x10 ; // Receive + else flags &= ~0x10 ; + + if ( fifoPtr > 7 ) flags |= 0x04 ; // Halffull Marker + else flags &= ~0x04 ; + + if ( fifoPtr == 15 ) flags |= 0x08 ; // Full Marker + else flags &= ~0x08 ; + + return flags ; +} + +unsigned char KSerialView::getTransmitFlags() +{ + unsigned char flags = 0 ; + if ( m_statusBits[ 6 ]->isChecked() ) + flags |= 0x02 ; + if ( m_statusBits[ 7 ]->isChecked() ) + flags |= 0x01 ; + + return flags ; +} + +void KSerialView::receive() +{ + int i ; + + if ( fifoPtr == 0 ) { // Fifo empty + statusPort->setReadValue( 0x00 ) ; + return ; + } + + rxPort->setReadValue( rxFifo[ 0 ] ) ; + for ( i = 1 ; i < 16 ; i++ ) + rxFifo[ i - 1 ] = rxFifo[ i ] ; + fifoPtr -= 1 ; + + statusPort->setReadValue( getReceiveFlags() | getTransmitFlags() ) ; + setStatusBits( getReceiveFlags() ) ; +} + +void KSerialView::keyPressed( int key ) +{ + if ( key == '\n' || key == 0 ) + return ; + + rxFifo[ fifoPtr ] = key ; + if ( fifoPtr != 15 ) + fifoPtr += 1 ; + + statusPort->setReadValue( getReceiveFlags() | getTransmitFlags() ) ; + setStatusBits( getReceiveFlags() ) ; +} + +void KSerialView::txFlagsChanged( bool en ) +{ + en = en ; + statusPort->setReadValue( getReceiveFlags() | getTransmitFlags() ) ; +} + +void KSerialView::setStatusBits( unsigned char value ) +{ + m_statusBits[ 3 ]->setChecked( (value & 0x10) != 0 ) ; + m_statusBits[ 4 ]->setChecked( (value & 0x08) != 0 ) ; + m_statusBits[ 5 ]->setChecked( (value & 0x04) != 0 ) ; +} diff --git a/src/kserialview.h b/src/kserialview.h new file mode 100755 index 0000000..1a21dbc --- /dev/null +++ b/src/kserialview.h @@ -0,0 +1,110 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef KSERIALVIEW_H +#define KSERIALVIEW_H + +#include <ktoolbar.h> +#include <ktextedit.h> +#include <klineedit.h> +#include <qcheckbox.h> +#include <qpushbutton.h> +#include <qfont.h> +#include <qpopupmenu.h> + +#include "kport.h" + +class KSerialWindow : public KTextEdit +{ + Q_OBJECT + + public: + KSerialWindow( QWidget *parent ) : KTextEdit( parent ) { + setWrapColumnOrWidth( 80 ) ; // Serial window is a terminal + setWrapPolicy( QTextEdit::Anywhere ) ; + setWordWrap( QTextEdit::FixedColumnWidth ) ; + setFont( KGlobalSettings::fixedFont() ) ; // Use default fixed font + } + virtual ~KSerialWindow() {} ; + + protected: + virtual void keyPressEvent( QKeyEvent *e ) + { + emit keyPressed( e->ascii() ) ; + } + + virtual void mousePressEvent( QMouseEvent *e ) { + } + virtual void mouseReleaseEvent( QMouseEvent *e ) {} + virtual QPopupMenu *createPopupMenu( const QPoint &pos ) + { + QPopupMenu *menu = new QPopupMenu( this ) ; + menu->insertItem( "clear view", this, SLOT( clearView() ) ) ; + return menu ; + } + public slots: + void clearView() { + clear() ; + } + + signals: + void keyPressed( int key ) ; + +} ; + +class KSerialView : public QWidget +{ + Q_OBJECT + public: + KSerialView( CPicoBlaze *cpu, QWidget *parent ); + ~KSerialView(); + + KPort * rxPort, * txPort, * statusPort ; + + public slots: + void transmit( unsigned char ) ; + void receive() ; + void keyPressed( int key ) ; + + protected: + KSerialWindow *view ; + + unsigned char rxFifo[ 16 ] ; + unsigned char fifoPtr ; + + unsigned char getReceiveFlags() ; + unsigned char getTransmitFlags() ; + void setStatusBits( unsigned char ) ; + + CPicoBlaze * m_cpu ; + + KLineEdit *txPortID, *rxPortID, *statusPortID ; + QCheckBox *m_statusBits[ 8 ] ; + + QColor m_backgroundColor ; + QPushButton *m_clearButton ; + + public slots: + void updateTxId( const QString & ) ; + void updateRxId( const QString & ) ; + void updateStatusId( const QString & ) ; + void txFlagsChanged( bool en ) ; +}; + +#endif diff --git a/src/ksimulator.cpp b/src/ksimulator.cpp new file mode 100755 index 0000000..57b2f43 --- /dev/null +++ b/src/ksimulator.cpp @@ -0,0 +1,151 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include "ksimulator.h" + +KSimulator::KSimulator(QObject *parent, const char *name ) + : QObject(parent, name) +{ + m_picoBlaze = new CPicoBlaze() ; + m_assembler = new CAssembler() ; + + m_assembler->setCode( m_picoBlaze->code ) ; + m_timer = new QTimer( this ) ; + m_bInterrupt = FALSE ; + + m_timer->stop() ; + m_run = false ; + connect( m_timer, SIGNAL( timeout() ), this, SLOT( next() ) ) ; +} + +KSimulator::~KSimulator() +{ + + delete m_picoBlaze ; + delete m_assembler ; +} + +void KSimulator::setMessageList( KListView *messageList ) +{ + m_assembler->setMessageList( messageList ) ; +} + +void KSimulator::reset() +{ + m_picoBlaze->Reset() ; + emit stepped( m_picoBlaze->GetNextSourceLine() ) ; +} + +void KSimulator::clear() +{ + m_picoBlaze->code->ClearCode() ; + m_assembler->clear() ; +} + +void KSimulator::interrupt() +{ + m_bInterrupt = TRUE ; +} + +unsigned int KSimulator::getNextSourceLine() +{ + return m_picoBlaze->GetNextSourceLine() ; +} + +void KSimulator::next() +{ + if ( m_bInterrupt ) { + m_bInterrupt = FALSE ; + m_picoBlaze->Interrupt() ; + } else + m_picoBlaze->Next() ; + emit stepped( m_picoBlaze->GetNextSourceLine() ) ; +} + +CPicoBlaze * KSimulator::getCpu() +{ + return m_picoBlaze ; +} + +unsigned char KSimulator::getFlags() +{ + unsigned char flags = 0 ; + + if ( m_picoBlaze->flags.carry ) + flags |= CARRY_FLAG ; + if ( m_picoBlaze->flags.zero ) + flags |= ZERO_FLAG ; + if ( m_picoBlaze->flags.interrupt_enable ) + flags |= INTERRUPT_FLAG ; + + return flags ; +} + +void KSimulator::setFlags( unsigned char flags ) +{ + m_picoBlaze->flags.carry = flags & CARRY_FLAG ? TRUE : FALSE ; + m_picoBlaze->flags.zero = flags & ZERO_FLAG ? TRUE : FALSE ; + m_picoBlaze->flags.interrupt_enable = flags & INTERRUPT_FLAG ? TRUE : FALSE ; +} + +void KSimulator::run() +{ + m_timer->start( 1 ) ; + m_run = true ; +} + +void KSimulator::stop() +{ + m_timer->stop() ; + m_run = false ; +} + +bool KSimulator::isRunning() +{ + return m_run ; +} + +void KSimulator::getRegisterValues( unsigned char *values ) +{ + int i ; + + for ( i = 0 ; i < 16 ; i++ ) { + values[ i ] = m_picoBlaze->s[ i ] ; + } + +} + +void KSimulator::setRegisterValues( unsigned char *values ) +{ + int i ; + + for ( i = 0 ; i < 16 ; i++ ) { + m_picoBlaze->s[ i ] = values[ i ] ; + } +} + +void KSimulator::getScratchpad( unsigned char * values ) +{ + int i ; + + for ( i = 0 ; i < SCRATCHPAD_SIZE ; i++ ) + values[ i ] = m_picoBlaze->scratch->Get( i ) ; +} + +#include "ksimulator.moc" diff --git a/src/ksimulator.h b/src/ksimulator.h new file mode 100755 index 0000000..f54f5be --- /dev/null +++ b/src/ksimulator.h @@ -0,0 +1,91 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef KSIMULATOR_H +#define KSIMULATOR_H + +#include <qobject.h> +#include "cpicoblaze.h" +#include "cassembler.h" + +#include <string> +#include <qtimer.h> +#include <klistview.h> + +#include "kprocessorview.h" + +#define ZERO_FLAG 0x01 +#define CARRY_FLAG 0x02 +#define INTERRUPT_FLAG 0x04 + +class KSimulator : public QObject +{ + Q_OBJECT + public: + KSimulator(QObject *parent = 0, const char *name = 0); + ~KSimulator(); + + void setFilename( string filename ) { m_assembler->setFilename( filename ) ; } + bool compile() { return m_assembler->assemble() ; } + bool exportVHDL( string templateFile, string outputDir, string entityName ) + { + return m_assembler->exportVHDL( templateFile, outputDir, entityName ) ; + } + + bool exportHEX( string filename, bool mem ) + { + return m_assembler->exportHEX( filename, mem ) ; + } + + void setRegisterValues( unsigned char *values ) ; + void getRegisterValues( unsigned char *values ) ; + unsigned char getFlags() ; + void setFlags( unsigned char flags ) ; + void getScratchpad( unsigned char * values ) ; + + unsigned int getNextSourceLine() ; + + void assemblerError( unsigned int line, const char * str ) ; + void setMessageList( KListView *messageList ) ; + + bool isRunning() ; + + CPicoBlaze * getCpu() ; + + signals: + void stepped( unsigned int currentSourceLine ) ; + + public slots: + void run() ; + void stop() ; + void next() ; + void interrupt() ; + void reset() ; + void clear() ; + + private: + CPicoBlaze * m_picoBlaze ; + CAssembler * m_assembler ; + QTimer * m_timer ; + bool m_bInterrupt ; + KListView *m_messageList ; + bool m_run ; +}; + +#endif diff --git a/src/main.cpp b/src/main.cpp new file mode 100755 index 0000000..2ab2fce --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,70 @@ +/*************************************************************************** + * Copyright (C) 2005 by Mark Six * + * marksix@xs4all.nl * + * * + * This program is free software; 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 2 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 * + * MERCHANTABILITY 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +#include "kpicosim.h" +#include <kapplication.h> +#include <kaboutdata.h> +#include <kcmdlineargs.h> +#include <klocale.h> + +static const char description[] = + I18N_NOOP("A KDE KPart Application"); + +static const char version[] = "0.1"; + +static KCmdLineOptions options[] = +{ +// { "+[URL]", I18N_NOOP( "Document to open" ), 0 }, + KCmdLineLastOption +}; + +int main(int argc, char **argv) +{ + KAboutData about("kpicosim", I18N_NOOP("KPicoSim"), version, description, + KAboutData::License_GPL, "(C) %{YEAR} Mark Six", 0, 0, "m6@xs4all.nl"); + about.addAuthor( "Mark Six", 0, "m6@xs4all.nl" ); + KCmdLineArgs::init(argc, argv, &about); + KCmdLineArgs::addCmdLineOptions( options ); + KApplication app; + KPicoSim *mainWin = 0; + + if (app.isRestored()) + { + RESTORE(KPicoSim); + } + else + { + // no session.. just start up normally + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + /// @todo do something with the command line args here + + mainWin = new KPicoSim(); + app.setMainWidget( mainWin ); + mainWin->show(); + + args->clear(); + } + + // mainWin has WDestructiveClose flag by default, so it will delete itself. + return app.exec(); +} + diff --git a/src/pics/Makefile.am b/src/pics/Makefile.am new file mode 100644 index 0000000..e726b97 --- /dev/null +++ b/src/pics/Makefile.am @@ -0,0 +1,5 @@ +INCLUDES = $(all_includes) +METASOURCES = AUTO +mypicsdir = $(kde_datadir)/kpicosim/pics + +mypics_DATA = continue.png interrupt.png next.png rebuild.png reset.png diff --git a/src/pics/continue.png b/src/pics/continue.png Binary files differnew file mode 100644 index 0000000..0d4232b --- /dev/null +++ b/src/pics/continue.png diff --git a/src/pics/interrupt.png b/src/pics/interrupt.png Binary files differnew file mode 100644 index 0000000..69dfb9e --- /dev/null +++ b/src/pics/interrupt.png diff --git a/src/pics/next.png b/src/pics/next.png Binary files differnew file mode 100644 index 0000000..561d70a --- /dev/null +++ b/src/pics/next.png diff --git a/src/pics/rebuild.png b/src/pics/rebuild.png Binary files differnew file mode 100644 index 0000000..bd3c870 --- /dev/null +++ b/src/pics/rebuild.png diff --git a/src/pics/reset.png b/src/pics/reset.png Binary files differnew file mode 100644 index 0000000..a8dad33 --- /dev/null +++ b/src/pics/reset.png diff --git a/src/psm.xml b/src/psm.xml new file mode 100644 index 0000000..83e4386 --- /dev/null +++ b/src/psm.xml @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE language SYSTEM "language.dtd"> +<!-- +This program, including associated files, is free software. You may +distribute it and/or modify it under the terms of the GNU General Public +License as published by the Free Software Foundation; either Version 2 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 MERCHANTABILITY +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; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +--> + +<language name="pblazeASM" version="1.02" kateversion="2.1" section="Assembler" extensions="*.psm" mimetype="text/x-psm" author="Mark Six" license="GPL"> + <highlighting> + <list name="instructions"> + <item> ADD </item> + <item> ADDCY </item> + <item> AND </item> + <item> CALL </item> + <item> COMPARE </item> + <item> FETCH </item> + <item> INPUT </item> + <item> JUMP </item> + <item> LOAD </item> + <item> OR </item> + <item> OUTPUT </item> + <item> RETURN </item> + <item> RETURNI </item> + <item> ROTATE </item> + <item> RL </item> + <item> RR </item> + <item> SL0 </item> + <item> SL1 </item> + <item> SLA </item> + <item> SLX </item> + <item> SR0 </item> + <item> SR1 </item> + <item> SRA </item> + <item> SRX </item> + <item> STORE </item> + <item> SUB </item> + <item> SUBCY </item> + <item> TEST </item> + <item> XOR </item> + <item> DISABLE </item> + <item> ENABLE </item> + </list> + + <list name="instruction_attr"> + <item> NZ </item> + <item> Z </item> + <item> C </item> + <item> NC </item> + <item> INTERRUPT </item> + <item> DISABLE </item> + <item> ENABLE </item> + <item> s0 </item> + <item> s1 </item> + <item> s2 </item> + <item> s3 </item> + <item> s4 </item> + <item> s5 </item> + <item> s6 </item> + <item> s7 </item> + <item> s8 </item> + <item> s9 </item> + <item> sA </item> + <item> sB </item> + <item> sC </item> + <item> sD </item> + <item> sE </item> + <item> sF </item> + </list> + + <list name="directives"> + <item> constant </item> + <item> namereg </item> + <item> address </item> + </list> + + + <contexts> + <!-- The main context --> + <context name="Normal" attribute="Normal Text" lineEndContext="#stay"> + <keyword attribute="Instructions" context="Opcode" String="instructions"/> + <keyword attribute="Directives" context="Opcode" String="directives"/> + <DetectChar attribute="Comment" context="Comment" char=";" /> + </context> + + <context name="Comment" attribute="Comment" lineEndContext="#pop" /> + + <context name="Opcode" attribute="Opcode" lineEndContext="#pop"> + <keyword attribute="InstructionAttr" context="#stay" String="instruction_attr"/> + <DetectChar attribute="Comment" context="Comment" char=";" /> + </context> + </contexts> + + <itemDatas> + <itemData name="Normal Text" defStyleNum="dsNormal"/> + <itemData name="Directives" defStyleNum="dsOthers"/> + <itemData name="Instructions" defStyleNum="dsKeyword"/> + <itemData name="InstructionAttr" defStyleNum="dsNormal" color="#000080" selColor="#000080" bold="0" italic="1"/> + <itemData name="Comment" defStyleNum="dsComment" /> + </itemDatas> + </highlighting> + + <general> + <comments> + <comment name="singleLine" start=";" /> + </comments> + <keywords casesensitive="0" weakDeliminator="_.$" /> + </general> +</language> diff --git a/src/types.h b/src/types.h new file mode 100755 index 0000000..f3d440c --- /dev/null +++ b/src/types.h @@ -0,0 +1,9 @@ + + +typedef unsigned char uint8_t ; +typedef unsigned short uint16_t ; +typedef unsigned int uint32_t ; + +#define TRUE 1 +#define FALSE 0 + |