URL
https://opencores.org/ocsvn/openarty/openarty/trunk
Subversion Repositories openarty
Compare Revisions
- This comparison shows the changes necessary to convert path
/openarty/trunk/sw/host
- from Rev 30 to Rev 31
- ↔ Reverse comparison
Rev 30 → Rev 31
/cpuscope.cpp
0,0 → 1,167
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: cpuscope.cpp |
// |
// Project: XuLA2-LX25 SoC based upon the ZipCPU |
// |
// Purpose: To read out, and decompose, the results of the wishbone scope |
// as applied to the ZipCPU internal operation. |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015-2016, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
// by the Free Software Foundation, either version 3 of the License, or (at |
// your option) any later version. |
// |
// This program is distributed in the hope that it will be useful, but WITHOUT |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <strings.h> |
#include <ctype.h> |
#include <string.h> |
#include <signal.h> |
#include <assert.h> |
|
#include "port.h" |
#include "llcomms.h" |
#include "regdefs.h" |
#include "scopecls.h" |
|
#define WBSCOPE R_CPUSCOPE |
#define WBSCOPEDATA R_CPUSCOPED |
|
FPGA *m_fpga; |
void closeup(int v) { |
m_fpga->kill(); |
exit(0); |
} |
|
const char *regstr[] = { |
"R0","R1","R2","R3","R4","R5","R6","R7","R8","R9","RA","RB","RC", |
"SP","CC","PC" |
}; |
|
class CPUSCOPE : public SCOPE { |
public: |
CPUSCOPE(FPGA *fpga, unsigned addr, bool vecread) |
: SCOPE(fpga, addr, false, false) {}; |
~CPUSCOPE(void) {} |
virtual void decode(DEVBUS::BUSW val) const { |
if (val & 0x80000000) |
printf("TRIG "); |
else |
printf(" "); |
if ((val & 0x40000000)==0) { |
printf("%s <- 0x.%08x", regstr[(val>>32-6)&0xf], val&0x03ffffff); |
} else if ((val & 0x60000000)==0x60000000) { |
if (val&0x08000000) |
printf("MEM-W[0x........] <- 0x.%07x %s", |
(val&0x07ffffff), |
(val&0x10000000)?"(GBL)":""); |
else |
printf("MEM-R[0x.%07x] -> (Not Givn) %s", |
(val&0x07ffffff), |
(val&0x10000000)?"(GBL)":""); |
} else if ((val & 0x70000000)==0x40000000) |
printf("JMP 0x%08x", (val&0x0fffffff)); |
else { |
int master, halt, brk, sleep, gie, buserr, trap, |
ill, clri, pfv, pfi, dcdce, dcdv, dcdstall, |
opce, opvalid, oppipe, aluce, alubsy, aluwr, |
aluill, aluwrf, memce, memwe, membsy; |
master = (val>>27)&1; |
halt = (val>>26)&1; |
brk = (val>>25)&1; |
sleep = (val>>24)&1; |
gie = (val>>23)&1; |
buserr = (val>>22)&1; |
trap = (val>>21)&1; |
ill = (val>>20)&1; |
clri = (val>>19)&1; |
pfv = (val>>18)&1; |
pfi = (val>>17)&1; |
dcdce = (val>>16)&1; |
dcdv = (val>>15)&1; |
dcdstall=(val>>14)&1; |
opce = (val>>13)&1; |
opvalid= (val>>12)&1; |
oppipe = (val>>11)&1; |
aluce = (val>>10)&1; |
alubsy = (val>> 9)&1; |
aluwr = (val>> 8)&1; |
aluill = (val>> 7)&1; |
aluwrf = (val>> 6)&1; |
memce = (val>> 5)&1; |
memwe = (val>> 4)&1; |
membsy = (val>> 3)&1; |
printf("FLAGS %08x", val); |
printf(" CE[%c%c%c%c]", |
(dcdce)?'D':' ', |
(opce)?'O':' ', |
(aluce)?'A':' ', |
(memce)?'M':' '); |
printf(" V[%c%c%c%c]", |
(pfv)?'P':' ', |
(dcdv)?'D':' ', |
(opvalid)?'O':' ', |
(aluwr)?'A':' '); |
if (master) printf(" MCE"); |
if (halt) printf(" I-HALT"); |
if (brk) printf(" O-BREAK"); |
if (sleep) printf(" SLP"); |
if (GIE) printf(" GIE"); |
if (buserr) printf(" BE"); |
if (trap) printf(" TRAP"); |
if (ill) printf(" ILL"); |
if (clri) printf(" CLR-I"); |
if (pfi) printf(" PF-ILL"); |
if (dcdstall)printf(" DCD-STALL"); |
if (oppipe) printf(" OP-PIPE"); |
if (alubsy) printf(" ALU-BUSY"); |
if (memwe) printf(" MEM-WE"); |
if (membsy) printf(" MEM-BUSY"); |
// |
} |
} |
}; |
|
int main(int argc, char **argv) { |
FPGAOPEN(m_fpga); |
|
signal(SIGSTOP, closeup); |
signal(SIGHUP, closeup); |
|
CPUSCOPE *scope = new CPUSCOPE(m_fpga, WBSCOPE, false); |
if (!scope->ready()) { |
printf("Scope is not yet ready:\n"); |
scope->decode_control(); |
scope->decode(WBSCOPEDATA); |
printf("\n"); |
} else |
scope->read(); |
delete m_fpga; |
} |
|
/erxscope.cpp
0,0 → 1,122
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: erxscope.cpp |
// |
// Project: XuLA2-LX25 SoC based upon the ZipCPU |
// |
// Purpose: This file decodes the debug bits produced by the enetpackets.v |
// Verilog module, and stored in a Wishbone Scope. It is useful |
// for determining if the packet transmitter works at all or not. |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015-2016, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
// by the Free Software Foundation, either version 3 of the License, or (at |
// your option) any later version. |
// |
// This program is distributed in the hope that it will be useful, but WITHOUT |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <strings.h> |
#include <ctype.h> |
#include <string.h> |
#include <signal.h> |
#include <assert.h> |
|
#include "port.h" |
#include "regdefs.h" |
#include "scopecls.h" |
|
#define WBSCOPE R_NETSCOPE |
#define WBSCOPEDATA R_NETSCOPED |
|
FPGA *m_fpga; |
void closeup(int v) { |
m_fpga->kill(); |
exit(0); |
} |
|
class ERXSCOPE : public SCOPE { |
public: |
ERXSCOPE(FPGA *fpga, unsigned addr, bool vecread = true) |
: SCOPE(fpga, addr, false, vecread) {}; |
~ERXSCOPE(void) {} |
virtual void decode(DEVBUS::BUSW val) const { |
int trigger, nerr, wr, nprev, crcv, mace, bcast, clear, |
rxerr, miss, rxvalid, rxbusy, crs, dv, rxd, macv, |
pred, crcd, macd, neop; |
|
trigger= (val>>31)&1; |
neop = (val>>30)&1; |
wr = (val>>29)&1; |
nprev = (val>>28)&1; |
pred = (val>>24)&15; |
crcv = (val>>23)&1; |
crcd = (val>>19)&15; |
mace = (val>>18)&1; |
bcast = (val>>17)&1; |
macv = (val>>16)&1; |
macd = (val>>12)&15; |
clear = (val>>11)&1; |
rxerr = (val>>10)&1; |
miss = (val>> 9)&1; |
nerr = (val>> 8)&1; |
rxvalid= (val>> 7)&1; |
rxbusy = (val>> 6)&1; |
crs = (val>> 5)&1; |
dv = (val>> 4)&1; |
rxd = (val )&15; |
|
printf("%s [%s%s%s%x] p[%s%x] c[%s%x] m[%s%s%s%x] ![%s-] %s%s%s%s%s%s", |
(trigger)?"TR":" ", |
(rxerr)?"RXER":" ", |
(crs)?"CRS":" ", |
(dv)?"DV":" ", rxd, |
(nprev)?"P":" ", pred, |
(crcv)?"C":" ", crcd, |
(bcast)?"B":" ", (mace)?"E":" ", (macv)?"M":" ", macd, |
(wr)?"WR":" ", (nerr)?"ER":" ", (rxbusy)?"BSY":" ", |
(neop)?"EOP":" ", |
(miss)?"MISS":" ", (clear)?"CLEAR":" ", |
(rxvalid)?"VALID":" "); |
} |
}; |
|
int main(int argc, char **argv) { |
FPGAOPEN(m_fpga); |
|
signal(SIGSTOP, closeup); |
signal(SIGHUP, closeup); |
|
ERXSCOPE *scope = new ERXSCOPE(m_fpga, WBSCOPE); |
if (!scope->ready()) { |
printf("Scope is not yet ready:\n"); |
scope->decode_control(); |
} else |
scope->read(); |
delete m_fpga; |
} |
|
/zipdbg.cpp
0,0 → 1,689
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: |
// |
// Project: OpenArty, an entirely open SoC based upon the Arty platform |
// |
// Project: XuLA2-LX25 SoC based upon the ZipCPU |
// |
// Purpose: Provide a debugger to step through the ZipCPU assembler, |
// evaluate the ZipCPU's current state, modify registers as(if) |
// needed, etc. All of this through the UART port of the Arty board. |
// |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015-2016, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
// by the Free Software Foundation, either version 3 of the License, or (at |
// your option) any later version. |
// |
// This program is distributed in the hope that it will be useful, but WITHOUT |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include <stdlib.h> |
#include <signal.h> |
#include <time.h> |
#include <unistd.h> |
#include <string.h> |
|
#include <ctype.h> |
#include <ncurses.h> |
|
#include "zopcodes.h" |
#include "zparser.h" |
#include "devbus.h" |
#include "regdefs.h" |
|
#include "port.h" |
|
#define CMD_REG 0 |
#define CMD_DATA 1 |
#define CMD_HALT (1<<10) |
#define CMD_STALL (1<<9) |
#define CMD_STEP (1<<8) |
#define CMD_INT (1<<7) |
#define CMD_RESET (1<<6) |
|
#define KEY_ESCAPE 27 |
#define KEY_RETURN 10 |
#define CTRL(X) ((X)&0x01f) |
|
class SPARSEMEM { |
public: |
bool m_valid; |
unsigned int m_a, m_d; |
}; |
|
bool gbl_err = false; |
class ZIPSTATE { |
public: |
bool m_valid, m_gie, m_last_pc_valid; |
unsigned int m_sR[16], m_uR[16]; |
unsigned int m_p[20]; |
unsigned int m_last_pc, m_pc, m_sp; |
SPARSEMEM m_smem[5]; |
SPARSEMEM m_imem[5]; |
ZIPSTATE(void) : m_valid(false), m_last_pc_valid(false) {} |
|
void step(void) { |
m_last_pc_valid = true; |
m_last_pc = m_pc; |
} |
}; |
|
// No particular "parameters" need definition or redefinition here. |
class ZIPPY : public DEVBUS { |
static const int MAXERR; |
typedef DEVBUS::BUSW BUSW; |
DEVBUS *m_fpga; |
int m_cursor; |
ZIPSTATE m_state; |
bool m_user_break, m_show_users_timers, m_show_cc; |
public: |
ZIPPY(DEVBUS *fpga) : m_fpga(fpga), m_cursor(0), m_user_break(false), |
m_show_users_timers(false), m_show_cc(false) {} |
|
void read_raw_state(void) { |
m_state.m_valid = false; |
for(int i=0; i<16; i++) |
m_state.m_sR[i] = cmd_read(i); |
for(int i=0; i<16; i++) |
m_state.m_uR[i] = cmd_read(i+16); |
for(int i=0; i<20; i++) |
m_state.m_p[i] = cmd_read(i+32); |
|
m_state.m_gie = (m_state.m_sR[14] & 0x020); |
m_state.m_pc = (m_state.m_gie) ? (m_state.m_uR[15]):(m_state.m_sR[15]); |
m_state.m_sp = (m_state.m_gie) ? (m_state.m_uR[13]):(m_state.m_sR[13]); |
|
if (m_state.m_last_pc_valid) |
m_state.m_imem[0].m_a = m_state.m_last_pc; |
else |
m_state.m_imem[0].m_a = m_state.m_pc - 1; |
try { |
m_state.m_imem[0].m_d = readio(m_state.m_imem[0].m_a); |
m_state.m_imem[0].m_valid = true; |
} catch(BUSERR be) { |
m_state.m_imem[0].m_valid = false; |
} |
m_state.m_imem[1].m_a = m_state.m_pc; |
try { |
m_state.m_imem[1].m_d = readio(m_state.m_imem[1].m_a); |
m_state.m_imem[1].m_valid = true; |
} catch(BUSERR be) { |
m_state.m_imem[1].m_valid = false; |
} |
|
for(int i=1; i<4; i++) { |
if (!m_state.m_imem[i].m_valid) { |
m_state.m_imem[i+1].m_valid = false; |
m_state.m_imem[i+1].m_a = m_state.m_imem[i].m_a+1; |
continue; |
} |
m_state.m_imem[i+1].m_a = zop_early_branch( |
m_state.m_imem[i].m_a, |
m_state.m_imem[i].m_d); |
try { |
m_state.m_imem[i+1].m_d = readio(m_state.m_imem[i+1].m_a); |
m_state.m_imem[i+1].m_valid = true; |
} catch(BUSERR be) { |
m_state.m_imem[i+1].m_valid = false; |
} |
} |
|
m_state.m_smem[0].m_a = m_state.m_sp; |
for(int i=1; i<5; i++) |
m_state.m_smem[i].m_a = m_state.m_smem[i-1].m_a+1; |
for(int i=0; i<5; i++) { |
m_state.m_smem[i].m_valid = true; |
if (m_state.m_smem[i].m_valid) |
try { |
m_state.m_smem[i].m_d = readio(m_state.m_smem[i].m_a); |
m_state.m_smem[i].m_valid = true; |
} catch(BUSERR be) { |
m_state.m_smem[i].m_valid = false; |
} |
} |
m_state.m_valid = true; |
} |
|
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); m_state.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 show_user_timers(bool v) { |
m_show_users_timers = v; |
} |
|
void toggle_cc(void) { |
m_show_cc = !m_show_cc; |
} |
|
void showval(int y, int x, const char *lbl, unsigned int v, bool c) { |
if (c) |
mvprintw(y,x, ">%s> 0x%08x<", lbl, v); |
else |
mvprintw(y,x, " %s: 0x%08x ", lbl, v); |
} |
|
void dispreg(int y, int x, const char *n, unsigned int v, bool c) { |
// 4,4,8,1 = 17 of 20, +2 = 18 |
if (c) |
mvprintw(y, x, ">%s> 0x%08x<", n, v); |
else |
mvprintw(y, x, " %s: 0x%08x ", n, v); |
} |
|
int showins(int y, const char *lbl, const unsigned int pcidx) { |
char la[80], lb[80]; |
int r = y-1; |
|
mvprintw(y, 0, "%s0x%08x", lbl, m_state.m_imem[pcidx].m_a); |
|
if (m_state.m_gie) attroff(A_BOLD); |
else attron(A_BOLD); |
|
la[0] = '\0'; |
lb[0] = '\0'; |
if (m_state.m_imem[pcidx].m_valid) { |
zipi_to_string(m_state.m_imem[pcidx].m_d, la, lb); |
printw(" 0x%08x", m_state.m_imem[pcidx].m_d); |
printw(" %-25s", la); |
if (lb[0]) { |
mvprintw(y-1, 0, "%s", lbl); |
mvprintw(y-1, strlen(lbl)+10+3+8+2, "%-25s", lb); |
r--; |
} |
} else { |
printw(" 0x-------- %-25s", "(Bus Error)"); |
} |
attroff(A_BOLD); |
|
return r; |
} |
|
void showstack(int y, const char *lbl, const unsigned int idx) { |
mvprintw(y, 27+26, "%s%08x ", lbl, m_state.m_smem[idx].m_a); |
|
if (m_state.m_gie) attroff(A_BOLD); |
else attron(A_BOLD); |
|
if (m_state.m_smem[idx].m_valid) |
printw("0x%08x", m_state.m_smem[idx].m_d); |
else |
printw("(Bus Err)"); |
attroff(A_BOLD); |
} |
|
unsigned int cmd_read(unsigned int a) { |
int errcount = 0; |
unsigned int s; |
|
writeio(R_ZIPCTRL, CMD_HALT|(a&0x3f)); |
while((((s=readio(R_ZIPCTRL))&CPU_STALL)== 0)&&(errcount<MAXERR) |
&&(!m_user_break)) |
errcount++; |
if (m_user_break) { |
endwin(); |
exit(EXIT_SUCCESS); |
} else if (errcount >= MAXERR) { |
endwin(); |
printf("ERR: errcount(%d) >= MAXERR on cmd_read(a=%2x)\n", errcount, a); |
printf("ZIPCTRL = 0x%08x", s); |
if ((s & 0x0200)==0) printf(" STALL"); |
if (s & 0x0400) printf(" HALTED"); |
if ((s & 0x03000)==0x01000) |
printf(" SW-HALT"); |
else { |
if (s & 0x01000) printf(" SLEEPING"); |
if (s & 0x02000) printf(" GIE(UsrMode)"); |
} printf("\n"); |
exit(EXIT_FAILURE); |
} |
return readio(R_ZIPDATA); |
} |
|
void cmd_write(unsigned int a, int v) { |
int errcount = 0; |
unsigned int s; |
|
writeio(R_ZIPCTRL, CMD_HALT|(a&0x3f)); |
while((((s=readio(R_ZIPCTRL))&CPU_STALL)== 0)&&(errcount<MAXERR) |
&&(!m_user_break)) |
errcount++; |
if (m_user_break) { |
endwin(); |
exit(EXIT_SUCCESS); |
} else if (errcount >= MAXERR) { |
endwin(); |
printf("ERR: errcount(%d) >= MAXERR on cmd_read(a=%2x)\n", errcount, a); |
printf("ZIPCTRL = 0x%08x", s); |
if ((s & 0x0200)==0) printf(" STALL"); |
if (s & 0x0400) printf(" HALTED"); |
if ((s & 0x03000)==0x01000) |
printf(" SW-HALT"); |
else { |
if (s & 0x01000) printf(" SLEEPING"); |
if (s & 0x02000) printf(" GIE(UsrMode)"); |
} printf("\n"); |
exit(EXIT_FAILURE); |
} |
|
writeio(R_ZIPDATA, (unsigned int)v); |
} |
|
void read_state(void) { |
int ln= 0; |
bool gie; |
|
read_raw_state(); |
|
if (m_cursor < 0) |
m_cursor = 0; |
else if (m_cursor >= 44) |
m_cursor = 43; |
|
mvprintw(ln,0, "Peripherals"); |
mvprintw(ln,30,"%-50s", "CPU State: "); |
{ |
unsigned int v = readio(R_ZIPCTRL); |
mvprintw(ln,41, "0x%08x ", v); |
// if (v & 0x010000) |
// printw("INT "); |
if ((v & 0x003000) == 0x03000) |
printw("Sleeping "); |
else if (v & 0x001000) |
printw("Halted "); |
else if (v & 0x002000) |
printw("User Mode "); |
else |
printw("Supervisor mode "); |
if (v& 0x0200) { |
v = m_state.m_sR[15]; |
|
} else printw("Stalled "); |
// if (v & 0x008000) |
// printw("Break-Enabled "); |
// if (v & 0x000080) |
// printw("PIC Enabled "); |
} ln++; |
showval(ln, 0, "PIC ", m_state.m_p[0], (m_cursor==0)); |
showval(ln,20, "WDT ", m_state.m_p[1], (m_cursor==1)); |
showval(ln,40, "WBUS", m_state.m_p[2], (m_cursor==2)); |
showval(ln,60, "PIC2", m_state.m_p[3], (m_cursor==3)); |
ln++; |
showval(ln, 0, "TMRA", m_state.m_p[4], (m_cursor==4)); |
showval(ln,20, "TMRB", m_state.m_p[5], (m_cursor==5)); |
showval(ln,40, "TMRC", m_state.m_p[6], (m_cursor==6)); |
showval(ln,60, "JIF ", m_state.m_p[7], (m_cursor==7)); |
|
ln++; |
if (!m_show_users_timers) { |
showval(ln, 0, "MTSK", m_state.m_p[ 8], (m_cursor==8)); |
showval(ln,20, "MOST", m_state.m_p[ 9], (m_cursor==9)); |
showval(ln,40, "MPST", m_state.m_p[10], (m_cursor==10)); |
showval(ln,60, "MICT", m_state.m_p[11], (m_cursor==11)); |
} else { |
showval(ln, 0, "UTSK", m_state.m_p[12], (m_cursor==8)); |
showval(ln,20, "UMST", m_state.m_p[13], (m_cursor==9)); |
showval(ln,40, "UPST", m_state.m_p[14], (m_cursor==10)); |
showval(ln,60, "UICT", m_state.m_p[15], (m_cursor==11)); |
} |
|
ln++; |
ln++; |
unsigned int cc = m_state.m_sR[14]; |
gie = (cc & 0x020); |
if (gie) |
attroff(A_BOLD); |
else |
attron(A_BOLD); |
mvprintw(ln, 0, "Supervisor Registers"); |
ln++; |
|
dispreg(ln, 0, "sR0 ", m_state.m_sR[0], (m_cursor==12)); |
dispreg(ln,20, "sR1 ", m_state.m_sR[1], (m_cursor==13)); |
dispreg(ln,40, "sR2 ", m_state.m_sR[2], (m_cursor==14)); |
dispreg(ln,60, "sR3 ", m_state.m_sR[3], (m_cursor==15)); ln++; |
|
dispreg(ln, 0, "sR4 ", m_state.m_sR[4], (m_cursor==16)); |
dispreg(ln,20, "sR5 ", m_state.m_sR[5], (m_cursor==17)); |
dispreg(ln,40, "sR6 ", m_state.m_sR[6], (m_cursor==18)); |
dispreg(ln,60, "sR7 ", m_state.m_sR[7], (m_cursor==19)); ln++; |
|
dispreg(ln, 0, "sR8 ", m_state.m_sR[ 8], (m_cursor==20)); |
dispreg(ln,20, "sR9 ", m_state.m_sR[ 9], (m_cursor==21)); |
dispreg(ln,40, "sR10", m_state.m_sR[10], (m_cursor==22)); |
dispreg(ln,60, "sR11", m_state.m_sR[11], (m_cursor==23)); ln++; |
|
dispreg(ln, 0, "sR12", m_state.m_sR[12], (m_cursor==24)); |
dispreg(ln,20, "sSP ", m_state.m_sR[13], (m_cursor==25)); |
|
if (m_show_cc) { |
mvprintw(ln,40, " sCC :%16s", ""); |
dispreg(ln, 40, "sCC ", m_state.m_sR[14], (m_cursor==26)); |
} else { |
mvprintw(ln,40, " sCC :%16s", ""); |
mvprintw(ln,40, "%ssCC :%s%s%s%s%s%s%s", |
(m_cursor == 26)?">":" ", |
(cc&0x1000)?"FE":"", // Floating point exception |
(cc&0x0800)?"DV":"", // Division by zero |
(cc&0x0400)?"BE":"", // Bus Error |
(cc&0x0200)?"TP":"", // Trap |
(cc&0x0100)?"IL":"", // Illegal instruction |
(cc&0x0080)?"BK":"", // Break |
((gie==0)&&(cc&0x0010))?"HLT":""); // Halted |
mvprintw(ln,54,"%s%s%s%s", |
(cc&8)?"V":" ", |
(cc&4)?"N":" ", |
(cc&2)?"C":" ", |
(cc&1)?"Z":" "); |
} |
dispreg(ln,60, "sPC ", m_state.m_sR[15], (m_cursor==27)); |
ln++; |
|
if (gie) |
attron(A_BOLD); |
else |
attroff(A_BOLD); |
mvprintw(ln, 0, "User Registers"); ln++; |
dispreg(ln, 0, "uR0 ", m_state.m_uR[0], (m_cursor==28)); |
dispreg(ln,20, "uR1 ", m_state.m_uR[1], (m_cursor==29)); |
dispreg(ln,40, "uR2 ", m_state.m_uR[2], (m_cursor==30)); |
dispreg(ln,60, "uR3 ", m_state.m_uR[3], (m_cursor==31)); ln++; |
|
dispreg(ln, 0, "uR4 ", m_state.m_uR[4], (m_cursor==32)); |
dispreg(ln,20, "uR5 ", m_state.m_uR[5], (m_cursor==33)); |
dispreg(ln,40, "uR6 ", m_state.m_uR[6], (m_cursor==34)); |
dispreg(ln,60, "uR7 ", m_state.m_uR[7], (m_cursor==35)); ln++; |
|
dispreg(ln, 0, "uR8 ", m_state.m_uR[8], (m_cursor==36)); |
dispreg(ln,20, "uR9 ", m_state.m_uR[9], (m_cursor==37)); |
dispreg(ln,40, "uR10", m_state.m_uR[10], (m_cursor==38)); |
dispreg(ln,60, "uR11", m_state.m_uR[11], (m_cursor==39)); ln++; |
|
dispreg(ln, 0, "uR12", m_state.m_uR[12], (m_cursor==40)); |
dispreg(ln,20, "uSP ", m_state.m_uR[13], (m_cursor==41)); |
cc = m_state.m_uR[14]; |
if (m_show_cc) { |
mvprintw(ln,40, " uCC :%16s", ""); |
dispreg(ln, 40, "uCC ", m_state.m_uR[14], (m_cursor==42)); |
} else { |
mvprintw(ln,40, " uCC :%16s", ""); |
mvprintw(ln,40, "%suCC :%s%s%s%s%s%s%s", |
(m_cursor == 42)?">":" ", |
(cc&0x1000)?"FE":"", // Floating point Exception |
(cc&0x0800)?"DV":"", // Division by zero |
(cc&0x0400)?"BE":"", // Bus Error |
(cc&0x0200)?"TP":"", // Trap |
(cc&0x0100)?"IL":"", // Illegal instruction |
(cc&0x0040)?"ST":"", // Single-step |
((gie)&&(cc&0x0010))?"SL":""); // Sleep |
mvprintw(ln,54,"%s%s%s%s", |
(cc&8)?"V":" ", |
(cc&4)?"N":" ", |
(cc&2)?"C":" ", |
(cc&1)?"Z":" "); |
} |
dispreg(ln,60, "uPC ", m_state.m_uR[15], (m_cursor==43)); |
|
attroff(A_BOLD); |
ln+=3; |
|
showins(ln+4, " ", 0); |
{ |
int lclln = ln+3; |
for(int i=1; i<5; i++) |
lclln = showins(lclln, (i==1)?">":" ", i); |
for(int i=0; i<5; i++) |
showstack(ln+i, (i==0)?">":" ", i); |
} |
} |
|
void cursor_up(void) { |
if (m_cursor > 3) |
m_cursor -= 4; |
} void cursor_down(void) { |
if (m_cursor < 40) |
m_cursor += 4; |
} void cursor_left(void) { |
if (m_cursor > 0) |
m_cursor--; |
else m_cursor = 43; |
} void cursor_right(void) { |
if (m_cursor < 43) |
m_cursor++; |
else m_cursor = 0; |
} |
|
int cursor(void) { return m_cursor; } |
}; |
|
const int ZIPPY::MAXERR = 100000; |
|
FPGA *m_fpga; |
|
void get_value(ZIPPY *zip) { |
int wy, wx, ra; |
int c = zip->cursor(); |
|
wx = (c & 0x03) * 20 + 9 + 1; |
wy = (c >> 2); |
if (wy >= 3+4) |
wy++; |
if (wy > 3) |
wy += 2; |
wy++; |
|
if (c >= 12) |
ra = c - 12; |
else |
ra = c + 32; |
|
bool done = false; |
char str[16]; |
int pos = 0; str[pos] = '\0'; |
attron(A_NORMAL | A_UNDERLINE); |
mvprintw(wy, wx, "%-8s", ""); |
while(!done) { |
int chv = getch(); |
switch(chv) { |
case KEY_ESCAPE: |
pos = 0; str[pos] = '\0'; done = true; |
break; |
case KEY_RETURN: case KEY_ENTER: case KEY_UP: case KEY_DOWN: |
done = true; |
break; |
case KEY_LEFT: case KEY_BACKSPACE: |
if (pos > 0) pos--; |
break; |
case KEY_CLEAR: |
pos = 0; |
break; |
case '0': case ' ': str[pos++] = '0'; break; |
case '1': str[pos++] = '1'; break; |
case '2': str[pos++] = '2'; break; |
case '3': str[pos++] = '3'; break; |
case '4': str[pos++] = '4'; break; |
case '5': str[pos++] = '5'; break; |
case '6': str[pos++] = '6'; break; |
case '7': str[pos++] = '7'; break; |
case '8': str[pos++] = '8'; break; |
case '9': str[pos++] = '9'; break; |
case 'A': case 'a': str[pos++] = 'A'; break; |
case 'B': case 'b': str[pos++] = 'B'; break; |
case 'C': case 'c': str[pos++] = 'C'; break; |
case 'D': case 'd': str[pos++] = 'D'; break; |
case 'E': case 'e': str[pos++] = 'E'; break; |
case 'F': case 'f': str[pos++] = 'F'; break; |
} |
|
if (pos > 8) |
pos = 8; |
str[pos] = '\0'; |
|
attron(A_NORMAL | A_UNDERLINE); |
mvprintw(wy, wx, "%-8s", str); |
if (pos > 0) { |
attron(A_NORMAL | A_UNDERLINE | A_BLINK); |
mvprintw(wy, wx+pos-1, "%c", str[pos-1]); |
} |
attrset(A_NORMAL); |
} |
|
if (pos > 0) { |
int v; |
v = strtoul(str, NULL, 16); |
zip->cmd_write(ra, v); |
} |
} |
|
void on_sigint(int v) { |
endwin(); |
|
fprintf(stderr, "Interrupted!\n"); |
exit(-2); |
} |
|
void stall_screen(void) { |
erase(); |
mvprintw(0,0, "CPU is stalled. (Q to quit)\n"); |
} |
|
int main(int argc, char **argv) { |
// FPGAOPEN(m_fpga); |
ZIPPY *zip; // |
|
int skp=0, port = FPGAPORT; |
|
FPGAOPEN(m_fpga); |
zip = new ZIPPY(m_fpga); |
|
|
initscr(); |
raw(); |
noecho(); |
keypad(stdscr, true); |
|
signal(SIGINT, on_sigint); |
|
int chv; |
bool done = false; |
|
zip->halt(); |
for(int i=0; (i<5)&&(zip->stalled()); i++) |
; |
if (!zip->stalled()) |
zip->read_state(); |
else |
stall_screen(); |
while((!done)&&(!gbl_err)) { |
chv = getch(); |
switch(chv) { |
case 'c': case 'C': |
zip->toggle_cc(); |
break; |
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 'l': case 'L': case CTRL('L'): |
redrawwin(stdscr); |
case 'm': case 'M': |
zip->show_user_timers(false); |
break; |
case 'q': case 'Q': case CTRL('C'): |
case KEY_CANCEL: case KEY_CLOSE: case KEY_EXIT: |
case KEY_ESCAPE: |
done = true; |
break; |
case 'r': case 'R': |
zip->reset(); |
erase(); |
break; |
case 't': case 'T': |
case 's': case 'S': |
zip->step(); |
break; |
case 'u': case 'U': |
zip->show_user_timers(true); |
break; |
case '\r': case '\n': |
case KEY_IC: case KEY_ENTER: |
get_value(zip); |
break; |
case KEY_UP: |
zip->cursor_up(); |
break; |
case KEY_DOWN: |
zip->cursor_down(); |
break; |
case KEY_LEFT: |
zip->cursor_left(); |
break; |
case KEY_RIGHT: |
zip->cursor_right(); |
break; |
case ERR: case KEY_CLEAR: |
default: |
; |
} |
|
if ((done)||(gbl_err)) |
break; |
else if (zip->stalled()) |
stall_screen(); |
else |
zip->read_state(); |
} |
|
endwin(); |
|
if (gbl_err) { |
printf("Killed on error: could not access bus!\n"); |
exit(-2); |
} |
} |
|
/zipload.cpp
0,0 → 1,535
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: zipload.cpp |
// |
// Project: OpenArty, an entirely open SoC based upon the Arty platform |
// |
// Purpose: To load a program for the ZipCPU into memory, whether flash |
// or SDRAM. This requires a working/running configuration |
// in order to successfully load. |
// |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015-2016, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
// by the Free Software Foundation, either version 3 of the License, or (at |
// your option) any later version. |
// |
// This program is distributed in the hope that it will be useful, but WITHOUT |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include <stdio.h> |
#include <stdlib.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include <fcntl.h> |
#include <unistd.h> |
#include <strings.h> |
#include <ctype.h> |
#include <string.h> |
#include <signal.h> |
#include <assert.h> |
|
#include "port.h" |
#include "llcomms.h" |
#include "regdefs.h" |
#include "flashdrvr.h" |
|
bool iself(const char *fname) { |
FILE *fp; |
bool ret = true; |
|
if ((!fname)||(!fname[0])) |
return false; |
|
fp = fopen(fname, "rb"); |
|
if (!fp) return false; |
if (0x7f != fgetc(fp)) ret = false; |
if ('E' != fgetc(fp)) ret = false; |
if ('L' != fgetc(fp)) ret = false; |
if ('F' != fgetc(fp)) ret = false; |
fclose(fp); |
return ret; |
} |
|
long fgetwords(FILE *fp) { |
// Return the number of words in the current file, and return the |
// file as though it had never been adjusted |
long fpos, flen; |
fpos = ftell(fp); |
if (0 != fseek(fp, 0l, SEEK_END)) { |
fprintf(stderr, "ERR: Could not determine file size\n"); |
perror("O/S Err:"); |
exit(-2); |
} flen = ftell(fp); |
if (0 != fseek(fp, fpos, SEEK_SET)) { |
fprintf(stderr, "ERR: Could not seek on file\n"); |
perror("O/S Err:"); |
exit(-2); |
} flen /= sizeof(FPGA::BUSW); |
return flen; |
} |
|
FPGA *m_fpga; |
class SECTION { |
public: |
unsigned m_start, m_len; |
FPGA::BUSW m_data[1]; |
}; |
|
SECTION **singlesection(int nwords) { |
fprintf(stderr, "NWORDS = %d\n", nwords); |
size_t sz = (2*(sizeof(SECTION)+sizeof(SECTION *)) |
+(nwords-1)*(sizeof(FPGA::BUSW))); |
char *d = (char *)malloc(sz); |
SECTION **r = (SECTION **)d; |
memset(r, 0, sz); |
r[0] = (SECTION *)(&d[2*sizeof(SECTION *)]); |
r[0]->m_len = nwords; |
r[1] = (SECTION *)(&r[0]->m_data[r[0]->m_len]); |
r[0]->m_start = 0; |
r[1]->m_start = 0; |
r[1]->m_len = 0; |
|
return r; |
} |
|
SECTION **rawsection(const char *fname) { |
SECTION **secpp, *secp; |
unsigned num_words; |
FILE *fp; |
int nr; |
|
fp = fopen(fname, "r"); |
if (fp == NULL) { |
fprintf(stderr, "Could not open: %s\n", fname); |
exit(-1); |
} |
|
if ((num_words=fgetwords(fp)) > FLASHWORDS-(RESET_ADDRESS-EQSPIFLASH)) { |
fprintf(stderr, "File overruns flash memory\n"); |
exit(-1); |
} |
secpp = singlesection(num_words); |
secp = secpp[0]; |
secp->m_start = RAMBASE; |
secp->m_len = num_words; |
nr= fread(secp->m_data, sizeof(FPGA::BUSW), num_words, fp); |
if (nr != (int)num_words) { |
fprintf(stderr, "Could not read entire file\n"); |
perror("O/S Err:"); |
exit(-2); |
} assert(secpp[1]->m_len == 0); |
|
return secpp; |
} |
|
unsigned byteswap(unsigned n) { |
unsigned r; |
|
r = (n&0x0ff); n>>= 8; |
r = (r<<8) | (n&0x0ff); n>>= 8; |
r = (r<<8) | (n&0x0ff); n>>= 8; |
r = (r<<8) | (n&0x0ff); n>>= 8; |
|
return r; |
} |
|
// #define CHEAP_AND_EASY |
#ifdef CHEAP_AND_EASY |
#else |
#include <libelf.h> |
#include <gelf.h> |
|
void elfread(const char *fname, unsigned &entry, SECTION **§ions) { |
Elf *e; |
int fd, i; |
size_t n; |
char *id; |
Elf_Kind ek; |
GElf_Ehdr ehdr; |
GElf_Phdr phdr; |
const bool dbg = false; |
|
if (elf_version(EV_CURRENT) == EV_NONE) { |
fprintf(stderr, "ELF library initialization err, %s\n", elf_errmsg(-1)); |
perror("O/S Err:"); |
exit(EXIT_FAILURE); |
} if ((fd = open(fname, O_RDONLY, 0)) < 0) { |
fprintf(stderr, "Could not open %s\n", fname); |
perror("O/S Err:"); |
exit(EXIT_FAILURE); |
} if ((e = elf_begin(fd, ELF_C_READ, NULL))==NULL) { |
fprintf(stderr, "Could not run elf_begin, %s\n", elf_errmsg(-1)); |
exit(EXIT_FAILURE); |
} |
|
ek = elf_kind(e); |
if (ek == ELF_K_ELF) { |
; // This is the kind of file we should expect |
} else if (ek == ELF_K_AR) { |
fprintf(stderr, "Cannot run an archive!\n"); |
exit(EXIT_FAILURE); |
} else if (ek == ELF_K_NONE) { |
; |
} else { |
fprintf(stderr, "Unexpected ELF file kind!\n"); |
exit(EXIT_FAILURE); |
} |
|
if (gelf_getehdr(e, &ehdr) == NULL) { |
fprintf(stderr, "getehdr() failed: %s\n", elf_errmsg(-1)); |
exit(EXIT_FAILURE); |
} if ((i=gelf_getclass(e)) == ELFCLASSNONE) { |
fprintf(stderr, "getclass() failed: %s\n", elf_errmsg(-1)); |
exit(EXIT_FAILURE); |
} if ((id = elf_getident(e, NULL)) == NULL) { |
fprintf(stderr, "getident() failed: %s\n", elf_errmsg(-1)); |
exit(EXIT_FAILURE); |
} if (i != ELFCLASS32) { |
fprintf(stderr, "This is a 64-bit ELF file, ZipCPU ELF files are all 32-bit\n"); |
exit(EXIT_FAILURE); |
} |
|
if (dbg) { |
printf(" %-20s 0x%jx\n", "e_type", (uintmax_t)ehdr.e_type); |
printf(" %-20s 0x%jx\n", "e_machine", (uintmax_t)ehdr.e_machine); |
printf(" %-20s 0x%jx\n", "e_version", (uintmax_t)ehdr.e_version); |
printf(" %-20s 0x%jx\n", "e_entry", (uintmax_t)ehdr.e_entry); |
printf(" %-20s 0x%jx\n", "e_phoff", (uintmax_t)ehdr.e_phoff); |
printf(" %-20s 0x%jx\n", "e_shoff", (uintmax_t)ehdr.e_shoff); |
printf(" %-20s 0x%jx\n", "e_flags", (uintmax_t)ehdr.e_flags); |
printf(" %-20s 0x%jx\n", "e_ehsize", (uintmax_t)ehdr.e_ehsize); |
printf(" %-20s 0x%jx\n", "e_phentsize", (uintmax_t)ehdr.e_phentsize); |
printf(" %-20s 0x%jx\n", "e_shentsize", (uintmax_t)ehdr.e_shentsize); |
printf("\n"); |
} |
|
|
// Check whether or not this is an ELF file for the ZipCPU ... |
if (ehdr.e_machine != 0x0dadd) { |
fprintf(stderr, "This is not a ZipCPU ELF file\n"); |
exit(EXIT_FAILURE); |
} |
|
// Get our entry address |
entry = ehdr.e_entry; |
|
|
// Now, let's go look at the program header |
if (elf_getphdrnum(e, &n) != 0) { |
fprintf(stderr, "elf_getphdrnum() failed: %s\n", elf_errmsg(-1)); |
exit(EXIT_FAILURE); |
} |
|
unsigned total_octets = 0, current_offset=0, current_section=0; |
for(i=0; i<(int)n; i++) { |
total_octets += sizeof(SECTION *)+sizeof(SECTION); |
|
if (gelf_getphdr(e, i, &phdr) != &phdr) { |
fprintf(stderr, "getphdr() failed: %s\n", elf_errmsg(-1)); |
exit(EXIT_FAILURE); |
} |
|
if (dbg) { |
printf(" %-20s 0x%x\n", "p_type", phdr.p_type); |
printf(" %-20s 0x%jx\n", "p_offset", phdr.p_offset); |
printf(" %-20s 0x%jx\n", "p_vaddr", phdr.p_vaddr); |
printf(" %-20s 0x%jx\n", "p_paddr", phdr.p_paddr); |
printf(" %-20s 0x%jx\n", "p_filesz", phdr.p_filesz); |
printf(" %-20s 0x%jx\n", "p_memsz", phdr.p_memsz); |
printf(" %-20s 0x%x [", "p_flags", phdr.p_flags); |
|
if (phdr.p_flags & PF_X) printf(" Execute"); |
if (phdr.p_flags & PF_R) printf(" Read"); |
if (phdr.p_flags & PF_W) printf(" Write"); |
printf("]\n"); |
printf(" %-20s 0x%jx\n", "p_align", phdr.p_align); |
} |
|
total_octets += phdr.p_memsz; |
} |
|
char *d = (char *)malloc(total_octets + sizeof(SECTION)+sizeof(SECTION *)); |
memset(d, 0, total_octets); |
|
SECTION **r = sections = (SECTION **)d; |
current_offset = (n+1)*sizeof(SECTION *); |
current_section = 0; |
|
for(i=0; i<(int)n; i++) { |
r[i] = (SECTION *)(&d[current_offset]); |
|
if (gelf_getphdr(e, i, &phdr) != &phdr) { |
fprintf(stderr, "getphdr() failed: %s\n", elf_errmsg(-1)); |
exit(EXIT_FAILURE); |
} |
|
if (dbg) { |
printf(" %-20s 0x%jx\n", "p_offset", phdr.p_offset); |
printf(" %-20s 0x%jx\n", "p_vaddr", phdr.p_vaddr); |
printf(" %-20s 0x%jx\n", "p_paddr", phdr.p_paddr); |
printf(" %-20s 0x%jx\n", "p_filesz", phdr.p_filesz); |
printf(" %-20s 0x%jx\n", "p_memsz", phdr.p_memsz); |
printf(" %-20s 0x%x [", "p_flags", phdr.p_flags); |
|
if (phdr.p_flags & PF_X) printf(" Execute"); |
if (phdr.p_flags & PF_R) printf(" Read"); |
if (phdr.p_flags & PF_W) printf(" Write"); |
printf("]\n"); |
|
printf(" %-20s 0x%jx\n", "p_align", phdr.p_align); |
} |
|
current_section++; |
|
r[i]->m_start = phdr.p_paddr; |
r[i]->m_len = phdr.p_filesz/ sizeof(FPGA::BUSW); |
|
current_offset += phdr.p_memsz + sizeof(SECTION); |
|
// Now, let's read in our section ... |
if (lseek(fd, phdr.p_offset, SEEK_SET) < 0) { |
fprintf(stderr, "Could not seek to file position %08lx\n", phdr.p_offset); |
perror("O/S Err:"); |
exit(EXIT_FAILURE); |
} if (phdr.p_filesz > phdr.p_memsz) |
phdr.p_filesz = 0; |
if (read(fd, r[i]->m_data, phdr.p_filesz) != (int)phdr.p_filesz) { |
fprintf(stderr, "Didnt read entire section\n"); |
perror("O/S Err:"); |
exit(EXIT_FAILURE); |
} |
|
// Next, we need to byte swap it from big to little endian |
for(unsigned j=0; j<r[i]->m_len; j++) |
r[i]->m_data[j] = byteswap(r[i]->m_data[j]); |
|
if (dbg) for(unsigned j=0; j<r[i]->m_len; j++) |
fprintf(stderr, "ADR[%04x] = %08x\n", r[i]->m_start+j, |
r[i]->m_data[j]); |
} |
|
r[i] = (SECTION *)(&d[current_offset]); |
r[current_section]->m_start = 0; |
r[current_section]->m_len = 0; |
|
elf_end(e); |
close(fd); |
} |
#endif |
|
void usage(void) { |
printf("USAGE: zipload [-hr] <zip-program-file>\n"); |
printf("\n" |
"\t-h\tDisplay this usage statement\n"); |
printf( |
"\t-r\tStart the ZipCPU running from the address in the program file\n"); |
} |
|
int main(int argc, char **argv) { |
int skp=0; |
bool start_when_finished = false; |
unsigned entry = 0; |
FLASHDRVR *flash = NULL; |
const char *bitfile = NULL, *altbitfile = NULL; |
|
if (argc < 2) { |
usage(); |
exit(EXIT_SUCCESS); |
} |
|
skp=1; |
for(int argn=0; argn<argc-skp; argn++) { |
if (argv[argn+skp][0] == '-') { |
switch(argv[argn+skp][1]) { |
case 'h': |
usage(); |
exit(EXIT_SUCCESS); |
break; |
case 'r': |
start_when_finished = true; |
break; |
default: |
fprintf(stderr, "Unknown option, -%c\n\n", |
argv[argn+skp][0]); |
usage(); |
exit(EXIT_FAILURE); |
break; |
} skp++; argn--; |
} else { |
// Anything here must be the program to load. |
argv[argn] = argv[argn+skp]; |
} |
} argc -= skp; |
|
|
if (argc == 0) { |
printf("No executable file given!\n\n"); |
usage(); |
exit(EXIT_FAILURE); |
} if (access(argv[0],R_OK)!=0) { |
// If there's no code file, or the code file cannot be opened |
fprintf(stderr, "Cannot open executable, %s\n", argv[0]); |
exit(EXIT_FAILURE); |
} |
|
const char *codef = (argc>0)?argv[0]:NULL; |
DEVBUS::BUSW *fbuf = new DEVBUS::BUSW[FLASHWORDS]; |
|
// Set the flash buffer to all ones |
memset(fbuf, -1, FLASHWORDS*sizeof(fbuf[0])); |
|
m_fpga = FPGAOPEN(m_fpga); |
|
// Make certain we can talk to the FPGA |
try { |
unsigned v = m_fpga->readio(R_VERSION); |
if (v < 0x20161000) { |
fprintf(stderr, "Could not communicate with board (invalid version)\n"); |
exit(EXIT_FAILURE); |
} |
} catch(BUSERR b) { |
fprintf(stderr, "Could not communicate with board (BUSERR when reading VERSION)\n"); |
exit(EXIT_FAILURE); |
} |
|
// Halt the CPU |
try { |
unsigned v; |
printf("Halting the CPU\n"); |
m_fpga->writeio(R_ZIPCTRL, CPU_HALT|CPU_RESET); |
} catch(BUSERR b) { |
fprintf(stderr, "Could not halt the CPU (BUSERR)\n"); |
exit(EXIT_FAILURE); |
} |
|
flash = new FLASHDRVR(m_fpga); |
|
if (codef) try { |
SECTION **secpp = NULL, *secp; |
|
if(iself(codef)) { |
// zip-readelf will help with both of these ... |
elfread(codef, entry, secpp); |
} else { |
fprintf(stderr, "ERR: %s is not in ELF format\n", codef); |
exit(EXIT_FAILURE); |
} |
|
printf("Loading: %s\n", codef); |
// assert(secpp[1]->m_len = 0); |
for(int i=0; secpp[i]->m_len; i++) { |
bool valid = false; |
secp= secpp[i]; |
|
// Make sure our section is either within block RAM |
if ((secp->m_start >= MEMBASE) |
&&(secp->m_start+secp->m_len |
<= MEMBASE+MEMWORDS)) |
valid = true; |
|
// Flash |
if ((secp->m_start >= RESET_ADDRESS) |
&&(secp->m_start+secp->m_len |
<= EQSPIFLASH+FLASHWORDS)) |
valid = true; |
|
// Or SDRAM |
if ((secp->m_start >= RAMBASE) |
&&(secp->m_start+secp->m_len |
<= RAMBASE+RAMWORDS)) |
valid = true; |
if (!valid) { |
fprintf(stderr, "No such memory on board: 0x%08x - %08x\n", |
secp->m_start, secp->m_start+secp->m_len); |
exit(EXIT_FAILURE); |
} |
} |
|
unsigned startaddr = RESET_ADDRESS, codelen = 0; |
for(int i=0; secpp[i]->m_len; i++) { |
secp = secpp[i]; |
if ( ((secp->m_start >= RAMBASE) |
&&(secp->m_start+secp->m_len |
<= RAMBASE+RAMWORDS)) |
||((secp->m_start >= MEMBASE) |
&&(secp->m_start+secp->m_len |
<= MEMBASE+MEMWORDS)) ) { |
for(int i=0; (unsigned)i<secp->m_len; i++) { |
m_fpga->writei(secp->m_start, |
secp->m_len, |
secp->m_data); |
} |
} else { |
if (secp->m_start < startaddr) { |
codelen += (startaddr-secp->m_start); |
startaddr = secp->m_start; |
} if (secp->m_start+secp->m_len > startaddr+codelen) { |
codelen = secp->m_start+secp->m_len-startaddr; |
} memcpy(&fbuf[secp->m_start-EQSPIFLASH], |
secp->m_data, |
secp->m_len*sizeof(FPGA::BUSW)); |
} |
} |
if ((flash)&&(!flash->write(startaddr, codelen, &fbuf[startaddr-EQSPIFLASH], true))) { |
fprintf(stderr, "ERR: Could not write program to flash\n"); |
exit(EXIT_FAILURE); |
} else if (!flash) |
printf("flash->write(%08x, %d, ... );\n", startaddr, |
codelen); |
if (m_fpga) m_fpga->readio(R_VERSION); // Check for bus errors |
|
// Now ... how shall we start this CPU? |
if (start_when_finished) { |
printf("Clearing the CPUs registers\n"); |
for(int i=0; i<32; i++) { |
m_fpga->writeio(R_ZIPCTRL, CPU_HALT|i); |
if (i == CPU_sPC) |
m_fpga->writeio(R_ZIPDATA, entry); |
else |
m_fpga->writeio(R_ZIPDATA, 0); |
} |
|
m_fpga->writeio(R_CPUSCOPE, 25); |
printf("Starting the CPU\n"); |
m_fpga->writeio(R_ZIPCTRL, CPU_HALT|CPU_CLRCACHE|CPU_RESET); |
m_fpga->writeio(R_ZIPCTRL, CPU_GO|CPU_sPC); |
} else { |
printf("The CPU should be fully loaded, you may now\n"); |
printf("start it (from reset/reboot) with:\n"); |
printf("> wbregs cpu 0x40\n"); |
printf("\n"); |
} |
} catch(BUSERR a) { |
fprintf(stderr, "ARTY-BUS error: %08x\n", a.addr); |
exit(-2); |
} |
|
printf("CPU Status is: %08x\n", m_fpga->readio(R_ZIPCTRL)); |
if (m_fpga) delete m_fpga; |
|
return EXIT_SUCCESS; |
} |
|
/zipstate.cpp
0,0 → 1,143
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: zipstate.cpp |
// |
// Project: OpenArty, an entirely open SoC based upon the Arty platform |
// |
// Purpose: To get a quick (understandable) peek at what the ZipCPU |
// is up to without stopping the CPU. This is basically |
// identical to a "wbregs cpu" command, save that the bit fields of the |
// result are broken out into something more human readable. |
// |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015-2016, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
// by the Free Software Foundation, either version 3 of the License, or (at |
// your option) any later version. |
// |
// This program is distributed in the hope that it will be useful, but WITHOUT |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <strings.h> |
#include <ctype.h> |
#include <string.h> |
#include <signal.h> |
#include <assert.h> |
|
#include "port.h" |
#include "llcomms.h" |
#include "regdefs.h" |
|
FPGA *m_fpga; |
void closeup(int v) { |
m_fpga->kill(); |
exit(0); |
} |
|
unsigned int cmd_read(FPGA *fpga, int r) { |
const unsigned int MAXERR = 1000; |
unsigned int errcount = 0; |
unsigned int s; |
|
fpga->writeio(R_ZIPCTRL, CPU_HALT|(r&0x03f)); |
while((((s = fpga->readio(R_ZIPCTRL))&CPU_STALL)== 0)&&(errcount<MAXERR)) |
errcount++; |
if (errcount >= MAXERR) { |
printf("ERR: errcount(%d) >= MAXERR on cmd_read(a=%02x)\n", |
errcount, r); |
printf("ZIPCTRL = 0x%08x", s); |
if ((s & 0x0200)==0) printf(" STALL"); |
if (s & 0x0400) printf(" HALTED"); |
if ((s & 0x03000)==0x01000) |
printf(" SW-HALT"); |
else { |
if (s & 0x01000) printf(" SLEEPING"); |
if (s & 0x02000) printf(" GIE(UsrMode)"); |
} printf("\n"); |
exit(EXIT_FAILURE); |
} return fpga->readio(R_ZIPDATA); |
} |
|
void usage(void) { |
printf("USAGE: zipstate\n"); |
} |
|
int main(int argc, char **argv) { |
int skp=0, port = FPGAPORT; |
bool long_state = false; |
unsigned int v; |
|
skp=1; |
for(int argn=0; argn<argc-skp; argn++) { |
if (argv[argn+skp][0] == '-') { |
if (argv[argn+skp][1] == 'l') |
long_state = true; |
skp++; argn--; |
} else |
argv[argn] = argv[argn+skp]; |
} argc -= skp; |
|
FPGAOPEN(m_fpga); |
|
if (!long_state) { |
v = m_fpga->readio(R_ZIPCTRL); |
|
printf("0x%08x: ", v); |
if (v & 0x0080) printf("PINT "); |
// if (v & 0x0100) printf("STEP "); // self resetting |
if((v & 0x00200)==0) printf("STALL "); |
if (v & 0x00400) printf("HALTED "); |
if((v & 0x03000)==0x01000) { |
printf("SW-HALT"); |
} else { |
if (v & 0x01000) printf("SLEEPING "); |
if (v & 0x02000) printf("GIE(UsrMode) "); |
} |
// if (v & 0x0800) printf("CLR-CACHE "); |
printf("\n"); |
} else { |
printf("Reading the long-state ...\n"); |
for(int i=0; i<14; i++) { |
printf("sR%-2d: 0x%08x ", i, cmd_read(m_fpga, i)); |
if ((i&3)==3) |
printf("\n"); |
} printf("sCC : 0x%08x ", cmd_read(m_fpga, 14)); |
printf("sPC : 0x%08x ", cmd_read(m_fpga, 15)); |
printf("\n\n"); |
|
for(int i=0; i<14; i++) { |
printf("uR%-2d: 0x%08x ", i, cmd_read(m_fpga, i+16)); |
if ((i&3)==3) |
printf("\n"); |
} printf("uCC : 0x%08x ", cmd_read(m_fpga, 14+16)); |
printf("uPC : 0x%08x ", cmd_read(m_fpga, 15+16)); |
printf("\n\n"); |
} |
|
delete m_fpga; |
} |
|
/zprog.sh
0,0 → 1,99
#!/bin/bash |
################################################################################ |
## |
## Filename: zprog.sh |
## |
## Project: OpenArty, an entirely open SoC based upon the Arty platform |
## |
## Purpose: To install a new program into the Arty, using the main |
## programming slot (slot 0). |
## |
## Creator: Dan Gisselquist, Ph.D. |
## Gisselquist Technology, LLC |
## |
################################################################################ |
## |
## Copyright (C) 2015-2016, Gisselquist Technology, LLC |
## |
## This program is free software (firmware): you can redistribute it and/or |
## modify it under the terms of the GNU General Public License as published |
## by the Free Software Foundation, either version 3 of the License, or (at |
## your option) any later version. |
## |
## This program is distributed in the hope that it will be useful, but WITHOUT |
## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
## for more details. |
## |
## You should have received a copy of the GNU General Public License along |
## with this program. (It's in the $(ROOT)/doc directory, run make with no |
## target there if the PDF file isn't present.) If not, see |
## <http://www.gnu.org/licenses/> for a copy. |
## |
## License: GPL, v3, as defined and found on www.gnu.org, |
## http://www.gnu.org/licenses/gpl.html |
## |
## |
################################################################################ |
## |
## |
export PATH=$PATH:. |
export BINFILE=../../xilinx/openarty.runs/impl_1/toplevel.bin |
|
WBREGS=wbregs |
WBPROG=wbprogram |
|
# |
# $WBREGS qspiv 0x8b # Accomplished by the flash driver |
# |
$WBREGS stopwatch 2 # Clear and stop the stopwatch |
$WBREGS stopwatch 1 # Start the stopwatch |
echo $WBPROG @0x0400000 $BINFILE |
$WBPROG @0x0400000 $BINFILE |
$WBREGS stopwatch 0 # Stop the stopwatch, we are done |
$WBREGS stopwatch # Print out the time on the stopwatch |
|
$WBREGS wbstar 0 |
$WBREGS fpgacmd 15 |
sleep 1 |
|
|
RED=0x00ff0000 |
GREEN=0x0000ff00 |
WHITE=0x000f0f0f |
BLACK=0x00000000 |
DIMGREEN=0x00001f00 |
|
$WBREGS led 0x0f |
$WBREGS clrled0 $RED |
$WBREGS clrled1 $RED |
$WBREGS clrled2 $RED |
$WBREGS clrled3 $RED |
|
sleep 1 |
$WBREGS clrled0 $GREEN |
$WBREGS led 0x10 |
sleep 1 |
$WBREGS clrled1 $GREEN |
$WBREGS clrled0 $DIMGREEN |
$WBREGS led 0x20 |
sleep 1 |
$WBREGS clrled2 $GREEN |
$WBREGS clrled1 $DIMGREEN |
$WBREGS led 0x40 |
|
if [[ -x ./wbsettime ]]; then |
./wbsettime |
fi |
|
$WBREGS clrled3 $GREEN |
$WBREGS clrled2 $DIMGREEN |
$WBREGS led 0x80 |
sleep 1 |
$WBREGS clrled0 $WHITE |
$WBREGS clrled1 $BLACK |
$WBREGS clrled2 $BLACK |
$WBREGS clrled3 $WHITE |
$WBREGS led 0x00 |
|
|
zprog.sh
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property