URL
https://opencores.org/ocsvn/zipcpu/zipcpu/trunk
Subversion Repositories zipcpu
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 18 to Rev 19
- ↔ Reverse comparison
Rev 18 → Rev 19
/zipcpu/trunk/sw/zipdbg/zipdbg.cpp
0,0 → 1,300
/////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: zipdbg.cpp |
// |
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core |
// |
// Purpose: Provide a simple debugger for the Zip CPU. This allows you |
// to halt the CPU, examine the registers, and even single step |
// the CPU. It's not fully functional yet, as I would like to implement |
// breakpoints and the ability to modify registers, but it's a good |
// start. |
// |
// Commands while in the debugger are: |
// 'r' - RESET the CPU |
// 'g' - Go. Release the CPU and exit the debugger. |
// 'q' - Quit. Leave the debugger, while leaving the CPU halted. |
// 's' - Single Step. Allows the CPU to advance by one instruction. |
// |
// |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Tecnology, LLC |
// |
/////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
// by the Free Software Foundation, either version 3 of the License, or (at |
// your option) any later version. |
// |
// This program is distributed in the hope that it will be useful, but WITHOUT |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
/////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include <stdlib.h> |
#include <signal.h> |
#include <time.h> |
#include <unistd.h> |
|
#include <ctype.h> |
#include <ncurses.h> |
|
// #include "twoc.h" |
// #include "qspiflashsim.h" |
#include "zopcodes.h" |
#include "zparser.h" |
#include "devbus.h" |
#include "regdefs.h" |
// #include "port.h" |
|
// No particular "parameters" need definition or redefinition here. |
class ZIPPY : public DEVBUS { |
typedef DEVBUS::BUSW BUSW; |
DEVBUS *m_fpga; |
public: |
ZIPPY(DEVBUS *fpga) : m_fpga(fpga) {} |
|
void kill(void) { m_fpga->kill(); } |
void close(void) { m_fpga->close(); } |
void writeio(const BUSW a, const BUSW v) { m_fpga->writeio(a, v); } |
BUSW readio(const BUSW a) { return m_fpga->readio(a); } |
void readi(const BUSW a, const int len, BUSW *buf) { |
return m_fpga->readi(a, len, buf); } |
void readz(const BUSW a, const int len, BUSW *buf) { |
return m_fpga->readz(a, len, buf); } |
void writei(const BUSW a, const int len, const BUSW *buf) { |
return m_fpga->writei(a, len, buf); } |
void writez(const BUSW a, const int len, const BUSW *buf) { |
return m_fpga->writez(a, len, buf); } |
bool poll(void) { return m_fpga->poll(); } |
void usleep(unsigned ms) { m_fpga->usleep(ms); } |
void wait(void) { m_fpga->wait(); } |
bool bus_err(void) const { return m_fpga->bus_err(); } |
void reset_err(void) { m_fpga->reset_err(); } |
void clear(void) { m_fpga->clear(); } |
|
void reset(void) { writeio(R_ZIPCTRL, CPU_RESET|CPU_HALT); } |
void step(void) { writeio(R_ZIPCTRL, CPU_STEP); } |
void go(void) { writeio(R_ZIPCTRL, CPU_GO); } |
void halt(void) { writeio(R_ZIPCTRL, CPU_HALT); } |
bool stalled(void) { return ((readio(R_ZIPCTRL)&CPU_STALL)==0); } |
|
void showval(int y, int x, const char *lbl, unsigned int v) { |
mvprintw(y,x, "%s: 0x%08x", lbl, v); |
} |
|
void dispreg(int y, int x, const char *n, unsigned int v) { |
// 4,4,8,1 = 17 of 20, +3 = 19 |
mvprintw(y, x, "%s: 0x%08x", n, v); |
} |
|
void showins(int y, const char *lbl, |
const int gie, const unsigned int pc) { |
char line[80]; |
unsigned int v; |
|
mvprintw(y, 0, "%s: 0x%08x", lbl, pc); |
|
if (gie) attroff(A_BOLD); |
else attron(A_BOLD); |
|
line[0] = '\0'; |
try { |
v= readio(pc); |
zipi_to_string(v, line); |
printw(" 0x%08x", v); |
printw(" %-24s", &line[1]); |
} catch(BUSERR b) { |
printw(" 0x%08x %-24s", b.addr, "(Bus Error)"); |
} |
attroff(A_BOLD); |
} |
|
unsigned int cmd_read(unsigned int a) { |
writeio(R_ZIPCTRL, CPU_HALT|(a&0x3f)); |
while((readio(R_ZIPCTRL) & CPU_STALL) == 0) |
; |
return readio(R_ZIPDATA); |
} |
|
void read_state(void) { |
int ln= 0; |
bool gie; |
|
mvprintw(ln,0, "Peripherals"); |
mvprintw(ln,40, "CPU State: "); |
{ |
unsigned int v = readio(R_ZIPDATA); |
if (v & 0x010000) |
printw("EXT-INT "); |
if (v & 0x002000) |
printw("Supervisor Mod "); |
if (v & 0x001000) |
printw("Sleeping "); |
if (v & 0x008000) |
printw("Break-Enabled "); |
} |
ln++; |
showval(ln, 1, "PIC ", cmd_read(32+ 0)); |
showval(ln,21, "WDT ", cmd_read(32+ 1)); |
showval(ln,41, "CACH", cmd_read(32+ 2)); |
showval(ln,61, "PIC2", cmd_read(32+ 3)); |
ln++; |
showval(ln, 1, "TMRA", cmd_read(32+ 4)); |
showval(ln,21, "TMRB", cmd_read(32+ 5)); |
showval(ln,41, "TMRC", cmd_read(32+ 6)); |
showval(ln,61, "JIF ", cmd_read(32+ 7)); |
|
ln++; |
showval(ln, 1, "UTSK", cmd_read(32+12)); |
showval(ln,21, "UMST", cmd_read(32+13)); |
showval(ln,41, "UPST", cmd_read(32+14)); |
showval(ln,61, "UAST", cmd_read(32+15)); |
|
ln++; |
ln++; |
unsigned int cc = cmd_read(14); |
gie = (cc & 0x020); |
if (gie) |
attroff(A_BOLD); |
else |
attron(A_BOLD); |
mvprintw(ln, 0, "Supervisor Registers"); |
ln++; |
|
dispreg(ln, 1, "sR0 ", cmd_read(0)); |
dispreg(ln,21, "sR1 ", cmd_read(1)); |
dispreg(ln,41, "sR2 ", cmd_read(2)); |
dispreg(ln,61, "sR3 ", cmd_read(3)); ln++; |
|
dispreg(ln, 1, "sR4 ", cmd_read(4)); |
dispreg(ln,21, "sR5 ", cmd_read(5)); |
dispreg(ln,41, "sR6 ", cmd_read(6)); |
dispreg(ln,61, "sR7 ", cmd_read(7)); ln++; |
|
dispreg(ln, 1, "sR8 ", cmd_read( 8)); |
dispreg(ln,21, "sR9 ", cmd_read( 9)); |
dispreg(ln,41, "sR10", cmd_read(10)); |
dispreg(ln,61, "sR11", cmd_read(11)); ln++; |
|
dispreg(ln, 1, "sR12", cmd_read(12)); |
dispreg(ln,21, "sSP ", cmd_read(13)); |
|
mvprintw(ln,41, "sCC :%s%s%s%s%s%s%s", |
(cc & 0x040)?"STP":" ", |
(cc & 0x020)?"GIE":" ", |
(cc & 0x010)?"SLP":" ", |
(cc&8)?"V":" ", |
(cc&4)?"N":" ", |
(cc&2)?"C":" ", |
(cc&1)?"Z":" "); |
mvprintw(ln,61, "sPC : 0x%08x", cmd_read(15)); |
ln++; |
|
if (gie) |
attron(A_BOLD); |
else |
attroff(A_BOLD); |
mvprintw(ln, 0, "User Registers"); ln++; |
dispreg(ln, 1, "uR0 ", cmd_read(16)); |
dispreg(ln,21, "uR1 ", cmd_read(17)); |
dispreg(ln,41, "uR2 ", cmd_read(18)); |
dispreg(ln,61, "uR3 ", cmd_read(19)); ln++; |
|
dispreg(ln, 1, "uR4 ", cmd_read(20)); |
dispreg(ln,21, "uR5 ", cmd_read(21)); |
dispreg(ln,41, "uR6 ", cmd_read(22)); |
dispreg(ln,61, "uR7 ", cmd_read(23)); ln++; |
|
dispreg(ln, 1, "uR8 ", cmd_read(24)); |
dispreg(ln,21, "uR9 ", cmd_read(25)); |
dispreg(ln,41, "uR10", cmd_read(26)); |
dispreg(ln,61, "uR11", cmd_read(27)); ln++; |
|
dispreg(ln, 1, "uR12", cmd_read(28)); |
dispreg(ln,21, "uSP ", cmd_read(29)); |
cc = cmd_read(30); |
mvprintw(ln,41, "uCC :%s%s%s%s%s%s%s", |
(cc&0x040)?"STP":" ", |
(cc&0x020)?"GIE":" ", |
(cc&0x010)?"SLP":" ", |
(cc&8)?"V":" ", |
(cc&4)?"N":" ", |
(cc&2)?"C":" ", |
(cc&1)?"Z":" "); |
mvprintw(ln,61, "uPC : 0x%08x", cmd_read(31)); |
|
attroff(A_BOLD); |
ln+=2; |
|
ln+=3; |
BUSW pc = cmd_read((gie)?31:15); |
showins(ln, "I ", gie, pc+2); ln++; |
showins(ln, "Dc", gie, pc+1); ln++; |
showins(ln, "Op", gie, pc ); ln++; |
showins(ln, "Al", gie, pc-1); ln++; |
} |
}; |
|
DEVBUS *m_fpga; |
|
int main(int argc, char **argv) { |
// FPGAOPEN(m_fpga); |
ZIPPY *zip = new ZIPPY(m_fpga); |
|
initscr(); |
raw(); |
noecho(); |
keypad(stdscr, true); |
|
int chv; |
bool done = false; |
|
zip->halt(); |
for(int i=0; (i<5)&&(zip->stalled()); i++) |
; |
if (!zip->stalled()) |
zip->read_state(); |
while(!done) { |
chv = getch(); |
switch(chv) { |
case 'g': case 'G': |
m_fpga->writeio(R_ZIPCTRL, CPU_GO); |
// We just released the CPU, so we're now done. |
done = true; |
break; |
case 'q': case 'Q': |
done = true; |
break; |
case 'r': case 'R': |
zip->reset(); |
erase(); |
break; |
case 's': case 'S': |
zip->step(); |
break; |
case ERR: |
default: |
; |
} |
|
if (zip->stalled()) |
erase(); |
else |
zip->read_state(); |
} |
|
endwin(); |
} |
|
/zipcpu/trunk/sw/zipdbg/regdefs.h
0,0 → 1,70
/////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: regdefs.h |
// |
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core |
// |
// Purpose: This is a generic file that will need to be modified from one |
// board implementation of the ZIP CPU to another. Specifically, |
// this file defines where items are on a WISHBONE bus. In this |
// case, the Zip CPU debug addresses are found at 0x060 and 0x61. |
// The Zip Debugger needs to know these addresses in order to |
// know what addresses to peek and poke to control and access the |
// Zip CPU. |
// |
// |
// Creator: Dan Gisselquist |
// Gisselquist Tecnology, LLC |
// |
/////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
// by the Free Software Foundation, either version 3 of the License, or (at |
// your option) any later version. |
// |
// This program is distributed in the hope that it will be useful, but WITHOUT |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
/////////////////////////////////////////////////////////////////////////////// |
// |
// |
#ifndef REGDEFS_H |
#define REGDEFS_H |
|
// Zip CPU Control and Debug registers |
#define R_ZIPCTRL 0x00000060 |
#define R_ZIPDATA 0x00000061 |
|
// RAM memory space |
#define RAMBASE 0x00008000 |
// Flash memory space |
#define QSPIFLASH 0x00100000 |
|
#define RAMLEN 0x08000 |
|
#define CPU_GO 0x0000 |
#define CPU_RESET 0x0040 |
#define CPU_INT 0x0080 |
#define CPU_STEP 0x0100 |
#define CPU_STALL 0x0200 |
#define CPU_HALT 0x0400 |
#define CPU_CLRCACHE 0x0800 |
#define CPU_sR0 (0x0000|CPU_HALT) |
#define CPU_sSP (0x000d|CPU_HALT) |
#define CPU_sCC (0x000e|CPU_HALT) |
#define CPU_sPC (0x000f|CPU_HALT) |
#define CPU_uR0 (0x0010|CPU_HALT) |
#define CPU_uSP (0x001d|CPU_HALT) |
#define CPU_uCC (0x001e|CPU_HALT) |
#define CPU_uPC (0x001f|CPU_HALT) |
|
#endif |
/zipcpu/trunk/sw/zipdbg/devbus.h
0,0 → 1,95
/////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: devbus.h |
// |
// Project: UART to WISHBONE FPGA library |
// |
// Purpose: The purpose of this file is to document an interface which |
// any devic with a bus, whether it be implemented over a UART, |
// an ethernet, or a PCI express bus, must implement. This |
// describes only an interface, and not how that interface is |
// to be accomplished. |
// |
// Creator: Dan Gisselquist |
// Gisselquist Tecnology, LLC |
// |
/////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
// by the Free Software Foundation, either version 3 of the License, or (at |
// your option) any later version. |
// |
// This program is distributed in the hope that it will be useful, but WITHOUT |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
/////////////////////////////////////////////////////////////////////////////// |
// |
// |
#ifndef DEVBUS_H |
#define DEVBUS_H |
|
#include <unistd.h> |
|
typedef unsigned int uint32; |
|
class BUSERR { |
public: |
uint32 addr; |
BUSERR(const uint32 a) : addr(a) {}; |
}; |
|
class DEVBUS { |
public: |
typedef uint32 BUSW; |
|
virtual void kill(void) = 0; |
virtual void close(void) = 0; |
|
// Write a single value to a single address |
virtual void writeio(const BUSW a, const BUSW v) = 0; |
|
// Read a single value to a single address |
virtual BUSW readio(const BUSW a) = 0; |
|
// Read a series of values from values from a block of memory |
virtual void readi(const BUSW a, const int len, BUSW *buf) = 0; |
|
// Read a series of values from the same address in memory |
virtual void readz(const BUSW a, const int len, BUSW *buf) = 0; |
|
virtual void writei(const BUSW a, const int len, const BUSW *buf) = 0; |
virtual void writez(const BUSW a, const int len, const BUSW *buf) = 0; |
|
// Query whether or not an interrupt has taken place |
virtual bool poll(void) = 0; |
|
// Sleep until interrupt, but sleep no longer than msec milliseconds |
virtual void usleep(unsigned msec) = 0; |
|
// Sleep until an interrupt, no matter how long it takes for that |
// interrupt to take place |
virtual void wait(void) = 0; |
|
// Query whether or not a bus error has taken place. This is somewhat |
// of a misnomer, as my current bus error detection code exits any |
// interface, but ... it is what it is. |
virtual bool bus_err(void) const = 0; |
|
// Clear any bus error condition. |
virtual void reset_err(void) = 0; |
|
// Clear any interrupt condition that has already been noticed by |
// the interface, does not check for further interrupt |
virtual void clear(void) = 0; |
}; |
|
#endif |
/zipcpu/trunk/sw/zasm/test.S
11,6 → 11,20
; Status: As of August, 2015, this file assembles, builds, and passes |
; all of its tests in the Verilator simulator. |
; |
; Okay, as of 15 August, there are now some tests that don't pass. |
; In particular, the #include test used to pass but didn't pass today. |
; Likewise the PUSH() macro test hasn't passed yet. Finally, be aware |
; that this implementation is specific to where it loads on a board. |
; I tried loading it on my Basys development board, where I had placed |
; RAM in a different location and ... things didn't work out so well. |
; So grep the __here__ line and adjust it for where you intend to load |
; this file. |
; |
; In general, as I'm building the CPU, I'm modifying this file to place |
; more and more capability tests within the file. If the Lord is |
; willing, this will become the proof that the CPU completely works. |
; |
; |
; Creator: Dan Gisselquist, Ph.D. |
; Gisselquist Tecnology, LLC |
; |
34,7 → 48,7
; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; |
#include "sys.i" |
// #include "sys.i" |
sys.bus equ 0xc0000000 |
sys.breaken equ 0x080 |
sys.step equ 0x040 |
108,6 → 122,7
mov R0,uCC |
; Don't clear the user PC register |
; Now, let's try loading some constants into registers |
; Specifically, we're testing the LDI, LDIHI, and LDILO instructions |
dead_beef equ 0xdeadbeef |
ldi 0x0dead,r5 |
ldi 0x0beef,r6 |
372,6 → 387,19
cmp $5,r2 |
trap.ne r11 |
|
// Let's test whether LSL works |
ldi $0x0b00,r11 |
ldi 0x035,r2 |
lsl 8,r2 |
ldi 0x03500,r1 |
cmp r2,r1 |
trap.ne r11 |
ldi 0x074,r0 |
and 0x0ff,r0 |
or r0,r2 |
cmp 0x03574,r2 |
trap.ne r11 |
|
// Return success / Test the trap interrupt |
clr r11 |
trap r11 |
384,6 → 412,7
halt |
|
// Now, let's test whether or not we can handle a subroutine |
#ifdef PUSH_TEST |
reverse_bit_order: |
PUSH(R1,SP) |
PUSH(R2,SP) |
398,6 → 427,7
POP(R2,SP) |
POP(R1,SP) |
RET |
#endif |
fill 512,0 |
stack: |
word 0 |