URL
https://opencores.org/ocsvn/tv80/tv80/trunk
Subversion Repositories tv80
Compare Revisions
- This comparison shows the changes necessary to convert path
/tv80/trunk
- from Rev 93 to Rev 94
- ↔ Reverse comparison
Rev 93 → Rev 94
/sc_env/sc_env_top.cpp
1,7 → 1,9
#include "systemc.h" |
#include "systemperl.h" |
#include "env_memory.h" |
#include "tv_responder.h" |
#include "Vtv80s.h" |
#include "SpTraceVcd.h" |
|
int sc_main(int argc, char *argv[]) |
{ |
53,6 → 55,7
env_memory0.rd_n (rd_n); |
env_memory0.wr_n (wr_n); |
env_memory0.addr (addr); |
env_memory0.reset_n (reset_n); |
|
tv_responder tv_resp0("tv_resp0"); |
tv_resp0.clk (clk); |
73,6 → 76,7
tv_resp0.halt_n (halt_n); |
|
// create dumpfile |
/* |
sc_trace_file *trace_file; |
trace_file = sc_create_vcd_trace_file("sc_tv80_env"); |
sc_trace (trace_file, clk, "clk"); |
91,10 → 95,28
sc_trace (trace_file, di, "di"); |
sc_trace (trace_file, dout, "dout"); |
sc_trace (trace_file, addr, "addr"); |
|
// Start Verilator traces |
Verilated::traceEverOn(true); |
SpTraceFile *tfp = new SpTraceFile; |
tv80s.trace (tfp, 99); |
tfp->open ("tv80.vcd"); |
*/ |
|
// check for command line argument |
if (argc > 1) { |
env_memory0.load_ihex (argv[1]); |
} |
|
// set reset to 0 before sim start |
reset_n.write (0); |
|
sc_start(8000); |
sc_start(); |
/* |
sc_close_vcd_trace_file (trace_file); |
tfp->close(); |
*/ |
|
|
return 0; |
} |
/sc_env/tv_responder.h
5,6 → 5,24
|
SC_MODULE(tv_responder) |
{ |
private: |
char str_buf [256]; |
int buf_ptr; |
|
int timeout_ctl; |
int cur_timeout; |
int max_timeout; |
|
int int_countdown; |
int nmi_countdown; |
uint8_t checksum; |
int ior_value; // increment-on-read value |
int nmi_trigger; // trigger nmi when IR = this value |
|
int reset_time; |
bool last_iowrite; |
|
public: |
sc_in<bool> clk; |
|
sc_out<bool> reset_n; |
26,8 → 44,18
void event(); |
|
SC_CTOR(tv_responder) { |
SC_THREAD(event); |
SC_METHOD(event); |
sensitive << clk.pos(); |
|
buf_ptr = 0; |
cur_timeout = 0; |
max_timeout = 10000; |
timeout_ctl = 1; |
int_countdown = 0; |
nmi_countdown = 0; |
nmi_trigger = 0; |
reset_time = 16; |
last_iowrite = false; |
} |
}; |
|
/sc_env/env_memory.cpp
6,31 → 6,43
int lcl_cs; |
int ad; |
|
// ignore activity during reset |
if (!reset_n) |
return; |
if (!mreq_n && !wr_n && (addr < AM_DEPTH)) { |
ad = (int) addr; |
memory[ad] = (unsigned char) wr_data.read(); |
#ifdef DEBUG |
printf ("Wrote %x to address %x\n", (int) wr_data.read(), ad); |
//printf ("MEM WR %04x=%02x\n", ad, (int) wr_data.read()); |
#endif |
} else if (!mreq_n && !rd_n && (addr < AM_DEPTH)) { |
} |
|
// async read output |
if (addr < AM_DEPTH) { |
ad = (int) addr; |
rd_data.write ( (unsigned int) memory[ad] ); |
#ifdef DEBUG |
printf ("Read %x from address %x\n", memory[ad], ad); |
#endif |
} |
} |
|
void inline readline(FILE *fh, char *buf) |
int inline readline(FILE *fh, char *buf) |
{ |
int c = 1; |
int c = 1, cnt = 0; |
|
if (feof(fh)) { |
*buf = (char) 0; |
return 0; |
} |
while (c) { |
c = fread (buf, 1, 1, fh); |
if (c && (*buf == '\n')) |
cnt++; |
if (c && (*buf == '\n')) { |
buf++; |
*buf = (char) 0; |
c = 0; |
} |
else buf++; |
} |
return cnt; |
} |
|
/* |
55,20 → 67,28
{ |
FILE *fh; |
char line[80]; |
char *lp; |
int rlen, addr, rtyp; |
char *lp; |
int rlen, addr, rtyp, databyte; |
int rv; |
int dcount = 0; |
|
fh = fopen (filename, "r"); |
|
readline (fh, line); |
while (strlen(line) > 0) { |
printf ("DEBUG: strlen(line)=%d\n", strlen(line)); |
sscanf (line, "%2x%2x%2x", &rlen, &addr, &rtyp); |
printf ("DEBUG: rlen=%d addr=%d rtyp=%d\n", rlen, addr, rtyp); |
lp = line + 6; |
for (int c=0; c<rlen; c++) { |
} |
} |
rv = readline (fh, line); |
while (strlen(line) > 0) { |
//printf ("DEBUG: strlen(line)=%d rv=%d line=%s\n", strlen(line), rv, line); |
sscanf (line, ":%02x%04x%02x", &rlen, &addr, &rtyp); |
//printf ("DEBUG: rlen=%d addr=%d rtyp=%d\n", rlen, addr, rtyp); |
lp = line + 9; |
for (int c=0; c<rlen; c++) { |
sscanf (lp, "%02x", &databyte); |
lp += 2; |
//printf ("DEBUG: loaded mem[%04x]=%02x\n", addr+c, databyte); |
memory[addr+c] = databyte; dcount++; |
} |
rv = readline (fh, line); |
} |
|
fclose (fh); |
printf ("ENVMEM : Read %d bytes from %s\n", dcount, filename); |
} |
/sc_env/env_memory.h
14,6 → 14,7
sc_in<bool> wr_n; |
sc_in<uint32_t> addr; |
sc_out<uint32_t> rd_data; |
sc_in<bool> reset_n; |
|
unsigned char *memory; |
|
24,7 → 25,7
SC_CTOR(env_memory) { |
memory = new unsigned char[AM_DEPTH]; |
SC_METHOD(event); |
sensitive << clk.pos(); |
sensitive << clk.pos() << addr; |
} |
}; |
|
/sc_env/tv_responder.cpp
3,16 → 3,166
void tv_responder::event () |
{ |
// init |
reset_n = 0; |
//reset_n = 0; |
/* |
wait_n = 1; |
int_n = 1; |
nmi_n = 1; |
busrq_n = 1; |
di_resp = 0; |
*/ |
|
for (int c=0; c<10; c++) |
wait(); |
reset_n = 1; |
wait(); |
printf ("Initialization complete.\n"); |
if (reset_time > 0) { |
reset_n = 0; |
wait_n = 1; |
int_n = 1; |
nmi_n = 1; |
busrq_n = 1; |
di_resp = 0; |
reset_time--; |
if (reset_time == 0) |
printf ("Initialization complete.\n"); |
return; |
} else { |
if (reset_time == 0) { |
reset_n = 1; |
reset_time--; |
} |
} |
|
|
if (!iorq_n & !rd_n) |
{ |
switch (addr) { |
case (0x82) : di_resp = timeout_ctl; break; |
case(0x83) : di_resp = max_timeout & 0xff; break; |
case(0x84) : di_resp = max_timeout >> 8; break; |
|
case(0x90) : di_resp = int_countdown; break; |
case(0x91) : di_resp = checksum; break; |
case(0x93) : di_resp = ior_value; break; |
case(0x94) : di_resp = rand(); break; |
case(0x95) : di_resp = nmi_countdown; break; |
case(0xA0) : di_resp = nmi_trigger; break; |
default : di_resp = 0; |
} |
} // if (!iorq_n & !rd_n) |
|
// wire wr_stb; |
// reg last_iowrite; |
|
// assign wr_stb = (!iorq_n & !wr_n); |
|
// always @(posedge clk) |
// begin |
//last_iowrite <= #1 wr_stb; |
//if (!iorq_n && !wr_n) |
// printf ("DEBUG: I/O Write detected addr=%02x\n", 0xff & (int) addr.read()); |
|
if (!iorq_n && !wr_n && !last_iowrite) { |
int l_dout, l_addr; |
|
l_addr = addr.read(); |
l_dout = dout.read(); |
|
last_iowrite = true; |
switch ( l_addr & 0xff) { |
case(0x80) : |
// dump control deprecated |
if (l_dout == 1) { |
printf ("%8d: --- TEST PASSED ---\n", 0); |
sc_stop(); |
} else if (l_dout == 2) { |
printf ("%8d: !!! TEST FAILED !!!\n", 0); |
sc_stop(); |
} |
break; |
|
case(0x81) : |
|
//printf ("%s: DEBUG : Detected write of character %x\n", sc_time_stamp().to_string(), l_dout); |
//cout << sc_time_stamp().to_string() << "DEBUG : Detected write of character " << l_dout << endl; |
if (l_dout == 0x0A) { |
//printf ("%8d: PROGRAM : ", sc_simulation_time()); |
cout << sc_time_stamp() << ": PROGRAM : "; |
|
for (int i=0; i<buf_ptr; i=i+1) |
//printf ("%s", str_buf[i]); |
cout << str_buf[i]; |
|
//printf ("\n"); |
cout << endl; |
buf_ptr = 0; |
} else { |
str_buf[buf_ptr] = (char) (l_dout & 0xff); |
buf_ptr = buf_ptr + 1; |
} |
break; |
|
case(0x82) : |
timeout_ctl = l_dout; |
break; |
|
case(0x83) : |
max_timeout = l_dout | (max_timeout & 0xFF00); |
break; |
|
case(0x84) : |
max_timeout = l_dout << 8 | (max_timeout & 0x00FF); |
break; |
|
case(0x90) : int_countdown = dout; break; |
case(0x91) : checksum = dout; break; |
case(0x92) : checksum = checksum + dout; break; |
case(0x93) : ior_value = dout; break; |
case(0x95) : nmi_countdown = dout; break; |
case(0xA0) : nmi_trigger = dout; break; |
} |
} else if (iorq_n) |
last_iowrite = false; |
|
if (timeout_ctl & 0x2) |
cur_timeout = 0; |
else if (timeout_ctl & 0x1) |
cur_timeout = cur_timeout + 1; |
|
if (cur_timeout >= max_timeout) { |
printf ("%8d: ERROR : Reached timeout %d cycles\n", 0, max_timeout); |
//tb_top.test_fail; |
sc_stop(); |
} |
|
if (int_countdown == 0) { |
int_n = 1; |
} else if (int_countdown == 1) |
int_n = 0; |
else if (int_countdown > 1) { |
int_countdown = int_countdown - 1; |
int_n = 1; |
} |
|
// when nmi countdown reaches 1, an NMI will be issued. |
// to clear the interrupt, write nmi_countdown to 0. |
if ((nmi_countdown == 0) && (nmi_trigger == 0)) |
nmi_n = 1; |
else if (nmi_countdown == 1) |
nmi_n = 0; |
else if (nmi_countdown > 1) { |
nmi_countdown = nmi_countdown - 1; |
nmi_n = 1; |
} |
|
// when IR equals the target instruction, an NMI will be |
// issued. To clear the interrupt, write nmi_trigger to |
// zero. |
/* can't do this in systemc |
if (nmi_trigger != 0) { |
if (nmi_trigger === tb_top.tv80s_inst.i_tv80_core.IR[7:0]) |
begin |
tb_top.nmi_n <= #80 0; |
tb_top.nmi_n <= #160 1; |
end |
} else if (nmi_countdown == 0) |
nmi_n = 1; |
*/ |
} |
/sc_env/Makefile
1,13 → 1,17
SYSTEMC=/opt/systemc |
VERILATOR_ROOT = /opt/verilator/share/verilator |
VERIDIR=../obj_dir |
INCLUDES=-I$(SYSTEMC)/include -I$(VERIDIR) -I$(VERILATOR_ROOT)/include |
INCLUDES=-I$(SYSTEMC)/include -I$(VERIDIR) -I$(VERILATOR_ROOT)/include -I$(SYSTEMPERL) |
LINKOPT=-L$(SYSTEMC)/lib-linux64 -lsystemc -lm |
DEFINES=-DDEBUG |
OBJFILES=sc_env_top.o env_memory.o tv_responder.o \ |
$(VERIDIR)/Vtv80s.o $(VERIDIR)/Vtv80s__Syms.o verilated.o |
$(VERIDIR)/Vtv80s.o $(VERIDIR)/Vtv80s__Syms.o \ |
$(VERIDIR)/Vtv80s__Trace.o \ |
$(VERIDIR)/Vtv80s__Trace__Slow.o \ |
verilated.o Sp.o |
OPT_FAST=-O2 |
|
CXX=g++ -g $(INCLUDES) $(DEFINES) |
CXX=g++ -g $(OPT_FAST) $(INCLUDES) $(DEFINES) |
|
all: sc_env_top |
|
21,11 → 25,23
$(CXX) -c $^ |
|
$(VERIDIR)/Vtv80s.o: |
(cd $(VERIDIR); make -f Vtv80s.mk Vtv80s.o) |
make OPT_FAST="$(OPT_FAST)" -f $(VERIDIR)/Vtv80s.mk -C $(VERIDIR) Vtv80s.o |
#(cd $(VERIDIR); make -f Vtv80s.mk Vtv80s.o) |
|
$(VERIDIR)/Vtv80s__Syms.o: |
(cd $(VERIDIR); make -f Vtv80s.mk Vtv80s__Syms.o) |
make OPT_FAST="$(OPT_FAST)" -f $(VERIDIR)/Vtv80s.mk -C $(VERIDIR) Vtv80s__Syms.o |
#(cd $(VERIDIR); make -f Vtv80s.mk Vtv80s__Syms.o) |
|
$(VERIDIR)/Vtv80s__Trace.o: |
(cd $(VERIDIR); make -f Vtv80s.mk Vtv80s__Trace.o) |
|
$(VERIDIR)/Vtv80s__Trace__Slow.o: |
(cd $(VERIDIR); make -f Vtv80s.mk Vtv80s__Trace__Slow.o) |
|
Sp.o: $(SYSTEMPERL)/Sp.cpp |
$(CXX) -I$(SYSTEMPERL) -c $^ |
|
clean: |
rm -f *.o |
rm -f ../obj_dir/*.o |
|