URL
https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk
Subversion Repositories openrisc_me
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/trunk/orpsocv2
- from Rev 46 to Rev 49
- ↔ Reverse comparison
Rev 46 → Rev 49
/bench/sysc/include/Or1200MonitorSC.h
51,23 → 51,30
|
// Constructor |
Or1200MonitorSC (sc_core::sc_module_name name, |
OrpsocAccess *_accessor); |
OrpsocAccess *_accessor, |
int argc, |
char *argv[]); |
|
// Method to check instructions |
void checkInstruction(); |
|
// Methods to setup and output state of processor to a file |
void init_displayState(int argc,char *argv[]); |
void displayState(); |
|
// Function to calculate performance of the sim |
void perfSummary(); |
|
// Print out the command-line switches for this module's options |
void printSwitches(); |
|
// Print out the usage for each option |
void printUsage(); |
|
// The ports |
sc_in<bool> clk; |
|
private: |
|
// Function to calculate performance of the sim |
void perfSummary(); |
|
// Special NOP instructions |
static const uint32_t NOP_NOP = 0x15000000; //!< Normal nop instruction |
static const uint32_t NOP_EXIT = 0x15000001; //!< End of simulation |
/bench/sysc/include/TraceSC.h
33,6 → 33,7
|
#include "Vorpsoc_top.h" |
|
|
#if VM_TRACE |
#include <SpTraceVcdC.h> |
#endif |
57,8 → 58,13
// Method to drive the trace |
void driveTrace(); |
|
// VCD dump controling vars |
int dump_start_delay, dump_stop_set; |
int dumping_now; |
sc_time dump_start,dump_stop; |
|
/* The port */ |
sc_in<bool> clk; |
//sc_in<bool> clk; |
|
private: |
|
65,6 → 71,7
//! The ORPSoC module we are tracing |
Vorpsoc_top *traceTarget; |
|
|
#if VM_TRACE |
//! The System Perl Trace file |
SpTraceVcdCFile *spTraceFile; |
/bench/sysc/include/OrpsocAccess.h
55,7 → 55,9
// Accessor functions |
bool getWbFreeze (); |
uint32_t getWbInsn (); |
uint32_t getIdInsn (); |
uint32_t getWbPC (); |
uint32_t getIdPC (); |
bool getExceptFlushpipe (); |
bool getExDslot (); |
// Get a specific GPR from the register file |
/bench/sysc/src/Or1200MonitorSC.cpp
45,25 → 45,96
//! @param[in] accessor Accessor class for this Verilated ORPSoC model |
|
Or1200MonitorSC::Or1200MonitorSC (sc_core::sc_module_name name, |
OrpsocAccess *_accessor) : |
OrpsocAccess *_accessor, |
int argc, |
char *argv[]) : |
sc_module (name), |
accessor (_accessor) |
{ |
SC_METHOD (checkInstruction); |
|
// If not -log option, then don't log |
|
string logfileDefault("vlt-executed.log"); |
string logfileNameString; |
|
exit_perf_summary_enabled = 1; // Simulation exit performance summary is |
// on by default. Turn off with "-q" on the cmd line |
|
// Parse the command line options |
int cmdline_name_found=0; |
if (argc > 1) |
{ |
// Search through the command line parameters for the "-log" option |
for(int i=1; i < argc; i++) |
{ |
if ((strcmp(argv[i], "-l")==0) || |
(strcmp(argv[i], "--log")==0)) |
{ |
logfileNameString = (argv[i+1]); |
cmdline_name_found=1; |
break; |
} |
} |
// Search through the command line parameters for the "-q","--no-perf-summary" option |
for(int i=1; i < argc; i++) |
{ |
if ((strcmp(argv[i], "-q")==0) || |
(strcmp(argv[i], "--quiet")==0)) |
{ |
exit_perf_summary_enabled = 0; |
break; |
} |
} |
} |
|
|
|
if(cmdline_name_found==1) // No -log option specified so don't turn on logging |
{ |
|
logging_enabled = 0; // Default is logging disabled |
statusFile.open(logfileNameString.c_str(), ios::out ); // open file to write to it |
|
if(statusFile.is_open()) |
{ |
// If we could open the file then turn on logging |
logging_enabled = 1; |
cout << "* Processor execution logged to file: " << logfileNameString << endl; |
} |
|
} |
|
|
SC_METHOD (displayState); |
sensitive << clk.pos(); |
dont_initialize(); |
start = clock(); |
|
SC_METHOD (displayState); |
logging_enabled = 0; // Default is logging disabled |
exit_perf_summary_enabled = 1; // Simulation exit performance summary is on by default. Turn off with "-q" on the cmd line |
|
// checkInstruction monitors the bus for special NOP instructionsl |
SC_METHOD (checkInstruction); |
sensitive << clk.pos(); |
dont_initialize(); |
|
start = clock(); |
|
|
|
|
} // Or1200MonitorSC () |
|
//! Print command line switches for the options of this module |
void |
Or1200MonitorSC::printSwitches() |
{ |
printf(" [-l <file>] [-q]"); |
} |
|
//! Print usage for the options of this module |
void |
Or1200MonitorSC::printUsage() |
{ |
printf(" -l, --log\t\tLog processor execution to file\n"); |
printf(" -q, --quiet\t\tDisable the performance summary at end of simulation\n"); |
} |
|
//! Method to handle special instrutions |
|
//! These are l.nop instructions with constant values. At present the |
73,7 → 144,7
//! - l.nop 2 Report the value in R3 |
//! - l.nop 3 Printf the string with the arguments in R3, etc |
//! - l.nop 4 Print a character |
|
extern int SIM_RUNNING; |
void |
Or1200MonitorSC::checkInstruction() |
{ |
91,8 → 162,9
ts = sc_time_stamp().to_seconds() * 1000000000.0; |
std::cout << std::fixed << std::setprecision (2) << ts; |
std::cout << " ns: Exiting (" << r3 << ")" << std::endl; |
if (exit_perf_summary_enabled) perfSummary(); |
perfSummary(); |
if (logging_enabled != 0) statusFile.close(); |
SIM_RUNNING=0; |
sc_stop(); |
break; |
|
121,65 → 193,12
|
} // checkInstruction() |
|
//! Method to setup the files for outputting the state of the processor |
|
//! This function will setup the output file, if enabled. |
|
void |
Or1200MonitorSC::init_displayState(int argc, char *argv[]) |
{ |
|
string logfileDefault("vlt-executed.log"); |
string logfileNameString; |
|
// Parse the command line options |
int cmdline_name_found=0; |
if (argc > 1) |
{ |
// Search through the command line parameters for the "-log" option |
for(int i=1; i < argc; i++) |
{ |
if (strcmp(argv[i], "-log")==0) |
{ |
logfileNameString = (argv[i+1]); |
cmdline_name_found=1; |
break; |
} |
} |
// Search through the command line parameters for the "-q","--no-perf-summary" option |
for(int i=1; i < argc; i++) |
{ |
if ((strcmp(argv[i], "-q")==0)||(strcmp(argv[i], "--no-perf-summary")==0)) |
{ |
exit_perf_summary_enabled = 0; |
break; |
} |
} |
|
|
} |
|
if(cmdline_name_found==0) // No -log option specified so don't turn on logging |
return; |
|
statusFile.open(logfileNameString.c_str(), ios::out ); // open file to write to it |
|
if(statusFile.is_open()) |
{ |
// If we could open the file then turn on logging |
logging_enabled = 1; |
cout << "Processor execution logged to file: " << logfileNameString << endl; |
} |
|
return; |
|
} |
|
//! Method to output the state of the processor |
|
//! This function will output to a file, if enabled, the status of the processor |
//! For now, it's just the PPC and instruction. |
|
#define PRINT_REGS 0 |
void |
Or1200MonitorSC::displayState() |
{ |
198,10 → 217,10
{ |
// Print PC, instruction |
statusFile << "\nEXECUTED("<< std::setfill(' ') << std::setw(11) << dec << insn_count << "): " << std::setfill('0') << hex << std::setw(8) << accessor->getWbPC() << ": " << hex << accessor->getWbInsn() << endl; |
|
#if PRINT_REGS |
// Print general purpose register contents |
for (int i=0; i<32; i++) |
{ |
{ |
if ((i%4 == 0)&&(i>0)) statusFile << endl; |
statusFile << std::setfill('0'); |
statusFile << "GPR" << dec << std::setw(2) << i << ": " << hex << std::setw(8) << (uint32_t) accessor->getGpr(i) << " "; |
212,6 → 231,7
statusFile << "EPCR0: " << hex << std::setw(8) << (uint32_t) accessor->getSprEpcr() << " "; |
statusFile << "EEAR0: " << hex << std::setw(8) << (uint32_t) accessor->getSprEear() << " "; |
statusFile << "ESR0 : " << hex << std::setw(8) << (uint32_t) accessor->getSprEsr() << endl; |
#endif |
|
} |
|
223,18 → 243,22
void |
Or1200MonitorSC::perfSummary() |
{ |
double ts; |
ts = sc_time_stamp().to_seconds() * 1000000000.0; |
int cycles = ts / (BENCH_CLK_HALFPERIOD*2); // Number of clock cycles we had |
if (exit_perf_summary_enabled) |
{ |
double ts; |
ts = sc_time_stamp().to_seconds() * 1000000000.0; |
int cycles = ts / (BENCH_CLK_HALFPERIOD*2); // Number of clock cycles we had |
|
clock_t finish = clock(); |
double elapsed_time = (double(finish)-double(start))/CLOCKS_PER_SEC; |
// It took elapsed_time seconds to do insn_count instructions. Divide insn_count by the time to get instructions/second. |
double ips = (insn_count/elapsed_time); |
double mips = (insn_count/elapsed_time)/1000000; |
int hertz = (int) ((cycles/elapsed_time)/1000); |
std::cout << "* Or1200Monitor: simulated " << sc_time_stamp() << ",time elapsed: " << elapsed_time << " seconds" << endl; |
std::cout << "* Or1200Monitor: simulated " << dec << cycles << " clock cycles, executed at approx " << hertz << "kHz" << endl; |
std::cout << "* Or1200Monitor: simulated " << insn_count << " instructions, insn/sec. = " << ips << ", mips = " << mips << endl; |
} |
return; |
} // perfSummary |
|
clock_t finish = clock(); |
double elapsed_time = (double(finish)-double(start))/CLOCKS_PER_SEC; |
// It took elapsed_time seconds to do insn_count instructions. Divide insn_count by the time to get instructions/second. |
double ips = (insn_count/elapsed_time); |
double mips = (insn_count/elapsed_time)/1000000; |
std::cout << "Or1200Monitor: real time elapsed: " << elapsed_time << " seconds" << endl; |
std::cout << "Or1200Monitor: simulated " << dec << cycles << " clock cycles, executed " << insn_count << " instructions" << endl; |
std::cout << "Or1200Monitor: simulated insn/sec = " << ips << ", simulator mips = " << mips << endl; |
return; |
} // calculateMips() |
|
/bench/sysc/src/Modules.make
26,8 → 26,13
# Tools and flags |
ARFLAGS = rcs |
#CXXFLAGS += $(OPT_FAST) $(OPT_SLOW) $(OPT) $(PROF_FLAGS) |
|
ifdef VLT_CPPFLAGS |
CXXFLAGS += $(VLT_CPPFLAGS) |
endif |
|
CXX ?= g++ |
PROF_OPTS ?= -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer |
#PROF_OPTS ?= -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -O3 |
OPT_ALL ?= $(OPT_SLOW) $(OPT_FAST) $(OPT) |
|
# Sub-directories |
40,6 → 45,10
UartSC.o |
LIB = libmodules.a |
|
ifdef VLT_DEBUG |
CXXFLAGS += -g |
endif |
|
# ----------------------------------------------------------------------------- |
# Rule to make dependency files |
%.d: %.cpp |
50,7 → 59,7
|
# Rule to make object files |
%.o: %.cpp |
$(CXX) $(CPPFLAGS) $(INCDIRS) $(CXXFLAGS) -c $< |
$(CXX) $(CPPFLAGS) $(PROF_OPTS) $(INCDIRS) $(CXXFLAGS) -c $< |
|
|
# ----------------------------------------------------------------------------- |
/bench/sysc/src/TraceSC.cpp
27,9 → 27,12
// $Id: TraceSC.cpp 302 2009-02-13 17:22:07Z jeremy $ |
|
#include "TraceSC.h" |
#include <systemc.h> |
|
using namespace std; |
|
#define DEBUG_TRACESC 1 |
|
SC_HAS_PROCESS( TraceSC ); |
|
//! Constructor for the trace module |
52,31 → 55,62
string testNameString; |
string vcdDumpFile; |
|
// Search through the command line parameters for the "-vcd" option |
// Search through the command line parameters for VCD dump options |
dump_start_delay = 0; |
dump_stop_set = 0; |
int time_val; |
int cmdline_name_found=0; |
if (argc > 1) |
{ |
for(int i=1; i<argc; i++) |
{ |
if (strcmp(argv[i], "-vcd")==0) |
if ((strcmp(argv[i], "-vcd")==0) || |
(strcmp(argv[i], "--vcd")==0)) |
{ |
testNameString = (argv[i+1]); |
vcdDumpFile = testNameString; |
cmdline_name_found=1; |
} |
else if ( (strcmp(argv[i], "-vcdstart")==0) || |
(strcmp(argv[i], "--vcdstart")==0) ) |
{ |
time_val = atoi(argv[i+1]); |
sc_time dump_start_time(time_val,SC_NS); |
dump_start = dump_start_time; |
if (DEBUG_TRACESC) cout << "TraceSC(): Dump start time set at " << dump_start.to_string() << endl; |
dump_start_delay = 1; |
break; |
} |
else if ( (strcmp(argv[i], "-vcdstop")==0) || |
(strcmp(argv[i], "--vcdstop")==0) ) |
{ |
time_val = atoi(argv[i+1]); |
sc_time dump_stop_time(time_val,SC_NS); |
dump_stop = dump_stop_time; |
if (DEBUG_TRACESC) cout << "TraceSC(): Dump stop time set at " << dump_stop.to_string() << endl; |
dump_stop_set = 1; |
break; |
} |
} |
} |
|
|
if(cmdline_name_found==0) // otherwise use our default VCD dump file name |
vcdDumpFile = dumpNameDefault; |
|
Verilated::traceEverOn (true); |
|
cout << "Enabling VCD trace" << endl; |
cout << "* Enabling VCD trace"; |
|
if (dump_start_delay) |
cout << ", on at time " << dump_start.to_string(); |
if (dump_stop_set) |
cout << ", off at time " << dump_stop.to_string(); |
|
cout << endl; |
|
printf("VCD dumpfile: %s\n", vcdDumpFile.c_str()); |
|
printf("* VCD dumpfile: %s\n", vcdDumpFile.c_str()); |
|
// Establish a new trace with its correct time resolution, and trace to |
// great depth. |
spTraceFile = new SpTraceVcdCFile (); |
84,9 → 118,15
traceTarget->trace (spTraceFile, 99); |
spTraceFile->open (vcdDumpFile.c_str()); |
|
if (dump_start_delay == 1) |
dumping_now = 0; // We'll wait for the time to dump |
else |
dumping_now = 1; // Begin with dumping turned on |
|
|
// Method to drive the dump on each clock edge |
SC_METHOD (driveTrace); |
sensitive << clk; |
//SC_METHOD (driveTrace); |
//sensitive << clk; |
|
#endif |
|
106,13 → 146,40
} // ~TraceSC () |
|
|
//! Method to drive the trace. We're called on ever clock edge, and also at |
//! Method to drive the trace. We're called on every clock edge, and also at |
//! initialization (to get initial values into the dump). |
void |
TraceSC::driveTrace() |
{ |
#if VM_TRACE |
spTraceFile->dump (sc_time_stamp().to_double()); |
|
if (DEBUG_TRACESC) cout << "TraceSC(): " << endl; |
if (dumping_now == 0) |
{ |
// Check the time, see if we should enable dumping |
if (sc_time_stamp() >= dump_start) |
{ |
// Give a message |
cout << "* VCD tracing turned on at time " << dump_start.to_string() << endl; |
dumping_now = 1; |
} |
} |
|
if (dumping_now == 1) |
spTraceFile->dump (sc_time_stamp().to_double()); |
|
|
// Should we turn off tracing? |
if ((dumping_now == 1) && (dump_stop_set == 1)) |
{ |
if (sc_time_stamp() >= dump_stop) |
{ |
// Give a message |
cout << "* VCD tracing turned off at time " << dump_stop.to_string() << endl; |
dumping_now = 0; // Turn off the dump |
} |
} |
|
#endif |
|
} // driveTrace() |
135,7 → 202,7
|
if (secs < 1.0e-15) |
{ |
cerr << "VCD time resolution " << secs << " too small: ignored" << endl; |
cerr << "* VCD time resolution " << secs << " too small: ignored" << endl; |
return; |
} |
else if (secs < 1.0e-12) |
/bench/sysc/src/OrpsocAccess.cpp
90,9 → 90,20
|
} // getExDslot () |
|
//! Access for the id_pc register |
|
//! @return The value of the or1200_except.id_pc register |
|
uint32_t |
OrpsocAccess::getIdPC () |
{ |
return (or1200_except->get_id_pc) (); |
|
} // getIdPC () |
|
//! Access for the wb_pc register |
|
//! @return The value of the or1200_except.wb_insn register |
//! @return The value of the or1200_except.wb_pc register |
|
uint32_t |
OrpsocAccess::getWbPC () |
112,7 → 123,17
|
} // getWbInsn () |
|
//! Access for the id_insn register |
|
//! @return The value of the or1200_ctrl.wb_insn register |
|
uint32_t |
OrpsocAccess::getIdInsn () |
{ |
return (or1200_ctrl->get_id_insn) (); |
|
} // getIdInsn () |
|
//! Access for the OR1200 GPRs |
|
//! These are extracted from memory using the Verilog function |
/bench/sysc/src/OrpsocMain.cpp
45,16 → 45,22
|
#include "Vorpsoc_top.h" |
#include "OrpsocAccess.h" |
#include "TraceSC.h" |
|
//#if VM_TRACE |
//#include <systemc.h> |
#include <SpTraceVcdC.h> |
//#endif |
|
//#include "TraceSC.h" |
#include "ResetSC.h" |
#include "Or1200MonitorSC.h" |
#include "UartSC.h" |
|
|
int SIM_RUNNING; |
int sc_main (int argc, |
char *argv[] ) |
{ |
|
sc_set_time_resolution( 1, TIMESCALE_UNIT); |
// CPU clock (also used as JTAG TCK) and reset (both active high and low) |
sc_time clkPeriod (BENCH_CLK_HALFPERIOD * 2.0, TIMESCALE_UNIT); |
|
83,13 → 89,30
sc_signal<bool> spi1_ss; |
sc_signal<bool> spi1_sclk; |
|
SIM_RUNNING = 0; |
|
// Setup the name of the VCD dump file |
int VCD_enabled = 0; |
string dumpNameDefault("vlt-dump.vcd"); |
string testNameString; |
string vcdDumpFile; |
// VCD dump controling vars |
int dump_start_delay, dump_stop_set; |
int dumping_now; |
int dump_depth = 99; // Default dump depth |
sc_time dump_start,dump_stop, finish_time; |
int finish_time_set = 0; // By default we will let the simulation finish naturally |
SpTraceVcdCFile *spTraceFile; |
|
int time_val; |
int cmdline_name_found=0; |
|
// Verilator accessor |
OrpsocAccess *accessor; |
|
// Modules |
Vorpsoc_top *orpsoc; // Verilated ORPSoC |
TraceSC *trace; // Drive VCD |
//TraceSC *trace; // Drive VCD |
|
ResetSC *reset; // Generate a RESET signal |
Or1200MonitorSC *monitor; // Handle l.nop x instructions |
97,14 → 120,117
|
// Instantiate the Verilator model, VCD trace handler and accessor |
orpsoc = new Vorpsoc_top ("orpsoc"); |
trace = new TraceSC ("trace", orpsoc, argc, argv); |
//trace = new TraceSC ("trace", orpsoc, argc, argv); |
accessor = new OrpsocAccess (orpsoc); |
|
// Instantiate the SystemC modules |
reset = new ResetSC ("reset", BENCH_RESET_TIME); |
monitor = new Or1200MonitorSC ("monitor", accessor); |
monitor = new Or1200MonitorSC ("monitor", accessor, argc, argv); |
uart = new UartSC("uart"); // TODO: Probalby some sort of param |
|
|
// Parse command line options |
// Default is for VCD generation OFF, only turned on if specified on command line |
dump_start_delay = 0; |
dump_stop_set = 0; |
dumping_now = 0; |
|
|
// Search through the command line parameters for options |
|
if (argc > 1) |
{ |
for(int i=1; i<argc; i++) |
{ |
if ((strcmp(argv[i], "-d")==0) || |
(strcmp(argv[i], "--vcdfile")==0)) |
{ |
testNameString = (argv[i+1]); |
vcdDumpFile = testNameString; |
cmdline_name_found=1; |
} |
else if ((strcmp(argv[i], "-v")==0) || |
(strcmp(argv[i], "--vcdon")==0)) |
{ |
dumping_now = 1; |
} |
else if ( (strcmp(argv[i], "-e")==0) || |
(strcmp(argv[i], "--endtime")==0) ) |
{ |
time_val = atoi(argv[i+1]); |
sc_time opt_end_time(time_val,TIMESCALE_UNIT); |
finish_time = opt_end_time; |
//if (DEBUG_TRACESC) cout << "* Commmand line opt: Sim. will end at " << finish_time.to_string() << endl; |
finish_time_set = 1; |
} |
//#if VM_TRACE |
else if ( (strcmp(argv[i], "-s")==0) || |
(strcmp(argv[i], "--vcdstart")==0) ) |
{ |
time_val = atoi(argv[i+1]); |
sc_time dump_start_time(time_val,TIMESCALE_UNIT); |
dump_start = dump_start_time; |
//if (DEBUG_TRACESC) cout << "* Commmand line opt: Dump start time set at " << dump_start.to_string() << endl; |
dump_start_delay = 1; |
dumping_now = 0; |
} |
else if ( (strcmp(argv[i], "-t")==0) || |
(strcmp(argv[i], "--vcdstop")==0) ) |
{ |
time_val = atoi(argv[i+1]); |
sc_time dump_stop_time(time_val,TIMESCALE_UNIT); |
dump_stop = dump_stop_time; |
//if (DEBUG_TRACESC) cout << "* Commmand line opt: Dump stop time set at " << dump_stop.to_string() << endl; |
dump_stop_set = 1; |
} |
/* Depth setting of VCD doesn't appear to work, I think it's set during verilator script compile time */ |
/* else if ( (strcmp(argv[i], "-p")==0) || |
(strcmp(argv[i], "--vcddepth")==0) ) |
{ |
dump_depth = atoi(argv[i+1]); |
//if (DEBUG_TRACESC) cout << "* Commmand line opt: Dump depth set to " << dump_depth << endl; |
}*/ |
else if ( (strcmp(argv[i], "-h")==0) || |
(strcmp(argv[i], "--help")==0) ) |
{ |
printf("\n ORPSoC Cycle Accurate model usage:\n"); |
printf(" %s [-vh] [-d <file>] [-e <time>] [-s <time>] [-t <time>]",argv[0]); |
monitor->printSwitches(); |
printf("\n\n"); |
printf(" -h, --help\t\tPrint this help message\n"); |
printf(" -e, --endtime\t\tStop the sim at this time (ns)\n"); |
printf(" -v, --vcdon\t\tEnable VCD generation\n"); |
printf(" -d, --vcdfile\t\tEnable and specify target VCD file name\n"); |
|
printf(" -s, --vcdstart\tEnable and delay VCD generation until this time (ns)\n"); |
printf(" -t, --vcdstop\t\tEnable and terminate VCD generation at this time (ns)\n"); |
monitor->printUsage(); |
printf("\n"); |
return 0; |
} |
|
} |
} |
|
if(cmdline_name_found==0) // otherwise use our default VCD dump file name |
vcdDumpFile = dumpNameDefault; |
|
// Determine if we're going to setup a VCD dump: |
// Pretty much setting any option will enable VCD dumping. |
if ((cmdline_name_found) || (dumping_now) || (dump_start_delay) || (dump_stop_set)) |
{ |
VCD_enabled = 1; |
|
cout << "* Enabling VCD trace"; |
|
if (dump_start_delay) |
cout << ", on at time " << dump_start.to_string(); |
if (dump_stop_set) |
cout << ", off at time " << dump_stop.to_string(); |
cout << endl; |
} |
|
|
// Connect up ORPSoC |
orpsoc->clk_pad_i (clk); |
orpsoc->rst_pad_i (rstn); |
131,11 → 257,10
|
orpsoc->gpio_a_pad_io (gpio_a); // GPIO bus - output only in |
// verilator sims |
|
|
// Connect up the VCD trace handler |
trace->clk (clk); // Trace |
|
//trace->clk (clk); // Trace |
|
// Connect up the SystemC modules |
reset->clk (clk); // Reset |
reset->rst (rst); |
154,18 → 279,124
spi_sd_miso = 0; // Tie off master-in/slave-out of SD SPI bus |
|
spi1_miso = 0; |
|
//#if VM_TRACE |
if (VCD_enabled) |
{ |
Verilated::traceEverOn (true); |
|
printf("* VCD dumpfile: %s\n", vcdDumpFile.c_str()); |
|
// Establish a new trace with its correct time resolution, and trace to |
// great depth. |
spTraceFile = new SpTraceVcdCFile (); |
//spTraceFile->spTrace()->set_time_resolution (sc_get_time_resolution()); |
//setSpTimeResolution (sc_get_time_resolution ()); |
//traceTarget->trace (spTraceFile, 99); |
orpsoc->trace (spTraceFile, dump_depth); |
|
if (dumping_now) |
{ |
spTraceFile->open (vcdDumpFile.c_str()); |
} |
//#endif |
} |
|
printf("Beginning test\n"); |
printf("* Beginning test\n"); |
|
// Init the UART function |
uart->initUart(25000000, 115200); |
|
// Turn on logging by setting the "-log logfilename" option on the command line |
monitor->init_displayState(argc, argv); |
SIM_RUNNING = 1; |
|
// Execute until we stop |
sc_start (); |
// First check how we should run the sim. |
if (VCD_enabled || finish_time_set) |
{ // We'll run sim with step |
|
if (!VCD_enabled && finish_time_set) |
{ |
// We just run the sim until the set finish time |
sc_start((double)(finish_time.to_double()), TIMESCALE_UNIT); |
SIM_RUNNING=0; |
sc_stop(); |
// Print performance summary |
monitor->perfSummary(); |
} |
else |
{ |
if (dump_start_delay) |
{ |
// Run the sim until we want to dump |
sc_start((double)(dump_start.to_double()),TIMESCALE_UNIT); |
// Open the trace file |
spTraceFile->open (vcdDumpFile.c_str()); |
dumping_now = 1; |
} |
|
if (dumping_now) |
{ |
// Step the sim and generate the trace |
// Execute until we stop |
while(!Verilated::gotFinish()) |
{ |
if (SIM_RUNNING) // Changed by Or1200MonitorSC when finish NOP |
sc_start (1,TIMESCALE_UNIT); // Step the sim |
else |
{ |
spTraceFile->close(); |
break; |
} |
|
spTraceFile->dump (sc_time_stamp().to_double()); |
|
if (dump_stop_set) |
{ |
if (sc_time_stamp() >= dump_stop) |
{ |
// Close dump file |
spTraceFile->close(); |
// Now continue on again until the end |
if (!finish_time_set) |
sc_start(); |
else |
{ |
// Determine how long we should run for |
sc_time sim_time_remaining = |
finish_time - sc_time_stamp(); |
sc_start((double)(sim_time_remaining.to_double()), |
TIMESCALE_UNIT); |
// Officially stop the sim |
sc_stop(); |
// Print performance summary |
monitor->perfSummary(); |
} |
break; |
} |
} |
if (finish_time_set) |
{ |
if (sc_time_stamp() >= finish_time) |
{ |
// Officially stop the sim |
sc_stop(); |
// Close dump file |
spTraceFile->close(); |
// Print performance summary |
monitor->perfSummary(); |
break; |
} |
} |
} |
} |
} |
} |
else |
{ |
// Simple run case |
sc_start(); |
} |
|
|
// Free memory |
delete monitor; |
delete reset; |
172,7 → 403,7
|
delete accessor; |
|
delete trace; |
//delete trace; |
delete orpsoc; |
|
return 0; |
/bench/verilog/eth_stim.v
49,7 → 49,7
initial |
begin |
|
repeat(30000) @(posedge eth_clk); |
repeat(170000) @(posedge eth_clk); |
|
rx_packet_length = 16'd96; // Bytes |
|
58,9 → 58,18
set_rx_addr_type(0, 48'h0102_0304_0506, 48'h0708_090A_0B0C, 16'h0D0E); |
append_rx_crc(0, rx_packet_length, 1'b0, 1'b0); |
|
/* |
// write to phy's control register for 10Mbps |
#Tp eth_phy0.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10 |
#Tp eth_phy0.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD |
*/ |
|
/* |
// write to phy's control register for 100Mbps |
#Tp eth_phy0.control_bit14_10 = 5'b01000; // bit 13 reset - speed 100 |
#Tp eth_phy0.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD |
*/ |
|
//#Tp eth_phy0.carrier_sense_tx_fd_detect(1); // Full duplex CRS detect normally off |
|
/* |
74,9 → 83,10
input plus_drible_nibble; // if length is longer for one nibble |
|
*/ |
#100000 eth_phy0.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, 0, rx_packet_length, 1'b0); |
|
|
// while (1) |
// begin |
#300000 eth_phy0.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, 0, rx_packet_length, 1'b0); |
//end |
/* TODO: Some checking here that the packet's contents actually ended up in RAM correctly */ |
|
end |
/bench/verilog/eth_phy_defines.v
54,7 → 54,7
// LED/Configuration pins on PHY device - see the specification, page 26, table 8 |
// Initial set of bits 13, 12 and 8 of Control Register |
`define LED_CFG1 1'b0 |
`define LED_CFG2 1'b0 |
`define LED_CFG2 1'b1 |
`define LED_CFG3 1'b1 |
|
|
/bench/verilog/eth_phy.v
79,7 → 79,7
`define UNICAST_WRONG_XFR 3 |
|
|
//`define ETH_PHY_VERBOSE 1 |
`define ETH_PHY_VERBOSE 1 |
|
module eth_phy // This PHY model simulate simplified Intel LXT971A PHY |
( |
/bench/verilog/smii_phy.v
44,7 → 44,7
// SMII |
input smii_tx, |
input smii_sync, |
output smii_rx, |
output reg smii_rx, |
|
// MII |
// TX |
89,6 → 89,10
/* Generate the state counter, based on incoming sync signal */ |
/* 10-bit shift register, indicating where we are */ |
reg [10:1] state_shiftreg; |
|
/* A wire hooked up from bit 0 with the last byte of the state counter/shiftreg */ |
wire [7:0] state_shiftreg_top_byte; |
assign state_shiftreg_top_byte[7:0] = state_shiftreg[10:3]; |
|
always @(posedge clk) |
begin |
127,94 → 131,133
else /* Increment */ |
segment_ctr <= segment_ctr + 1'b1; |
end |
end |
|
end // always @ (posedge clk) |
|
|
/**************************************************************************/ |
/* RX path logic PHY->(MII->SMII)->MAC */ |
/**************************************************************************/ |
|
reg rx_nibble_sel, rx_byte_valid; |
reg [7:0] rx_data_byte_rx_clk; |
reg [7:0] rx_data_byte_rx_clk; |
|
/* Receive the RX data from the PHY and serialise it */ |
/* If RX data valid goes high, then it's the beginning of a |
proper data segment*/ |
reg [4:0] rx_dv_nib_0; |
reg rx_nib_first,rx_nib_first_r; // if high, nib_0 contains the "first" of the pair of nibs |
reg [3:0] rx_segment_begin_num; |
|
// Allow us to check if RX DV has been low for a while |
reg [3:0] rx_dv_long_low_sr; |
wire dv_long_low; |
always @(posedge ethphy_mii_rx_clk) |
rx_dv_long_low_sr[3:0] <= {rx_dv_long_low_sr[2:0], ethphy_mii_rx_dv}; |
assign rx_dv_long_low = ~(|rx_dv_long_low_sr); |
reg rx_dv; |
wire [8:0] rx_fifo_out; |
wire rx_fifo_empty,rx_fifo_almost_empty; |
reg rx_fifo_pop; |
|
always @(posedge ethphy_mii_rx_clk or negedge rst_n) |
begin |
if(!rst_n) |
begin |
rx_nibble_sel <= 0; /* start with low nibble receiving */ |
rx_data_byte_rx_clk <= 0; |
rx_byte_valid <= 0; |
rx_dv_nib_0 <= 0; |
rx_nib_first <= 0; |
rx_nib_first_r <= 0; |
end |
else |
begin |
/* Half way through, and at the end of each 10-bit section |
and whenever we should load a new segment (each time for |
fast ethernet, else once every 10 times; whenever segment_ctr |
is 0)*/ |
//if ((state_shiftreg[6] | state_shiftreg[10]) & (segment_ctr==4'h0)) |
// begin |
/* Alternate the nibble we're selecting when RX_dv */ |
if(!ethphy_mii_rx_dv) /* data on rx line is not valid */ |
rx_nibble_sel <= 0; |
else |
rx_nibble_sel <= ~rx_nibble_sel; |
if (!rx_nib_first) |
rx_dv_nib_0 <= {ethphy_mii_rx_dv,ethphy_mii_rx_d}; |
if(ethphy_mii_rx_dv) |
rx_nib_first <= ~rx_nib_first; |
|
if (!ethphy_mii_rx_dv & !rx_nibble_sel) |
rx_byte_valid <= 0; |
else if (rx_nibble_sel) /* sampled high nibble, byte OK*/ |
rx_byte_valid <= 1; |
|
if (ethphy_mii_rx_dv & !rx_nibble_sel) |
/* Sampling low nibble */ |
rx_data_byte_rx_clk[3:0] <= ethphy_mii_rx_d; |
else if (ethphy_mii_rx_dv & rx_nibble_sel) |
/* Sample high nibble */ |
rx_data_byte_rx_clk[7:4] <= ethphy_mii_rx_d; |
|
//end // if ((state_shiftreg[4] | state_shiftreg[9]) & (segment_ctr==4'h0)) |
end // else: !if(!rst_n) |
end // always @ (posedge clk)' |
rx_nib_first_r <= rx_nib_first; |
|
end |
end // always @ (posedge ethphy_mii_rx_clk or negedge rst_n) |
|
/* SMII domain RX signals */ |
reg [7:0] rx_data_byte; |
reg rx_line_rx_dv; /* Reg for second bit of SMII RX sequence, RX_DV */ |
always @(posedge clk or negedge rst_n) |
begin |
if (!rst_n) rx_fifo_pop <= 0; |
else rx_fifo_pop <= (rx_fifo_almost_empty) ? (rx_fifo_pop ? ~rx_fifo_empty : rx_fifo_pop) : 1; |
|
/* A wire hooked up from bit 0 with the last byte of the state counter/shiftreg */ |
wire [7:0] state_shiftreg_top_byte; |
assign state_shiftreg_top_byte[7:0] = state_shiftreg[10:3]; |
rx_dv <= (state_shiftreg[10] & (((rx_segment_begin_num == (segment_ctr-1)) && !fast_ethernet)| fast_ethernet)) ? (rx_fifo_pop) : rx_dv; |
end |
|
/* Move RX's DV and data into SMII clk domain */ |
always @(posedge clk) |
begin |
if(!rst_n) |
begin |
rx_line_rx_dv <= 0; |
end |
else |
begin |
/* When we're at the beginning of a new 10-bit sequence and |
the beginning of the 10-segment loop load the valid bit */ |
if(state_shiftreg[1] & (segment_ctr==4'h0)) |
begin |
rx_line_rx_dv <= rx_byte_valid; |
rx_data_byte <= rx_data_byte_rx_clk; |
end |
end // else: !if(!rst_n) |
end // always @ (posedge clk) |
/* remember which counter value we were at when rx enable/valid |
went high. |
This is only useful when not doing fast ethernet*/ |
|
/* rx en has gone high - remember the sequence number we're in */ |
if ((rx_segment_begin_num == 4'hf) & (~rx_dv_long_low)) |
rx_segment_begin_num <= segment_ctr; |
|
/* If rx enable goes low again, reset the segment number */ |
if (rx_dv_long_low) |
/* reset to 0xf */ |
rx_segment_begin_num <= 4'hf; |
end |
|
/* Assign the rx line out */ |
assign smii_rx = state_shiftreg[1] ? ethphy_mii_crs : /* 1st bit is MII CRS */ |
/* next is RX_DV bit */ |
state_shiftreg[2] ? ((rx_byte_valid & (segment_ctr==4'h0)) | |
rx_line_rx_dv) : |
/* Depending on RX_DV, output the status byte or data byte */ |
rx_line_rx_dv ? |(state_shiftreg_top_byte & rx_data_byte) : |
/* Output status byte */ |
|(state_shiftreg_top_byte & |
|
|
/* A fifo, storing RX bytes coming from the PHY interface */ |
generic_fifo #(9, 64) rx_fifo |
( |
// Outputs |
.psh_full (), |
.pop_q (rx_fifo_out), |
.pop_empty (rx_fifo_empty), |
.almost_empty (rx_fifo_almost_empty), |
// Inputs |
.async_rst_n (rst_n), |
.psh_clk (ethphy_mii_rx_clk), |
.psh_we (rx_nib_first_r), |
.psh_d ({ethphy_mii_rx_err,ethphy_mii_rx_d,rx_dv_nib_0[3:0]}), |
.pop_clk (clk), |
.pop_re ((state_shiftreg[1] & rx_fifo_pop)&(((rx_segment_begin_num == segment_ctr) && !fast_ethernet)| fast_ethernet))); |
|
|
`ifdef RX_SYNC_1 |
|
/* Assign the rx line out */ |
always @(posedge clk) |
smii_rx <= state_shiftreg[1] ? ethphy_mii_crs : /* 1st bit is MII CRS */ |
state_shiftreg[2] ? ((rx_dv & (segment_ctr==4'h0) & !fast_ethernet) | |
rx_dv) : |
// inter-frame status byte or data byte |
state_shiftreg[3] ? (rx_dv ? (rx_fifo_out[0]) : ethphy_mii_rx_err) : |
state_shiftreg[4] ? (rx_dv ? (rx_fifo_out[1]) : fast_ethernet) : |
state_shiftreg[5] ? (rx_dv ? (rx_fifo_out[2]) : duplex) : |
state_shiftreg[6] ? (rx_dv ? (rx_fifo_out[3]) : link) : |
state_shiftreg[7] ? (rx_dv ? (rx_fifo_out[4]) : jabber) : |
state_shiftreg[8] ? (rx_dv ? (rx_fifo_out[5]) : 1) : |
state_shiftreg[9] ? (rx_dv ? (rx_fifo_out[6]) : 0) : |
state_shiftreg[10] ? (rx_dv ? (rx_fifo_out[7]) : 1) : 0; |
|
`else // !`ifdef RX_SYNC_1 |
|
/* Assign the rx line out */ |
always @(posedge clk) |
smii_rx <= state_shiftreg[10] ? ethphy_mii_crs : /* 1st bit is MII CRS */ |
state_shiftreg[1] ? ((rx_dv & (segment_ctr==4'h0) & !fast_ethernet) | |
rx_dv) : |
// inter-frame status byte or data byte |
state_shiftreg[2] ? (rx_dv ? (rx_fifo_out[0]) : ethphy_mii_rx_err) : |
state_shiftreg[3] ? (rx_dv ? (rx_fifo_out[1]) : fast_ethernet) : |
state_shiftreg[4] ? (rx_dv ? (rx_fifo_out[2]) : duplex) : |
state_shiftreg[5] ? (rx_dv ? (rx_fifo_out[3]) : link) : |
state_shiftreg[6] ? (rx_dv ? (rx_fifo_out[4]) : jabber) : |
state_shiftreg[7] ? (rx_dv ? (rx_fifo_out[5]) : 1) : |
state_shiftreg[8] ? (rx_dv ? (rx_fifo_out[6]) : 0) : |
state_shiftreg[9] ? (rx_dv ? (rx_fifo_out[7]) : 1) : 0; |
`endif // !`ifdef RX_SYNC_1 |
|
|
/* Status seq.: CRS, DV, ER, Speed, Duplex, Link, Jabber, UPV, FCD, 1 */ |
{1'b1,1'b0,1'b1,jabber,link,duplex,fast_ethernet,ethphy_mii_rx_err}); |
// {1'b1,1'b0,1'b1,jabber,link,duplex,,ethphy_mii_rx_err}); |
|
|
/**************************************************************************/ |
/* TX path logic MAC->(SMII->MII)->PHY */ |
229,25 → 272,49
reg tx_en_seqbit_scratch; |
reg [7:0] tx_data_byte_scratch; |
|
reg [1:0] tx_byte_to_phy; /* PHY sourced TX_CLK domain */ |
reg [2:0] tx_byte_to_phy; /* PHY sourced TX_CLK domain */ |
|
wire tx_fifo_empty; |
wire tx_fifo_empty, tx_fifo_almost_empty; |
wire tx_fifo_full; |
wire [7:0] tx_fifo_q_dat; |
wire tx_fifo_q_err; |
reg tx_fifo_pop; |
reg [3:0] tx_segment_begin_num; |
wire [3:0] tx_segment_load_num; |
|
|
assign tx_segment_load_num = (tx_segment_begin_num == 0) ? 4'h9 : tx_segment_begin_num - 1; |
|
/* Signal to tell us an appropriate time to copy the values out of the |
temp regs we put the incoming TX line into when we've received a |
sequence off the SMII TX line that has TX_EN high */ |
wire tx_seqbits_copy; |
assign tx_seqbits_copy = ((((!fast_ethernet) & (segment_ctr==4'h1)) | |
((fast_ethernet) & (state_shiftreg[1]))) |
& tx_en_seqbit_scratch); |
assign tx_seqbits_copy = ( |
( |
((!fast_ethernet) & (segment_ctr == tx_segment_load_num)) | |
fast_ethernet |
) |
& tx_en_seqbit_scratch & state_shiftreg[1] |
); |
|
always @(posedge clk) |
begin |
/* remember which counter value we were at when tx enable/valid |
went high. |
This is only useful when not doing fast ethernet*/ |
|
/* tx en has gone high - remember the sequence number we're in */ |
if ((tx_segment_begin_num == 4'hf) & (tx_en_seqbit_scratch)) |
tx_segment_begin_num <= segment_ctr; |
|
/* If tx enable goes low again, reset the segment number */ |
if (!tx_en_seqbit_scratch) |
/* reset to 0xf */ |
tx_segment_begin_num <= 4'hf; |
end |
|
|
always @(posedge clk) |
begin |
if (!rst_n) |
begin |
tx_er_seqbit_scratch <= 0; |
256,39 → 323,27
end |
else |
begin |
if (segment_ctr==4'h0) |
begin |
if(state_shiftreg[1]) |
tx_er_seqbit_scratch <= smii_tx; |
|
if(state_shiftreg[2]) |
tx_en_seqbit_scratch <= smii_tx; |
|
/* Preserve all but current bit of interest, as indicated |
by state vector bit (reversed, becuase we get MSbit |
first) and OR in the current smii_tx line value at this |
position*/ |
if((|state_shiftreg[10:3]) & tx_en_seqbit_scratch) |
tx_data_byte_scratch <= (tx_data_byte_scratch & ~state_shiftreg_top_byte) | |
({8{smii_tx}} & state_shiftreg_top_byte); |
|
end // if (segment_ctr==4'h0) |
|
/* If we've just received a sequence with TX_EN then put |
these values in the proper regs at the appropriate time, |
depending on the speed , ready for transmission to the PHY */ |
if (tx_seqbits_copy) |
begin |
|
/* Now clear the tx_en scratch bit so we don't do |
this again */ |
tx_en_seqbit_scratch <= 0; |
|
end // if (tx_seqbits_copy) |
if(state_shiftreg[1]) |
tx_er_seqbit_scratch <= smii_tx; |
|
if(state_shiftreg[2]) |
tx_en_seqbit_scratch <= smii_tx; |
|
/* Preserve all but current bit of interest, as indicated |
by state vector bit (reversed, becuase we get MSbit |
first) and OR in the current smii_tx line value at this |
position*/ |
if((|state_shiftreg[10:3]) & tx_en_seqbit_scratch) |
tx_data_byte_scratch <= (tx_data_byte_scratch & ~state_shiftreg_top_byte) | |
({8{smii_tx}} & state_shiftreg_top_byte); |
|
end |
end // always @ (posedge clk) |
|
|
|
reg [3:0] nib; |
|
|
|
/* In the event we have a valid byte frame then get it to the |
PHY as quickly as possible - this is TX_CLK domain */ |
always @(posedge ethphy_mii_tx_clk or negedge rst_n) |
305,42 → 360,53
end |
else |
begin |
|
if(!tx_fifo_empty) /* A byte ready to go to the MAC */ |
/* If fast_ethernet/100mbs we wait until the FIFO is full |
otherwise, we push out the byte each time we get one */ |
//if((!tx_fifo_empty && !fast_ethernet) || |
//(tx_fifo_full && fast_ethernet)) |
if (!tx_fifo_almost_empty) |
begin |
if(tx_byte_to_phy == 2'b00) |
if(tx_byte_to_phy == 0) |
begin |
/* Pop */ |
tx_byte_to_phy <= 1; |
tx_fifo_pop <= 1; |
tx_byte_to_phy <= 2'b01; |
end |
end |
|
|
/* FIFO control loop */ |
if (tx_byte_to_phy == 2'b01) /* Output bits 3-0 (bottom nibble ) */ |
if (tx_byte_to_phy == 1)/* Output bits 3-0 (bottom nibble ) */ |
begin |
|
ethphy_mii_tx_en <= 1; |
|
tx_fifo_pop <= 0; |
|
tx_byte_to_phy <= 2; |
|
ethphy_mii_tx_d <= tx_fifo_q_dat[3:0]; |
ethphy_mii_tx_en <= 1; |
nib <= tx_fifo_q_dat[7:4]; |
ethphy_mii_tx_err <= tx_fifo_q_err; |
tx_fifo_pop <= 0; |
tx_byte_to_phy <= 2'b10; |
|
end |
else if (tx_byte_to_phy == 2'b10) /* Output bits 7-4 (top nibble) */ |
else if (tx_byte_to_phy == 2) /* Output bits 7-4 (top nibble) */ |
begin |
ethphy_mii_tx_d <= tx_fifo_q_dat[7:4]; |
//ethphy_mii_tx_d <= tx_fifo_q_dat[7:4]; |
|
ethphy_mii_tx_d <= nib; |
|
if(!tx_fifo_empty) /* Check if more in FIFO */ |
begin |
tx_fifo_pop <= 1; /* Pop again */ |
tx_byte_to_phy <= 2'b01; |
tx_fifo_pop <= 1; |
tx_byte_to_phy <= 1; |
end |
else /* Finish up */ |
begin |
tx_byte_to_phy <= 2'b11; |
tx_byte_to_phy <= 3; |
ethphy_mii_tx_en <= 0; |
end |
end |
else if (tx_byte_to_phy == 2'b11) /* De-assert TX_EN */ |
else if (tx_byte_to_phy == 3) /* De-assert TX_EN */ |
begin |
ethphy_mii_tx_en <= 0; |
tx_byte_to_phy <= 2'b00; |
end |
end // else: !if(!rst_n) |
353,12 → 419,13
.psh_full (tx_fifo_full), |
.pop_q ({tx_fifo_q_err,tx_fifo_q_dat}), |
.pop_empty (tx_fifo_empty), |
.almost_empty (tx_fifo_almost_empty), |
// Inputs |
.async_rst_n (rst_n), |
.psh_clk (clk), |
.psh_we (tx_seqbits_copy), |
.psh_d ({tx_er_seqbit_scratch,tx_data_byte_scratch}), |
.pop_clk (), |
.pop_clk (ethphy_mii_tx_clk), |
.pop_re (tx_fifo_pop)); |
|
|
369,11 → 436,12
|
|
/* Generic fifo - this is bad, should probably be done some other way */ |
module generic_fifo (async_rst_n, psh_clk, psh_we, psh_d, psh_full, pop_clk, pop_re, pop_q, pop_empty); |
module generic_fifo (async_rst_n, psh_clk, psh_we, psh_d, psh_full, pop_clk, pop_re, pop_q, pop_empty, almost_empty); |
|
parameter dw = 8; |
parameter size = 64; |
|
parameter size = 16; |
parameter size_log_2 = 4; |
|
/* Asynch. reset, active low */ |
input async_rst_n; |
|
386,83 → 454,63
/* Pop side signals */ |
input pop_clk; |
input pop_re; |
//output reg [dw-1:0] pop_q; |
output reg [dw-1:0] pop_q; |
output pop_empty; |
output wire almost_empty; |
|
|
/* Actual FIFO memory */ |
reg [dw-1:0] fifo_mem [0:size-1]; |
|
/* Poorly defined pointer logic -- will need to be changed if the size paramter is too big - Verilog needs some log base 2 thing */ |
reg [7:0] ptr; /* Only 8 bits, so max size of 255 of fifo! */ |
|
/* FIFO position ptr regs */ |
reg [size_log_2 - 1 : 0 ] wr_ptr, rd_ptr, ctr; |
|
integer i; |
|
|
/* FIFO full signal for push side */ |
assign psh_full = (ptr == size-1) ? 1 : 0; |
//assign psh_full = (ptr == size-1) ? 1 : 0; |
/* This full logic means we all but one slot in the FIFO */ |
assign psh_full = ctr == size; |
|
/* FIFO empty signal for pop side */ |
assign pop_empty = (ptr == 0) ? 1 : 0; |
//assign pop_empty = (ptr == 0) ? 1 : 0; |
//assign pop_empty = ctr==0; |
assign pop_empty = rd_ptr == wr_ptr; |
|
assign almost_empty = ctr < 2; |
|
always @(posedge pop_re or negedge async_rst_n) |
begin |
if (!async_rst_n) |
rd_ptr <= 0; |
else |
begin |
pop_q = fifo_mem[rd_ptr]; |
rd_ptr <= rd_ptr + 1; |
ctr <= ctr - 1; |
end |
end |
|
/* This will work if pushing side is a lot faster than popping side */ |
reg pop_re_psh_clk; |
wire pop_re_risingedge_psh_clk; /* Signal to help push side see when |
there's been a pop_re rising edge, |
sampled on push clock */ |
|
/* Detect edge of signal in pop domain for psh domain */ |
assign pop_re_risingedge_psh_clk = (pop_re & !pop_re_psh_clk); |
|
|
integer i; |
always @(posedge psh_clk or negedge async_rst_n) |
always @(posedge psh_we or negedge async_rst_n) |
begin |
if (!async_rst_n) |
begin |
ptr <= 0; |
|
|
for (i=0;i<size;i=i+1) fifo_mem[i] <= 0; |
|
pop_re_psh_clk <= 0; |
|
wr_ptr <= 0; |
ctr <= 0; |
end |
else |
else |
begin |
|
pop_re_psh_clk <= pop_re; /* Register pop command in psh domain */ |
|
if (psh_we) /* Push into FIFO */ |
begin |
if (!pop_re_psh_clk) /* If no pop at the same time, simple */ |
begin |
fifo_mem[ptr] <= psh_d; |
ptr <= ptr + 1'b1; |
end |
else /* Pop at same edge */ |
begin |
/* Shift fifo contents */ |
for(i=1;i<size;i=i+1) |
fifo_mem[i-1] <= fifo_mem[i]; |
fifo_mem[size-1] <= 0; |
pop_q <= fifo_mem[0]; |
fifo_mem[ptr] <= psh_d; |
/* ptr remains unchanged */ |
end // else: !if!(pop_re_psh_clk) |
end // if (psh_we) |
else /* No push, see if there's a pop */ |
begin |
if (pop_re_risingedge_psh_clk) /* Detected a pop */ |
begin |
for(i=1;i<size;i=i+1) |
fifo_mem[i-1] <= fifo_mem[i]; |
fifo_mem[size-1] <= 0; |
pop_q <= fifo_mem[0]; |
ptr <= ptr - 1'b1; |
end |
end // else: !if(psh_we) |
end // else: !if(!async_rst_n) |
end // always @ (posedge psh_clk or negedge async_rst_n) |
fifo_mem[wr_ptr] <= psh_d; |
wr_ptr <= #1 wr_ptr + 1; |
ctr <= ctr + 1; |
end |
end |
|
|
|
endmodule // generic_fifo |
|
|
/bench/verilog/orpsoc_testbench.v
338,6 → 338,6
endmodule // orpsoc_testbench |
|
// Local Variables: |
// verilog-library-files:("../../rtl/verilog/orp_soc.v") |
// verilog-library-files:("../../rtl/verilog/orpsoc_top.v") |
// verilog-library-directories:("." "../../rtl/verilog") |
// End: |
// End: |
/bench/verilog/or1200_monitor.v
239,6 → 239,9
* shouldn't be needed - but is handy if someone changes something and stops |
* the test continuing forever. |
*/ |
integer num_nul_inst; |
initial num_nul_inst = 0; |
|
task monitor_for_crash; |
`define OR1200_MONITOR_CRASH_TRACE_SIZE 32 |
reg [31:0] insn_trace [0:`OR1200_MONITOR_CRASH_TRACE_SIZE-1]; //Trace buffer of 32 instructions |
247,6 → 250,9
|
begin |
if (`OR1200_TOP.or1200_cpu.or1200_ctrl.wb_insn == 32'h00000000) |
num_nul_inst = num_nul_inst + 1; |
|
if (num_nul_inst == 1000) // Sat a loop a bit too long... |
begin |
$fdisplay(fgeneral, "ERROR - no instruction at PC %h", `OR1200_TOP.or1200_cpu.or1200_except.wb_pc); |
$fdisplay(fgeneral, "Crash trace: Last %d instructions: ",`OR1200_MONITOR_CRASH_TRACE_SIZE); |
/bench/verilog/vpi/c/rsp-rtl_sim.h
103,13 → 103,13
int dbg_wb_write_block32(uint32_t adr, uint32_t *data, int len); |
|
/* read a register from cpu */ |
int dbg_cpu0_read(uint32_t adr, uint32_t *data); |
int dbg_cpu0_read(uint32_t adr, uint32_t *data, uint32_t length); |
|
/* read a register from cpu module */ |
int dbg_cpu0_read_ctrl(uint32_t adr, unsigned char *data); |
|
/* write a cpu register */ |
int dbg_cpu0_write(uint32_t adr, uint32_t data); |
int dbg_cpu0_write(uint32_t adr, uint32_t *data, uint32_t length); |
|
/* write a cpu module register */ |
int dbg_cpu0_write_ctrl(uint32_t adr, unsigned char data); |
/bench/verilog/vpi/c/gdb.h
120,6 → 120,25
order. |
*/ |
|
/* Special purpose groups */ |
|
#define OR1K_SPG_SIZE_BITS 11 |
#define OR1K_SPG_SIZE (1 << OR1K_SPG_SIZE_BITS) |
|
#define OR1K_SPG_SYS 0 |
#define OR1K_SPG_DMMU 1 |
#define OR1K_SPG_IMMU 2 |
#define OR1K_SPG_DC 3 |
#define OR1K_SPG_IC 4 |
#define OR1K_SPG_MAC 5 |
#define OR1K_SPG_DEBUG 6 |
#define OR1K_SPG_PC 7 |
#define OR1K_SPG_PM 8 |
#define OR1K_SPG_PIC 9 |
#define OR1K_SPG_TT 10 |
#define OR1K_SPG_FPU 11 |
|
|
typedef struct { |
uint32_t command; |
uint32_t length; |
/bench/verilog/vpi/c/rsp-rtl_sim.c
514,7 → 514,7
} |
|
/* read a register from cpu */ |
int dbg_cpu0_read(uint32_t adr, uint32_t *data) |
int dbg_cpu0_read(uint32_t adr, uint32_t *data, uint32_t length) |
{ |
|
if (DBG_CALLS)printf("dbg_cpu0_read: adr 0x%.8x\n",adr); |
524,9 → 524,11
send_command_to_vpi(CMD_CPU_RD_REG); |
|
send_address_to_vpi(adr); |
|
send_data_to_vpi(length); // Added 090901 --jb |
|
get_block_data_from_vpi(length, data); // changed 090901 --jb //get_data_from_vpi(data); |
|
get_data_from_vpi(data); |
|
get_response_from_vpi(); |
|
return 0; |
534,7 → 536,7
} |
|
/* write a cpu register */ |
int dbg_cpu0_write(uint32_t adr, uint32_t data) |
int dbg_cpu0_write(uint32_t adr, uint32_t *data, uint32_t length) |
{ |
|
if (DBG_CALLS)printf("dbg_cpu0_write: adr 0x%.8x\n",adr); |
545,7 → 547,9
|
send_address_to_vpi(adr); |
|
send_data_to_vpi(data); |
send_data_to_vpi(length); // Added 090901 -- jb |
|
send_block_data_to_vpi(length, data); // Added 090901 -- jb |
|
get_response_from_vpi(); |
|
621,14 → 625,16
printf("\tor1k stall failed. read: 0x%x\n", stalled); // check stall or1k |
//exit(1); |
} |
|
/* Read NPC,PPC and SR regs, they are consecutive in CPU, at adr. 16, 17 and 18 */ |
uint32_t pcs_and_sr[3]; |
debug2(" Reading npc, ppc\n"); |
dbg_cpu0_read(16, (uint32_t *)pcs_and_sr, 3 * 4); |
|
debug2(" Reading npc\n"); |
dbg_cpu0_read((0 << 11) + 16, &npc); |
debug2(" Reading ppc\n"); |
dbg_cpu0_read((0 << 11) + 18, &ppc); |
debug2(" Reading r1\n"); |
dbg_cpu0_read(0x401, &r1); |
printf(" Read npc = %.8x ppc = %.8x r1 = %.8x\n", npc, ppc, r1); |
dbg_cpu0_read(0x401, &r1, 4); |
printf(" Read npc = %.8x ppc = %.8x r1 = %.8x\n", |
pcs_and_sr[0], pcs_and_sr[2], r1); |
|
} |
|
/bench/verilog/vpi/c/gdb.c
144,6 → 144,7
string. So at least NUMREGBYTES*2 + 1 (for the 'G' or the EOS) are needed |
for register packets */ |
#define GDB_BUF_MAX ((NUM_REGS) * 8 + 1) |
//#define GDB_BUF_MAX 1500 |
|
/*! Size of the matchpoint hash table. Largest prime < 2^10 */ |
#define MP_HASH_SIZE 1021 |
191,7 → 192,24
#define SPR_DRR_FPE 0x00001000 //!< Floating point |
#define SPR_DRR_TE 0x00002000 //!< Trap |
|
/* Defines for Debug Mode Register 1 bits. */ |
#define SPR_DMR1_CW 0x00000003 /* Mask for CW bits */ |
#define SPR_DMR1_CW_AND 0x00000001 /* Chain watchpoint 0 AND */ |
#define SPR_DMR1_CW_OR 0x00000002 /* Chain watchpoint 0 OR */ |
#define SPR_DMR1_CW_SZ 2 /* Number of bits for each WP */ |
#define SPR_DMR1_ST 0x00400000 /* Single-step trace */ |
#define SPR_DMR1_BT 0x00800000 /* Branch trace */ |
|
/* Defines for Debug Mode Register 2 bits. */ |
#define SPR_DMR2_WCE0 0x00000001 /* Watchpoint counter enable 0 */ |
#define SPR_DMR2_WCE1 0x00000002 /* Watchpoint counter enable 1 */ |
#define SPR_DMR2_AWTC_MASK 0x00000ffc /* Assign watchpoints to ctr mask */ |
#define SPR_DMR2_WGB_MASK 0x003ff000 /* Watchpoints generaing brk mask */ |
#define SPR_DMR2_WBS_MASK 0xffc00000 /* Watchpoint brkpt status mask */ |
#define SPR_DMR2_AWTC_OFF 2 /* Assign watchpoints to ctr offset */ |
#define SPR_DMR2_WGB_OFF 12 /* Watchpoints generating brk offset */ |
#define SPR_DMR2_WBS_OFF 22 /* Watchpoint brkpt status offset */ |
|
/*! Definition of GDB target signals. Data taken from the GDB 6.8 |
source. Only those we use defined here. The exact meaning of |
signal number is defined by the header `include/gdb/signals.h' |
231,6 → 249,55
int npcIsCached; //!< Is the NPC cached - should be bool |
uint32_t npcCachedValue; //!< Cached value of the NPC |
|
/* Debug registers cache */ |
#define OR1K_MAX_MATCHPOINTS 8 |
|
enum dcr_cc { |
OR1K_CC_MASKED = 0, |
OR1K_CC_EQ = 1, |
OR1K_CC_LT = 2, |
OR1K_CC_LE = 3, |
OR1K_CC_GT = 4, |
OR1K_CC_GE = 5, |
OR1K_CC_NE = 6, |
OR1K_CC_RESERVED = 7 |
}; /* Compare operation */ |
|
enum dcr_ct { |
OR1K_CT_DISABLED = 0, /* Disabled */ |
OR1K_CT_FETCH = 1, /* Compare to fetch EA */ |
OR1K_CT_LEA = 2, /* Compare to load EA */ |
OR1K_CT_SEA = 3, /* Compare to store EA */ |
OR1K_CT_LDATA = 4, /* Compare to load data */ |
OR1K_CT_SDATA = 5, /* Compare to store data */ |
OR1K_CT_AEA = 6, /* Compare to load/store EA */ |
OR1K_CT_ADATA = 7 /* Compare to load/store data */ |
}; /* Compare to what? */ |
|
/*! Cached OR1K debug register values (ignores counters for now). */ |
static struct { |
uint32_t dvr[OR1K_MAX_MATCHPOINTS]; |
struct { |
uint32_t dp : 1; /* DVR/DCP present - Read Only */ |
enum dcr_cc cc : 3; /* Compare condition */ |
uint32_t sc : 1; /* Signed comparison? */ |
enum dcr_ct ct : 3; /* Compare to */ |
uint32_t dcr_reserved : 24; |
} dcr[OR1K_MAX_MATCHPOINTS]; |
uint32_t dmr1; |
uint32_t dmr2; |
uint32_t dcrw0; |
uint32_t dcrw1; |
uint32_t dsr; |
uint32_t drr; |
} or1k_dbg_group_regs_cache; |
|
// Value to indicate status of the registers |
// Init to -1, meaning we don't have a copy, 0 = clean copy, 1 = dirty copy |
static int dbg_regs_cache_dirty = -1; |
|
static uint32_t gpr_regs[MAX_GPRS]; // Static array to block read the GPRs into |
|
static int err = 0; |
|
|
331,6 → 398,15
static void mp_hash_add (enum mp_type type, uint32_t addr, uint32_t instr); |
static struct mp_entry * mp_hash_lookup (enum mp_type type, uint32_t addr); |
static struct mp_entry * mp_hash_delete (enum mp_type type, uint32_t addr); |
static void get_debug_registers(void); |
static void put_debug_registers(void); |
static int find_free_dcrdvr_pair(void); |
static int count_free_dcrdvr_pairs(void); |
static int find_matching_dcrdvr_pair(uint32_t addr, uint32_t cc); |
static void insert_hw_watchpoint(int wp_num, uint32_t address, uint32_t cc); |
static void remove_hw_watchpoint(int wp_num); |
static void enable_hw_breakpoint(int wp_num); |
static void disable_hw_breakpoint(int wp_num); |
static void rsp_remove_matchpoint (struct rsp_buf *p_buf); |
static void rsp_insert_matchpoint (struct rsp_buf *p_buf); |
static void rsp_command (struct rsp_buf *p_buf); |
388,6 → 464,9
rsp.sigval = 0; /* No exception */ |
rsp.start_addr = EXCEPT_RESET; /* Default restart point */ |
|
/* Clear the debug registers cache */ |
bzero((char*) &or1k_dbg_group_regs_cache, sizeof(or1k_dbg_group_regs_cache)); |
|
/* Set up the matchpoint hash table */ |
mp_hash_init (); |
|
520,12 → 599,15
|
gdb_set_chain(SC_RISC_DEBUG); |
|
// Now read the DRR (Debug Reason Register) |
gdb_read_reg(DRR_CPU_REG_ADD, &drr); |
get_debug_registers(); |
|
// Now check the DRR (Debug Reason Register) |
//gdb_read_reg(DRR_CPU_REG_ADD, &drr); |
drr = or1k_dbg_group_regs_cache.drr; |
|
if (DEBUG_GDB) printf("DRR: 0x%08x\n", drr); |
|
switch ((int)(drr&0xffffffff)) |
switch (drr) |
{ |
case SPR_DRR_RSTE: rsp.sigval = TARGET_SIGNAL_PWR; break; |
case SPR_DRR_BUSEE: rsp.sigval = TARGET_SIGNAL_BUS; break; |
777,6 → 859,7
signal (SIGPIPE, SIG_IGN); /* So we don't exit if client dies */ |
|
printf ("Remote debugging from host %s\n", inet_ntoa (sock_addr.sin_addr)); |
|
} /* rsp_get_client () */ |
|
|
1947,31 → 2030,21
/* Set the address as the value of the next program counter */ |
set_npc (addr); |
|
/* Clear Debug Reason Register (DRR) 0x3015 */ |
// Arc sim --> cpu_state.sprs[SPR_DRR] = 0; |
if(gdb_write_reg(DRR_CPU_REG_ADD, 0)) printf("Error write to DRR register\n"); |
or1k_dbg_group_regs_cache.drr = 0; // Clear DRR |
or1k_dbg_group_regs_cache.dmr1 &= ~SPR_DMR1_ST; // Continuing, so disable step if it's enabled |
or1k_dbg_group_regs_cache.dsr |= SPR_DSR_TE; // If breakpoints-cause-traps is not enabled |
dbg_regs_cache_dirty = 1; // Always write the cache back |
|
/* Commit all debug registers */ |
if (dbg_regs_cache_dirty == 1) |
put_debug_registers(); |
|
/* Clear watchpoint break generation in Debug Mode Register 2 (DMR2) 0x3011 */ |
// Arc sim --> cpu_state.sprs[SPR_DMR2] &= ~SPR_DMR2_WGB; |
if(gdb_read_reg(DMR2_CPU_REG_ADD, &temp_uint32)) printf("Error read from DMR2 register\n"); |
temp_uint32 &= ~SPR_DMR2_WGB; |
if(gdb_write_reg(DMR2_CPU_REG_ADD, temp_uint32)) printf("Error write to DMR2 register\n"); |
|
/* Clear the single step trigger in Debug Mode Register 1 (DMR1) Register 0x3010 */ |
// Arc sim --> cpu_state.sprs[SPR_DMR1] &= ~SPR_DMR1_ST; |
if(gdb_read_reg(DMR1_CPU_REG_ADD, &temp_uint32)) printf("Error read from DMR1 register\n"); |
temp_uint32 &= ~SPR_DMR1_ST; |
if(gdb_write_reg(DMR1_CPU_REG_ADD, temp_uint32)) printf("Error write to DMR1 register\n"); |
|
/* Set traps to be handled by the debug unit in the Debug Stop Register (DSR) Register 0x3014 */ |
// Arc sim --> cpu_state.sprs[SPR_DSR] |= SPR_DSR_TE; |
if(gdb_read_reg(DSR_CPU_REG_ADD, &temp_uint32)) printf("Error read from DSR register\n"); |
temp_uint32 |= SPR_DSR_TE; |
if(gdb_write_reg(DSR_CPU_REG_ADD, temp_uint32)) printf("Error write to DSR register\n"); |
|
/* Unstall the processor */ |
set_stall_state (0); |
|
/* Debug regs cache is now invalid */ |
dbg_regs_cache_dirty = -1; |
|
/* Note the GDB client is now waiting for a reply. */ |
rsp.client_waiting = 1; |
|
2002,15 → 2075,18
|
|
// Read all GPRs |
gdb_read_block(0x400, (uint32_t *) &gpr_regs, MAX_GPRS*4); |
|
for (r = 0; r < MAX_GPRS; r++){ |
|
err = gdb_read_reg(0x400 + r, &temp_uint32); |
/*err = gdb_read_reg(0x400 + r, &temp_uint32); |
if(err > 0){ |
if (DEBUG_GDB) printf("Error %d in gdb_read_reg at reg. %d\n", err, r); |
put_str_packet ("E01"); |
return; |
} |
reg2hex (temp_uint32, &(buffer.data[r * 8])); |
*/ |
reg2hex (gpr_regs[r], &(buffer.data[r * 8])); |
|
if (DEBUG_GDB_DUMP_DATA){ |
switch(r % 4) |
2029,38 → 2105,19
break; |
} |
} |
|
} |
/* ---------- PPC ---------- */ |
err = gdb_read_reg(PPC_CPU_REG_ADD, &temp_uint32); |
if(err > 0){ |
if (DEBUG_GDB) printf("Error %d in gdb_read_reg read --> PPC\n", err); |
put_str_packet ("E01"); |
return; |
} |
reg2hex (temp_uint32, &(buffer.data[PPC_REGNUM * 8])); |
if (DEBUG_GDB_DUMP_DATA) printf("PPC 0x%08x\n", temp_uint32); |
/* ---------- NPC ---------- */ |
temp_uint32 = get_npc(); |
/* |
err = gdb_read_reg(NPC_CPU_REG_ADD, &temp_uint32); |
if(err > 0){ |
if (DEBUG_GDB) printf("Error %d in gdb_read_reg read --> NPC\n", err); |
put_str_packet ("E01"); |
return; |
} |
*/ |
reg2hex (temp_uint32, &(buffer.data[NPC_REGNUM * 8])); |
if (DEBUG_GDB_DUMP_DATA) printf("NPC 0x%08x\n", temp_uint32); |
/* ---------- SR ---------- */ |
err = gdb_read_reg(SR_CPU_REG_ADD, &temp_uint32); |
if(err > 0){ |
if (DEBUG_GDB) printf("Error %d in gdb_read_reg read --> SP\n", err); |
put_str_packet ("E01"); |
return; |
} |
reg2hex (temp_uint32, &(buffer.data[SR_REGNUM * 8])); |
if (DEBUG_GDB_DUMP_DATA) printf("SR 0x%08x\n", temp_uint32); |
|
/* Read NPC,PPC and SR regs, they are consecutive in CPU, at adr. 16, 17 and 18 */ |
uint32_t pcs_and_sr[3]; |
gdb_read_block(NPC_CPU_REG_ADD, (uint32_t *)pcs_and_sr, 3 * 4); |
|
reg2hex (pcs_and_sr[0], &(buffer.data[NPC_REGNUM * 8])); |
reg2hex (pcs_and_sr[1], &(buffer.data[SR_REGNUM * 8])); |
reg2hex (pcs_and_sr[2], &(buffer.data[PPC_REGNUM * 8])); |
|
if (DEBUG_GDB_DUMP_DATA) printf("PPC 0x%08x\n", pcs_and_sr[2]); |
if (DEBUG_GDB_DUMP_DATA) printf("NPC 0x%08x\n", pcs_and_sr[0]); |
if (DEBUG_GDB_DUMP_DATA) printf("SR 0x%08x\n", pcs_and_sr[1]); |
|
/* Finalize the packet and send it */ |
buffer.data[NUM_REGS * 8] = 0; |
2090,16 → 2147,6
rsp_write_all_regs (struct rsp_buf *p_buf) |
{ |
uint32_t regnum; /* Register index */ |
// char valstr[9]; /* Allow for EOS on the string */ |
|
// /* Check for valid data */ |
// if (0 != (strcmp ("G", p_buf->data)) && (GDB_BUF_MAX != strlen(p_buf->data))) |
// { |
// fprintf (stderr, "Warning: Failed to recognize RSP write register " |
// "command: %s\n", p_buf->data); |
// // put_str_packet ("E01"); |
// return; |
// } |
|
// Make sure the processor is stalled |
gdb_ensure_or1k_stalled(); |
2111,44 → 2158,30
put_str_packet ("E01"); |
return; |
} |
|
|
/* ---------- GPRS ---------- */ |
for (regnum = 0; regnum < MAX_GPRS; regnum++) |
{ |
err = gdb_write_reg(0x400 + regnum, hex2reg (&p_buf->data[regnum * 8 + 1])); |
if(err > 0){ |
if (DEBUG_GDB) printf("Error %d in rsp_write_reg write --> GPRS\n", err); |
put_str_packet ("E01"); |
return; |
} |
} |
gpr_regs[regnum] = hex2reg (&p_buf->data[regnum * 8 + 1]); |
|
/* Do a block write */ |
gdb_write_block(0x400, (uint32_t *) gpr_regs, MAX_GPRS*32); |
|
/* ---------- PPC ---------- */ |
err = gdb_write_reg(PPC_CPU_REG_ADD, hex2reg (&p_buf->data[PPC_REGNUM * 8 + 1])); |
if(err > 0){ |
if (DEBUG_GDB) printf("Error %d in rsp_write_reg write --> PPC\n", err); |
put_str_packet ("E01"); |
return; |
} |
/* ---------- SR ---------- */ |
err = gdb_write_reg(SR_CPU_REG_ADD, hex2reg (&p_buf->data[SR_REGNUM * 8 + 1])); |
if(err > 0){ |
if (DEBUG_GDB) printf("Error %d in rsp_write_reg write --> SR\n", err); |
put_str_packet ("E01"); |
return; |
} |
/* Write PPC and SR regs, they are consecutive in CPU, at adr. 17 and 18 */ |
/* We handle NPC specially */ |
uint32_t pcs_and_sr[2]; |
pcs_and_sr[0] = hex2reg (&p_buf->data[SR_REGNUM * 8 + 1]); |
pcs_and_sr[1] = hex2reg (&p_buf->data[PPC_REGNUM * 8 + 1]); |
|
gdb_write_block(SR_CPU_REG_ADD, (uint32_t *)pcs_and_sr, 2 * 4); |
|
/* ---------- NPC ---------- */ |
set_npc(hex2reg (&p_buf->data[NPC_REGNUM * 8 + 1])); |
/* |
err = gdb_write_reg(NPC_CPU_REG_ADD, hex2reg (&p_buf->data[NPC_REGNUM * 8 + 1])); |
if(err > 0){ |
if (DEBUG_GDB) printf("Error %d in rsp_write_reg write --> NPC\n", err); |
put_str_packet ("E01"); |
return; |
} |
*/ |
|
/* Acknowledge. TODO: We always succeed at present, even if the data was |
defective. */ |
|
put_str_packet ("OK"); |
} /* rsp_write_all_regs () */ |
|
2763,9 → 2796,19
// First set the chain |
gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */ |
|
// special case for NPC |
/* special case for NPC */ |
if(regno == NPC_CPU_REG_ADD) |
temp_uint32 = get_npc(); |
/* Also special case for debug group (group 6) registers */ |
else if (((regno >> OR1K_SPG_SIZE_BITS) & 0xff) == OR1K_SPG_DEBUG) |
{ |
if (dbg_regs_cache_dirty == -1) // Regs invalid, get them |
get_debug_registers(); |
|
uint32_t * dbg_reg_array = (uint32_t *) &or1k_dbg_group_regs_cache; |
temp_uint32 = dbg_reg_array[(regno & 0xff)]; |
dbg_regs_cache_dirty = 0; |
} |
else |
{ |
err = gdb_read_reg(regno, &temp_uint32); |
2817,6 → 2860,16
// special case for NPC |
if(regno == NPC_CPU_REG_ADD) |
set_npc(val); |
/* Also special case for debug group (group 6) registers */ |
else if (((regno >> OR1K_SPG_SIZE_BITS) & 0xff) == OR1K_SPG_DEBUG) |
{ |
if (dbg_regs_cache_dirty == -1) // Regs invalid, get them |
get_debug_registers(); |
|
uint32_t * dbg_reg_array = (uint32_t *) &or1k_dbg_group_regs_cache; |
dbg_reg_array[(regno & 0xff)] = val; |
dbg_regs_cache_dirty = 1; |
} |
else |
{ |
|
2883,25 → 2936,14
// First set the chain |
err = gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */ |
if(err > 0){ |
if (DEBUG_GDB) printf("Error %d in gdb_set_chain\n", err); |
if (DEBUG_GDB) printf("Error %d in gdb_set_chain\n", err); |
put_str_packet ("E01"); |
return; |
} |
// OR32 Arc sim equivalent --> set_npc (rsp.start_addr); |
return; |
} |
|
/* Set NPC to reset vector 0x100 */ |
set_npc(rsp.start_addr); |
/* |
err = gdb_write_reg(NPC_CPU_REG_ADD, rsp.start_addr); |
if(err > 0){ |
if (DEBUG_GDB) printf("Error %d in rsp_restart write Reg. %x = 0x%08x\n", err, NPC_CPU_REG_ADD, rsp.start_addr); |
put_str_packet ("E01"); |
return; |
} |
|
else{ |
if (DEBUG_GDB) printf("Error %d Command Reset. Set NPC to Start vector %x = 0x%08x\n", err, NPC_CPU_REG_ADD, rsp.start_addr); |
} |
*/ |
|
} /* rsp_restart () */ |
|
|
2931,17 → 2973,8
|
if (0 == strcmp ("s", p_buf->data)) |
{ |
// Arc Sim Code --> addr = cpu_state.pc; /* Default uses current NPC */ |
/* ---------- Npc ---------- */ |
addr = get_npc(); |
/* |
err = gdb_read_reg(NPC_CPU_REG_ADD, &addr); |
if(err > 0){ |
printf("Error %d to read NPC in the STEP command 's'\n", err); |
rsp_client_close (); |
return; |
} |
*/ |
} |
else if (1 != sscanf (p_buf->data, "s%x", &addr)) |
{ |
2948,21 → 2981,11
fprintf (stderr, |
"Warning: RSP step address %s not recognized: ignored\n", |
p_buf->data); |
|
// Arc Sim Code --> addr = cpu_state.pc; /* Default uses current NPC */ |
|
/* ---------- NPC ---------- */ |
addr = get_npc(); |
/* |
err = gdb_read_reg(NPC_CPU_REG_ADD, &addr); |
if(err > 0){ |
printf("Error %d to read NPC in the STEP command 's'\n", err); |
rsp_client_close (); |
return; |
} |
*/ |
} |
|
//if (DEBUG_GDB) printf("rsp_step() --> Read NPC = 0x%08x\n", addr); |
rsp_step_generic (addr, EXCEPT_NONE); |
|
} /* rsp_step () */ |
3005,30 → 3028,21
|
set_npc (addr); |
|
/* Clear Debug Reason Register (DRR) 0x3015 */ |
// Arc sim --> cpu_state.sprs[SPR_DRR] = 0; |
if(gdb_write_reg(DRR_CPU_REG_ADD, 0)) printf("Error write to DRR register\n"); |
|
/* Clear watchpoint break generation in Debug Mode Register 2 (DMR2) 0x3011 */ |
// Arc sim --> cpu_state.sprs[SPR_DMR2] &= ~SPR_DMR2_WGB; |
if(gdb_read_reg(DMR2_CPU_REG_ADD, &temp_uint32)) printf("Error read from DMR2 register\n"); |
temp_uint32 &= ~SPR_DMR2_WGB; |
if(gdb_write_reg(DMR2_CPU_REG_ADD, temp_uint32)) printf("Error write to DMR2 register\n"); |
|
/* Set the single step trigger in Debug Mode Register 1 (DMR1) Register 0x3010 */ |
// Arc sim --> cpu_state.sprs[SPR_DMR1] |= SPR_DMR1_ST; |
if(gdb_read_reg(DMR1_CPU_REG_ADD, &temp_uint32)) printf("Error read from DMR1 register\n"); |
temp_uint32 |= SPR_DMR1_ST; |
if(gdb_write_reg(DMR1_CPU_REG_ADD, temp_uint32)) printf("Error write to DMR1 register\n"); |
|
/* Set traps to be handled by the debug unit in the Debug Stop Register (DSR) Register 0x3014 */ |
// Arc sim --> cpu_state.sprs[SPR_DSR] |= SPR_DSR_TE; |
if(gdb_read_reg(DSR_CPU_REG_ADD, &temp_uint32)) printf("Error read from DSR register\n"); |
temp_uint32 |= SPR_DSR_TE; |
if(gdb_write_reg(DSR_CPU_REG_ADD, temp_uint32)) printf("Error write to DSR register\n"); |
or1k_dbg_group_regs_cache.drr = 0; // Clear DRR |
or1k_dbg_group_regs_cache.dmr1 |= SPR_DMR1_ST; // Stepping, so enable step in DMR1 |
or1k_dbg_group_regs_cache.dsr |= SPR_DSR_TE; // Enable trap handled by DU |
or1k_dbg_group_regs_cache.dmr2 &= ~SPR_DMR2_WGB; // Stepping, so disable breakpoints from watchpoints |
dbg_regs_cache_dirty = 1; // Always write the cache back |
|
/* Commit all debug registers */ |
if (dbg_regs_cache_dirty == 1) |
put_debug_registers(); |
|
/* Unstall the processor */ |
set_stall_state (0); |
|
/* Debug regs cache now in invalid state */ |
dbg_regs_cache_dirty = -1; |
|
/* Note the GDB client is now waiting for a reply. */ |
rsp.client_waiting = 1; |
3264,6 → 3278,248
|
} /* rsp_write_mem_bin () */ |
|
/*---------------------------------------------------------------------------*/ |
/*!Copy the debug group registers from the processor into our cache struct |
*/ |
/*---------------------------------------------------------------------------*/ |
static void |
get_debug_registers(void) |
{ |
|
if (dbg_regs_cache_dirty != -1) return; // Don't need to update them |
|
if (DEBUG_GDB) |
printf("gdb - get_debug_registers() - reading %d bytes for debug regs\n",sizeof(or1k_dbg_group_regs_cache)); |
|
|
err = gdb_set_chain(SC_RISC_DEBUG); /* Register Chain */ |
/* Fill our debug group registers struct */ |
gdb_read_block((OR1K_SPG_DEBUG << OR1K_SPG_SIZE_BITS), |
(uint32_t *) &or1k_dbg_group_regs_cache, |
(uint32_t) sizeof(or1k_dbg_group_regs_cache)); |
dbg_regs_cache_dirty = 0; // Just updated it so not dirty |
|
if (DEBUG_GDB) |
{ |
printf("gdb - get_debug_registers() - registers:\n\t"); |
uint32_t * regs_ptr = (uint32_t*) &or1k_dbg_group_regs_cache; |
int i; |
for(i=0;i<(sizeof(or1k_dbg_group_regs_cache)/4);i++) |
{ if (i%4==0)printf("\n\t"); |
if (i<8) |
printf("DVR%.2d %.8x ",i,regs_ptr[i]); |
else if (i<16) |
printf("DCR%.2d %.8x ",i-8,regs_ptr[i]); |
else if (i<17) |
printf("DMR1 %.8x ",regs_ptr[i]); |
else if (i<18) |
printf("DMR2 %.8x ",regs_ptr[i]); |
else if (i<19) |
printf("DCWR0 %.8x ",regs_ptr[i]); |
else if (i<20) |
printf("DCWR1 %.8x ",regs_ptr[i]); |
else if (i<21) |
printf("DSR %.8x ",regs_ptr[i]); |
else if (i<22) |
printf("DRR %.8x ",regs_ptr[i]); |
|
} |
printf("\n"); |
} |
return; |
} /* get_debug_registers() */ |
|
/*---------------------------------------------------------------------------*/ |
/*!Copy the debug group registers from our cache to the processor |
*/ |
/*---------------------------------------------------------------------------*/ |
static void |
put_debug_registers(void) |
{ |
/* TODO: Block CPU registers write functionality */ |
if (DEBUG_GDB) printf("gdb - put_debug_registers()\n"); |
int i; |
uint32_t *dbg_regs_ptr = (uint32_t *) &or1k_dbg_group_regs_cache; |
|
if (DEBUG_GDB) |
{ |
printf("gdb - put_debug_registers() - registers:\n\t"); |
uint32_t * regs_ptr = (uint32_t*) &or1k_dbg_group_regs_cache; |
int i; |
for(i=0;i<(sizeof(or1k_dbg_group_regs_cache)/4);i++) |
{ if (i%4==0)printf("\n\t"); |
if (i<8) |
printf("DVR%.2d %.8x ",i,regs_ptr[i]); |
else if (i<16) |
printf("DCR%.2d %.8x ",i-8,regs_ptr[i]); |
else if (i<17) |
printf("DMR1 %.8x ",regs_ptr[i]); |
else if (i<18) |
printf("DMR2 %.8x ",regs_ptr[i]); |
else if (i<19) |
printf("DCWR0 %.8x ",regs_ptr[i]); |
else if (i<20) |
printf("DCWR1 %.8x ",regs_ptr[i]); |
else if (i<21) |
printf("DSR %.8x ",regs_ptr[i]); |
else if (i<22) |
printf("DRR %.8x ",regs_ptr[i]); |
|
} |
printf("\n"); |
} |
|
err = gdb_set_chain(SC_RISC_DEBUG); /* Register Chain */ |
|
gdb_write_block((OR1K_SPG_DEBUG << OR1K_SPG_SIZE_BITS), |
(uint32_t *) &or1k_dbg_group_regs_cache, |
sizeof(or1k_dbg_group_regs_cache)); |
|
return; |
|
} /* put_debug_registers() */ |
|
/*---------------------------------------------------------------------------*/ |
/*!Find the DVR/DCR pair corresponding to the address |
|
@return the number, 0-7 of the DCR/DVR pair, if possible, -1 else. */ |
/*---------------------------------------------------------------------------*/ |
static int |
find_matching_dcrdvr_pair(uint32_t addr, uint32_t cc) |
{ |
int i; |
for (i=0;i<OR1K_MAX_MATCHPOINTS; i++) |
{ |
// Find the one matching according to address, and in use |
if ((or1k_dbg_group_regs_cache.dvr[i] == addr) && |
(or1k_dbg_group_regs_cache.dcr[i].cc == cc)) |
{ |
/* |
if (DEBUG_GDB) printf("gdb - find_matching_dcrdvr_pair(%.8x, %d)\n",addr, cc); |
if (DEBUG_GDB) printf("gdb - find_matching_dcrdvr_pair match in %d: dvr[%d] = %.8x dcr[%d].cc=%d\n", |
i,i,or1k_dbg_group_regs_cache.dvr[i],i,or1k_dbg_group_regs_cache.dcr[i].cc); |
*/ |
return i; |
} |
} |
|
// If the loop finished, no appropriate matchpoints |
return -1; |
} /* find_matching_dcrdvr_pair() */ |
/*---------------------------------------------------------------------------*/ |
/*!Count number of free DCR/DVR pairs |
|
@return the number, 0-7 */ |
/*---------------------------------------------------------------------------*/ |
static int |
count_free_dcrdvr_pairs(void) |
{ |
int i, free=0; |
for (i=0;i<OR1K_MAX_MATCHPOINTS; i++) |
{ |
if ((or1k_dbg_group_regs_cache.dcr[i].cc == OR1K_CC_MASKED) // If compare condition is masked, it's not used |
&& or1k_dbg_group_regs_cache.dcr[i].dp ) // and the debug point is present |
free++; |
} |
|
|
return free; |
} /* count_free_dcrdvr_pairs() */ |
|
/*---------------------------------------------------------------------------*/ |
/*!Find a free hardware breakpoint register, DCR/DVR pair |
|
@return the number, 0-7 of the DCR/DVR pair, if possible, -1 else. */ |
/*---------------------------------------------------------------------------*/ |
static int |
find_free_dcrdvr_pair(void) |
{ |
int i; |
for (i=0;i<OR1K_MAX_MATCHPOINTS; i++) |
{ |
if ((or1k_dbg_group_regs_cache.dcr[i].cc == OR1K_CC_MASKED) // If compare condition is masked, it's not used |
&& or1k_dbg_group_regs_cache.dcr[i].dp ) // and the debug point is present |
return i; |
} |
|
// If the loop finished, no free matchpoints |
return -1; |
} /* find_free_dcrdvr_pair() */ |
|
/*---------------------------------------------------------------------------*/ |
/*!Setup a DCR/DVR pair for our watchpoint. |
@param[in] wp_num The watchpoint number |
@param[in] address The address for watchpoint |
*/ |
/*---------------------------------------------------------------------------*/ |
static void |
insert_hw_watchpoint(int wp_num, uint32_t address, uint32_t cc) |
{ |
if (DEBUG_GDB) printf("gdb - insert_hw_watchpoint(%d, 0x%.8x)\n",wp_num, address); |
or1k_dbg_group_regs_cache.dvr[wp_num] = address; |
|
or1k_dbg_group_regs_cache.dcr[wp_num].cc = cc; |
or1k_dbg_group_regs_cache.dcr[wp_num].sc = 0; |
or1k_dbg_group_regs_cache.dcr[wp_num].ct = OR1K_CT_FETCH; // Instruction fetch address |
|
// Mark the debug reg cache as dirty |
dbg_regs_cache_dirty = 1; |
return; |
|
} /* insert_hw_watchpoint() */ |
|
/*---------------------------------------------------------------------------*/ |
/*!Remove/free a DCR/DVR watchpoint pair |
@param[in] wp_num The watchpoint number |
*/ |
/*---------------------------------------------------------------------------*/ |
static void |
remove_hw_watchpoint(int wp_num) |
{ |
or1k_dbg_group_regs_cache.dvr[wp_num] = 0; |
|
or1k_dbg_group_regs_cache.dcr[wp_num].cc = OR1K_CC_MASKED; // We only do equals for now |
or1k_dbg_group_regs_cache.dcr[wp_num].sc = 0; |
|
/* Auto-disable it as generating a breakpoint, too, although maybe gets done after |
this call anyway. Best to ensure. */ |
disable_hw_breakpoint(wp_num); |
|
// Mark the debug reg cache as dirty |
dbg_regs_cache_dirty = 1; |
return; |
|
} /* remove_hw_watchpoint() */ |
|
/*---------------------------------------------------------------------------*/ |
/*!Enable a DCR/DVR watchpoint to generate a breakpoint |
@param[in] wp_num The watchpoint number |
*/ |
/*---------------------------------------------------------------------------*/ |
static void |
enable_hw_breakpoint(int wp_num) |
{ |
// Set the corresponding bit in DMR2 to enable matchpoint 'num' to trigger a breakpoint |
or1k_dbg_group_regs_cache.dmr2 |= (uint32_t) (1 << (SPR_DMR2_WGB_OFF + wp_num)); |
// Mark the debug reg cache as dirty |
dbg_regs_cache_dirty = 1; |
return; |
} /* enable_hw_breakpoint() */ |
|
/*---------------------------------------------------------------------------*/ |
/*!Disable a DCR/DVR watchpoint from generating a breakpoint |
@param[in] wp_num The watchpoint number |
*/ |
/*---------------------------------------------------------------------------*/ |
static void |
disable_hw_breakpoint(int wp_num) |
{ |
// Set the corresponding bit in DMR2 to enable matchpoint 'num' to trigger a breakpoint |
or1k_dbg_group_regs_cache.dmr2 &= (uint32_t) ~(1 << (SPR_DMR2_WGB_OFF + wp_num)); |
// Mark the debug reg cache as dirty |
dbg_regs_cache_dirty = 1; |
return; |
} /* disable_hw_breakpoint() */ |
|
/*---------------------------------------------------------------------------*/ |
/*!Handle a RSP remove breakpoint or matchpoint request |
3283,6 → 3539,7
uint32_t addr; /* Address specified */ |
int len; /* Matchpoint length (not used) */ |
struct mp_entry *mpe; /* Info about the replaced instr */ |
int wp_num; |
|
/* Break out the instruction */ |
if (3 != sscanf (p_buf->data, "z%1d,%x,%1d", (int *)&type, &addr, &len)) |
3334,7 → 3591,42
return; |
|
case BP_HARDWARE: |
put_str_packet (""); /* Not supported */ |
/* Adding support -- jb 090901 */ |
if (dbg_regs_cache_dirty == -1) // Regs invalid, get them |
get_debug_registers(); |
|
if (DEBUG_GDB) printf("gdb - rsp_remove_matchpoint() - hardware mp remove at addr %.8x\n",addr); |
#ifdef HWBP_BTWN |
// Find the first of the pair of dcr/dvr registers |
wp_num = find_matching_dcrdvr_pair(addr-4,OR1K_CC_GE); |
#else |
wp_num = find_matching_dcrdvr_pair(addr,OR1K_CC_EQ); |
remove_hw_watchpoint(wp_num); |
#endif |
if ( wp_num < 0 ) |
{ |
printf("gdb - rsp_remove_matchpoint() failed to remove hardware breakpoint at addr %.8x\n", |
addr); |
put_str_packet ("E01"); /* Cannot remove */ |
return; |
} |
|
if (DEBUG_GDB) printf("gdb - rsp_remove_matchpoint() - mp to remove in DCR/DVR pair %d \n",wp_num); |
remove_hw_watchpoint(wp_num); |
|
#ifdef HWBP_BTWN |
wp_num++; |
/* Should probably check here that this is correct. Oh well. */ |
remove_hw_watchpoint(wp_num); |
// Unchain these |
or1k_dbg_group_regs_cache.dmr1 &= ~(SPR_DMR1_CW << (wp_num * SPR_DMR1_CW_SZ)); |
#endif |
|
// Disable breakpoint generation |
disable_hw_breakpoint(wp_num); |
|
|
put_str_packet ("OK"); |
return; |
|
case WP_WRITE: |
3358,7 → 3650,6
} |
} /* rsp_remove_matchpoint () */ |
|
|
/*---------------------------------------------------------------------------*/ |
/*!Handle a RSP insert breakpoint or matchpoint request |
|
3376,7 → 3667,8
enum mp_type type; /* What sort of matchpoint */ |
uint32_t addr; /* Address specified */ |
int len; /* Matchpoint length (not used) */ |
uint32_t instr; |
uint32_t instr; |
int wp_num; |
|
/* Break out the instruction */ |
if (3 != sscanf (p_buf->data, "Z%1d,%x,%1d", (int *)&type, &addr, &len)) |
3423,7 → 3715,53
return; |
|
case BP_HARDWARE: // hardware-breakpoint Z1 hbreak |
put_str_packet (""); /* Not supported */ |
/* Adding support -- jb 090901 */ |
get_debug_registers(); // First update our copy of the debug registers |
|
#ifdef HWBP_BTWN |
if (count_free_dcrdvr_pairs() < 2) /* Need at least two spare watchpoints free */ |
put_str_packet (""); /* Cannot add */ |
#endif |
|
wp_num = find_free_dcrdvr_pair(); |
|
if (wp_num == -1) |
{ |
put_str_packet (""); /* Could not find a place to put the breakpoint */ |
|
} |
|
#ifdef HWBP_BTWN |
if ((wp_num >= OR1K_MAX_MATCHPOINTS-1) |
|| (wp_num %2 != 0)) /* Should have gotten either, 0,2,4,6 */ |
{ |
/* Something is wrong - can't do it */ |
put_str_packet (""); |
return; |
} |
|
// First watchpoint to watch for address greater than the address |
insert_hw_watchpoint(wp_num, addr-4, OR1K_CC_GE); |
|
wp_num++; // The watchpoints should be next to each other. |
|
// Second watchpoint to watch for address less than the address |
insert_hw_watchpoint(wp_num, addr+4, OR1K_CC_LE); |
|
// Chain these two together |
// First clear the chain settings for this wp (2 bits per) |
or1k_dbg_group_regs_cache.dmr1 &= ~(SPR_DMR1_CW << (wp_num * SPR_DMR1_CW_SZ)); |
// We will trigger a match when wp-1 {_-*{>AND<}*-_} wp go off. |
or1k_dbg_group_regs_cache.dmr1 |= (SPR_DMR1_CW_AND << (wp_num * SPR_DMR1_CW_SZ)); |
// Now enable this send wp (the higher of the two) to trigger a matchpoint |
#else |
/* Simply insert a watchpoint at the address */ |
insert_hw_watchpoint(wp_num, addr, OR1K_CC_EQ); |
|
#endif |
|
enable_hw_breakpoint(wp_num); |
put_str_packet ("OK"); |
return; |
|
case WP_WRITE: // write-watchpoint Z2 watch |
3505,7 → 3843,7
int gdb_read_reg(uint32_t adr, uint32_t *data) { |
if (DEBUG_CMDS) printf("rreg %d\n", gdb_chain); |
switch (gdb_chain) { |
case SC_RISC_DEBUG: return dbg_cpu0_read(adr, data) ? ERR_CRC : ERR_NONE; |
case SC_RISC_DEBUG: return dbg_cpu0_read(adr, data, 4) ? ERR_CRC : ERR_NONE; |
case SC_REGISTER: return dbg_cpu0_read_ctrl(adr, (unsigned char*)data) ? |
ERR_CRC : ERR_NONE; |
case SC_WISHBONE: return dbg_wb_read32(adr, data) ? ERR_CRC : ERR_NONE; |
3536,7 → 3874,7
if (DEBUG_CMDS) printf("wreg %d\n", gdb_chain); fflush (stdout); |
switch (gdb_chain) { /* remap registers, to be compatible with jp1 */ |
case SC_RISC_DEBUG: if (adr == JTAG_RISCOP) adr = 0x00; |
return dbg_cpu0_write(adr, data) ? ERR_CRC : ERR_NONE; |
return dbg_cpu0_write(adr, &data, 4) ? ERR_CRC : ERR_NONE; |
case SC_REGISTER: return dbg_cpu0_write_ctrl(adr, data) ? ERR_CRC : ERR_NONE; |
case SC_WISHBONE: return dbg_wb_write32(adr, data) ? ERR_CRC : ERR_NONE; |
case SC_TRACE: return 0; |
3545,10 → 3883,10
} |
|
int gdb_read_block(uint32_t adr, uint32_t *data, int len) { |
if (DEBUG_CMDS) printf("rb %d\n", gdb_chain); fflush (stdout); |
if (DEBUG_CMDS) printf("rb %d len %d\n", gdb_chain, len); fflush (stdout); |
switch (gdb_chain) { |
case SC_WISHBONE: return dbg_wb_read_block32(adr, data, len) ? |
ERR_CRC : ERR_NONE; |
case SC_RISC_DEBUG: return dbg_cpu0_read(adr, data, len) ? ERR_CRC : ERR_NONE; |
case SC_WISHBONE: return dbg_wb_read_block32(adr, data, len) ? ERR_CRC : ERR_NONE; |
default: return JTAG_PROXY_INVALID_CHAIN; |
} |
} |
3556,6 → 3894,7
int gdb_write_block(uint32_t adr, uint32_t *data, int len) { |
if (DEBUG_CMDS) printf("wb %d\n", gdb_chain); fflush (stdout); |
switch (gdb_chain) { |
case SC_RISC_DEBUG: return dbg_cpu0_write(adr, data, len) ? ERR_CRC : ERR_NONE; |
case SC_WISHBONE: return dbg_wb_write_block32(adr, data, len) ? |
ERR_CRC : ERR_NONE; |
default: return JTAG_PROXY_INVALID_CHAIN; |
/bench/verilog/vpi/verilog/vpi_debug_module.v
201,15 → 201,24
begin |
|
$get_command_address(cmd_adr); |
|
$get_command_data(block_cmd_length); |
|
$get_command_block_data(block_cmd_length, data_storage); |
|
$get_command_data(cmd_data); |
|
if (block_cmd_length > 4) |
cpu_write_block(cmd_adr, block_cmd_length); |
else |
begin |
cmd_data = data_storage[0]; // Get the single word we'll write |
cpu_write_32(cmd_data, cmd_adr,16'h3); |
`ifdef VPI_DEBUG_INFO |
$display("CPU reg write. adr: 0x%x (reg group: %d reg#: %d), val: 0x%x", |
cmd_adr,cmd_adr[15:11], cmd_adr[10:0], cmd_data); |
`endif |
end |
|
cpu_write_32(cmd_data, cmd_adr,16'h3); |
|
|
end |
|
218,15 → 227,27
|
$get_command_address(cmd_adr); |
|
cpu_read_32(cmd_data, cmd_adr, 16'h3); |
$get_command_data(block_cmd_length); // Added 090901 --jb |
|
/* Depending on size, issue a block or single read */ |
if (block_cmd_length > 4 ) |
cpu_read_block(cmd_adr, block_cmd_length); |
else |
cpu_read_32(cmd_data, cmd_adr, 16'h3); |
|
|
`ifdef VPI_DEBUG_INFO |
$display("CPU reg read. adr: 0x%x (reg group: %d reg#: %d), val: 0x%x", |
cmd_adr,cmd_adr[15:11], cmd_adr[10:0], cmd_data); |
if (cmd_size > 4 ) |
$display("CPU reg read. block adr: 0x%x (reg group: %d reg#: %d), num: %d", |
cmd_adr,cmd_adr[15:11], cmd_adr[10:0], block_cmd_length); |
else |
$display("CPU reg read. adr: 0x%x (reg group: %d reg#: %d), val: 0x%x", |
cmd_adr,cmd_adr[15:11], cmd_adr[10:0], cmd_data); |
`endif |
|
$return_command_data(cmd_data); |
|
$return_command_block_data(block_cmd_length, data_storage); |
|
end |
|
`CMD_WB_WR : |
1255,8 → 1276,32
end |
endtask |
|
// block of 32-bit reads from cpu |
task cpu_read_block; |
//output [31:0] data; |
input [`DBG_WB_ADR_LEN -1:0] addr; |
input [`DBG_WB_LEN_LEN -1:0] length; |
|
reg [31:0] tmp; |
|
begin |
debug_cpu_wr_comm(`DBG_CPU_READ, addr, length-1, 1'b0); |
|
last_cpu_cmd = `DBG_CPU_READ; last_cpu_cmd_text = "DBG_CPU_READ"; |
|
length_global = length; |
|
debug_cpu_go(1'b0, 1'b0); |
|
//data = data_storage[0]; |
|
//if (length>3) |
// $display("WARNING: Only first data word is returned( See module %m.)"); |
|
end |
endtask |
|
|
// 32-bit write to cpu |
task cpu_write_32; |
input [31:0] data; |
1276,8 → 1321,24
end |
endtask |
|
// block of 32-bit writes to cpu |
// Data will already be in data_storage |
task cpu_write_block; |
//input [31:0] data; |
input [`DBG_WB_ADR_LEN -1:0] addr; |
input [`DBG_WB_LEN_LEN -1:0] length; |
|
reg [31:0] tmp; |
|
begin |
debug_cpu_wr_comm(`DBG_CPU_WRITE, addr, length-1, 1'b0); |
last_cpu_cmd = `DBG_CPU_WRITE; last_cpu_cmd_text = "DBG_CPU_WRITE"; |
length_global = length; |
debug_cpu_go(1'b0, 1'b0); |
end |
endtask |
|
|
task debug_cpu_wr_comm; |
input [`DBG_CPU_ACC_TYPE_LEN -1:0] acc_type; |
input [`DBG_CPU_ADR_LEN -1:0] addr; |
/rtl/verilog/or1200_defines.v
363,8 → 363,8
// (consider available FPGA memory resources) |
// |
//`define OR1200_IC_1W_512B |
`define OR1200_IC_1W_4KB |
//`define OR1200_IC_1W_8KB |
//`define OR1200_IC_1W_4KB |
`define OR1200_IC_1W_8KB |
`define OR1200_DC_1W_4KB |
//`define OR1200_DC_1W_8KB |
|
985,7 → 985,7
// however already enough for use |
// with or32 gdb) |
// |
//`define OR1200_DU_HWBKPTS |
`define OR1200_DU_HWBKPTS |
|
// Number of DVR/DCR pairs if HW breakpoints enabled |
`define OR1200_DU_DVRDCR_PAIRS 8 |
1061,8 → 1061,8
// DMR2 bits |
`define OR1200_DU_DMR2_WCE0 0 |
`define OR1200_DU_DMR2_WCE1 1 |
`define OR1200_DU_DMR2_AWTC 12:2 |
`define OR1200_DU_DMR2_WGB 23:13 |
`define OR1200_DU_DMR2_AWTC 11:2 |
`define OR1200_DU_DMR2_WGB 23:12 |
|
// DWCR bits |
`define OR1200_DU_DWCR_COUNT 15:0 |
/rtl/verilog/components/smii/smii_txrx.v
1,293 → 1,371
////////////////////////////////////////////////////////////////////// |
//// //// |
//// SMII //// |
//// //// |
//// Description //// |
//// Low pin count serial MII ethernet interface //// |
//// //// |
//// To Do: //// |
//// - //// |
//// //// |
//// Author(s): //// |
//// - Michael Unneback, unneback@opencores.org //// |
//// ORSoC AB michael.unneback@orsoc.se //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source 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 Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
module smii_txrx |
( |
// SMII |
output tx, |
input rx, |
// MII |
// TX |
input [3:0] mtxd, |
input mtxen, |
input mtxerr, |
output mtx_clk, |
// RX |
output reg [3:0] mrxd, |
output reg mrxdv, |
output reg mrxerr, |
output mrx_clk, |
output mcoll, |
output reg mcrs, |
`ifdef SMII_SPEED |
output reg speed, |
`endif |
`ifdef SMII_DUPLEX |
output reg duplex, |
`endif |
`ifdef SMII_LINK |
output reg link, |
`endif |
// internal |
input [10:1] state, |
// clock and reset |
input clk, |
input rst |
); |
|
reg [7:0] tx_data_reg; |
reg tx_data_reg_valid; |
reg a0; |
reg state_data; |
|
reg [3:0] rx_tmp; |
|
`ifndef SMII_SPEED |
reg speed; |
`endif |
`ifndef SMII_DUPLEX |
reg duplex; |
`endif |
`ifndef SMII_LINK |
reg link; |
`endif |
reg jabber; |
|
reg mtx_clk_tmp, mrx_clk_tmp; |
|
reg [3:0] tx_cnt; |
reg [3:0] rx_cnt; |
|
///////////////////////////////////////////////// |
// Speed |
|
always @ (posedge clk or posedge rst) |
if (rst) |
tx_cnt <= 4'd0; |
else |
if (speed) |
tx_cnt <= 4'd0; |
else if (state[10]) |
if (tx_cnt == 4'd9) |
tx_cnt <= 4'd0; |
else |
tx_cnt <= tx_cnt + 4'd1; |
|
///////////////////////////////////////////////// |
// Transmit |
|
/* Timing scheme: |
On the first clock of segment 0 (so each segment when 100Mb/s, |
fast ethernet, or every 10 segments for 10Mb/s ethernet) we |
deteremine if that segment is data or not, depending on what is |
in the tx_data_reg_valid register. If the MAC wants to transmit |
something, we overwrite the previously sent values when they're |
no longer needed. Once the first nibble is sent, we can then |
overwrite it, and same for the second - so we generate the TX |
clock when state is 5, and sample the new nibble on the next |
clock, same with the second nibble, that is clocked when state |
is 9, and sampled when it is 10, so it gets overwritten when |
we've finished putting it on the serial line.*/ |
|
always @ (posedge clk or posedge rst) |
if (rst) |
mtx_clk_tmp <= 1'b0; |
else |
if ((state[5] | state[9]) & (tx_cnt == 4'd0)) |
mtx_clk_tmp <= 1'b1; |
else if (state[6] | state[10]) |
mtx_clk_tmp <= 1'b0; |
|
`ifdef ACTEL |
gbuf bufg1 |
( |
.CLK(mtx_clk_tmp), |
.GL(mtx_clk) |
); |
`else |
assign #1 mtx_clk = mtx_clk_tmp; |
`endif |
|
// storage of data from MII |
always @ (posedge clk or posedge rst) |
if (rst) |
begin |
tx_data_reg <= 8'd0; |
tx_data_reg_valid <= 1'b0; |
a0 <= 1'b0; |
end |
else |
if ((state[6] | state[10]) & (tx_cnt == 4'd0)) |
begin |
/* Toggale a0 when MII TX_EN goes high */ |
if (!mtxen) |
a0 <= 1'b0; |
else |
a0 <= ~a0; |
|
/* byte will be valid when MII TX_EN |
is high from the MAC */ |
if (!mtxen & !a0) |
tx_data_reg_valid <= 1'b0; |
else if (a0) |
tx_data_reg_valid <= 1'b1; |
|
/* Sample the nibble */ |
if (mtxen & !a0) |
tx_data_reg[3:0] <= mtxd; |
else if (mtxen & a0) |
tx_data_reg[7:4] <= mtxd; |
|
end // if ((state[4] | state[9]) & (tx_cnt == 4'd0)) |
|
|
/* Determine if we output a data byte or the inter-frame sequence |
with status information */ |
always @ (posedge clk or posedge rst) |
if (rst) |
state_data <= 1'b0; |
else |
if (state[1] & (tx_cnt == 4'd0)) |
state_data <= tx_data_reg_valid; |
|
/* A wire hooked up from bit 0 with the last byte of the state counter/shiftreg */ |
wire [7:0] state_data_byte; |
assign state_data_byte[7:0] = state[10:3]; |
|
/* Assign the SMII TX wire */ |
/* First bit always TX_ERR, then depending on the next bit, TX_EN, output |
either the inter-frame status byte or a data byte */ |
assign tx = state[1] ? mtxerr : |
state[2] ? ((tx_data_reg_valid & (tx_cnt == 4'd0)) | state_data) : |
state_data ? |(state_data_byte & tx_data_reg) : |
|(state_data_byte & {3'b111,jabber,link,duplex,speed,mtxerr}); |
|
///////////////////////////////////////////////// |
// Receive |
|
always @ (posedge clk or posedge rst) |
if (rst) |
rx_cnt <= 4'd0; |
else |
if (speed) |
rx_cnt <= 4'd0; |
else if (!mrxdv & state[8] & rx_tmp[3]) |
rx_cnt <= 4'd9; |
else if (state[10]) |
if (rx_cnt == 4'd9) |
rx_cnt <= 4'd0; |
else |
rx_cnt <= rx_cnt + 4'd1; |
|
always @ (posedge clk or posedge rst) |
if (rst) |
begin |
{mcrs, mrxdv, mrxerr, speed, duplex, link, jabber} <= 7'b0001110; |
rx_tmp <= 4'h0; |
mrxd <= 4'h0; |
end |
else |
begin |
/* Continually shift rx into rx_tmp bit 2, and shift rx_tmp along */ |
rx_tmp[2:0] <= {rx,rx_tmp[2:1]}; |
|
/* We appear to be beginning our sampling when state bit 3 is set */ |
if (state[3]) |
mcrs <= rx; |
|
/* rx_tmp[3] is used as the RX_DV bit*/ |
if (state[4]) |
rx_tmp[3] <= rx; |
|
if (rx_tmp[3]) //If data byte valid, and when we've got the first nibble, output it */ |
begin |
/* At this stage we've got the first 3 bits of the bottom |
nibble - we can sample the rx line directly to get the |
4th, and we'll also indicate that this byte is valid by |
raising the MII RX data valid (dv) line. */ |
if (state[8]) |
{mrxdv,mrxd} <= #1 {rx_tmp[3],rx,rx_tmp[2:0]}; |
/* High nibble, we have 3 bits and the final one is on |
the line - put it out for the MAC to read.*/ |
else if (state[2]) |
mrxd <= #1 {rx,rx_tmp[2:0]}; |
end |
else |
begin |
/* Not a data byte, it's the inter-frame status byte */ |
if (state[5]) |
mrxerr <= #1 rx; |
if (state[6]) |
speed <= #1 rx; |
if (state[7]) |
duplex <= #1 rx; |
if (state[8]) |
begin |
link <= #1 rx; |
mrxdv <= #1 1'b0; |
end |
if (state[9]) |
jabber <= #1 rx; |
end |
end // else: !if(rst) |
|
always @ (posedge clk or posedge rst) |
if (rst) |
mrx_clk_tmp <= 1'b0; |
else |
if ((state[1] | state[6]) & (rx_cnt == 4'd0)) |
mrx_clk_tmp <= 1'b1; |
else if (state[3] | state[8]) |
mrx_clk_tmp <= 1'b0; |
|
`ifdef ACTEL |
gbuf bufg2 |
( |
.CLK(mrx_clk_tmp), |
.GL(mrx_clk) |
); |
`else |
assign #1 mrx_clk = mrx_clk_tmp; |
`endif |
|
assign mcoll = mcrs & mtxen & !duplex; |
|
|
endmodule // smii_top |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// SMII //// |
//// //// |
//// Description //// |
//// Low pin count serial MII ethernet interface //// |
//// //// |
//// To Do: //// |
//// - //// |
//// //// |
//// Author(s): //// |
//// - Michael Unneback, unneback@opencores.org //// |
//// ORSoC AB michael.unneback@orsoc.se //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source 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 Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
module smii_txrx |
( |
// SMII |
output tx, |
input rx, |
// MII |
// TX |
input [3:0] mtxd, |
input mtxen, |
input mtxerr, |
output mtx_clk, |
// RX |
output reg [3:0] mrxd, |
output reg mrxdv, |
output reg mrxerr, |
output mrx_clk, |
output mcoll, |
output reg mcrs, |
`ifdef SMII_SPEED |
output reg speed, |
`endif |
`ifdef SMII_DUPLEX |
output reg duplex, |
`endif |
`ifdef SMII_LINK |
output reg link, |
`endif |
// internal |
input [10:1] state, |
// clock and reset |
input clk, |
input rst |
); |
|
reg [7:0] tx_data_reg; |
reg tx_data_reg_valid; |
reg a0; |
reg state_data; |
|
reg [3:0] rx_tmp; |
|
`ifndef SMII_SPEED |
reg speed; |
`endif |
`ifndef SMII_DUPLEX |
reg duplex; |
`endif |
`ifndef SMII_LINK |
reg link; |
`endif |
reg jabber; |
|
reg mtx_clk_tmp, mrx_clk_tmp; |
|
reg [3:0] tx_cnt; |
reg [3:0] rx_cnt; |
|
///////////////////////////////////////////////// |
// Speed |
|
always @ (posedge clk or posedge rst) |
if (rst) |
tx_cnt <= 4'd0; |
else |
if (speed) |
tx_cnt <= 4'd0; |
else if (state[10]) |
if (tx_cnt == 4'd9) |
tx_cnt <= 4'd0; |
else |
tx_cnt <= tx_cnt + 4'd1; |
|
///////////////////////////////////////////////// |
// Transmit |
|
/* Timing scheme: |
If we're fast ethernet, we clock every segment. Otherwise it's every 10 segments for 10mbit ethernet. |
For 10mbit ethernet it doesn't really matter where we clock it - we have plenty of time to put out the right bits. |
For fast ethernet, we have to do it at the right points. |
so the MII TX nibble clocks come on the 8th state of the segment prior to the one we will output, then on the 3rd clock of the segment we're currently outputting.*/ |
`define MII_TXNIB1_CLK 8 |
`define MII_TXNIB2_CLK 3 |
|
// tx_data_reg_valid here helps us make sure we always sample data beginning with the nib1 clock |
`define MII_TX_CLK_ASSERT ( \ |
((state[`MII_TXNIB1_CLK] | (state[`MII_TXNIB2_CLK] & tx_data_reg_valid)) \ |
& \ |
( \ |
((tx_cnt == 4'd0) & speed) | \ |
((tx_cnt == 4'd9) & !(speed) & state[`MII_TXNIB1_CLK]) | \ |
((tx_cnt == 4'd0) & !(speed) & tx_data_reg_valid & state[`MII_TXNIB2_CLK]) \ |
))) |
|
`define MII_TX_CLOCKED ( \ |
((state[`MII_TXNIB1_CLK+1] | (state[`MII_TXNIB2_CLK+1] & tx_data_reg_valid)) \ |
& \ |
( \ |
((tx_cnt == 4'd0) & speed) | \ |
((tx_cnt == 4'd9) & !(speed) & state[`MII_TXNIB1_CLK + 1]) | \ |
((tx_cnt == 4'd0) & !(speed) & tx_data_reg_valid & state[`MII_TXNIB2_CLK + 1]) \ |
))) |
|
always @ (posedge clk or posedge rst) |
if (rst) |
mtx_clk_tmp <= 1'b0; |
else |
if (`MII_TX_CLK_ASSERT) |
mtx_clk_tmp <= 1'b1; |
else //if (state[`MII_TXNIB1_CLK + 1] | state[`MII_TXNIB2_CLK + 1]) |
mtx_clk_tmp <= 1'b0; |
|
`ifdef ACTEL |
gbuf bufg1 |
( |
.CLK(mtx_clk_tmp), |
.GL(mtx_clk) |
); |
`else |
assign mtx_clk = mtx_clk_tmp; |
`endif |
|
// storage of data from MII |
always @ (posedge clk or posedge rst) |
if (rst) |
begin |
tx_data_reg <= 8'd0; |
tx_data_reg_valid <= 1'b0; |
a0 <= 1'b0; |
end |
else |
if (`MII_TX_CLOCKED) |
begin |
/* Toggale a0 when MII TX_EN goes high */ |
if (!mtxen) |
a0 <= 1'b0; |
else |
a0 <= ~a0; |
|
tx_data_reg_valid <= mtxen; |
|
/* Sample the nibble */ |
if (mtxen & !a0) |
tx_data_reg[3:0] <= mtxd; |
else if (mtxen & a0) |
tx_data_reg[7:4] <= mtxd; |
|
end // if ((state[4] | state[9]) & (tx_cnt == 4'd0)) |
|
|
/* Determine if we output a data byte or the inter-frame sequence |
with status information */ |
always @ (posedge clk or posedge rst) |
if (rst) |
state_data <= 1'b0; |
else |
if (state[1] & (tx_cnt == 4'd0)) |
state_data <= tx_data_reg_valid; |
|
/* A wire hooked up from bit 0 with the last byte of the state counter/shiftreg */ |
wire [7:0] state_data_byte; |
assign state_data_byte[7:0] = state[10:3]; |
|
/* Assign the SMII TX wire */ |
/* First bit always TX_ERR, then depending on the next bit, TX_EN, output |
either the inter-frame status byte or a data byte */ |
assign tx = state[1] ? mtxerr : |
state[2] ? ((tx_data_reg_valid & (tx_cnt == 4'd0)) | state_data) : |
state_data ? |(state_data_byte & tx_data_reg) : |
|(state_data_byte & {3'b111,jabber,link,duplex,speed,mtxerr}); |
|
///////////////////////////////////////////////// |
// Receive |
|
always @ (posedge clk or posedge rst) |
if (rst) |
rx_cnt <= 4'd0; |
else |
if (speed) |
rx_cnt <= 4'd0; |
else if (!mrxdv & state[8] & rx_tmp[3]) // Getting ready for data |
rx_cnt <= 4'd9; |
else if (state[10]) // wrap |
if (rx_cnt == 4'd9) |
rx_cnt <= 4'd0; |
else |
rx_cnt <= rx_cnt + 4'd1; |
|
always @ (posedge clk or posedge rst) |
if (rst) |
begin |
{mcrs, mrxdv, mrxerr, speed, duplex, link, jabber} <= 7'b0001110; |
rx_tmp <= 4'h0; |
mrxd <= 4'h0; |
end |
else |
begin |
/* Continually shift rx into rx_tmp bit 2, and shift rx_tmp along */ |
rx_tmp[2:0] <= {rx,rx_tmp[2:1]}; |
`define RX_BEGIN_STATE 3 |
/* We appear to be beginning our sampling when state bit 3 is set */ |
if (state[`RX_BEGIN_STATE]) //3 |
mcrs <= rx; |
|
/* rx_tmp[3] is used as the RX_DV bit*/ |
if (state[`RX_BEGIN_STATE+1]) |
rx_tmp[3] <= rx; |
|
if (rx_tmp[3]) //If data byte valid, and when we've got the first nibble, output it */ |
begin |
/* At this stage we've got the first 3 bits of the bottom |
nibble - we can sample the rx line directly to get the |
4th, and we'll also indicate that this byte is valid by |
raising the MII RX data valid (dv) line. */ |
if (state[`RX_BEGIN_STATE+5]) |
{mrxdv,mrxd} <= {rx_tmp[3],rx,rx_tmp[2:0]}; |
/* High nibble, we have 3 bits and the final one is on |
the line - put it out for the MAC to read.*/ |
else if (state[`RX_BEGIN_STATE-1]) |
mrxd <= {rx,rx_tmp[2:0]}; |
end |
else |
begin |
/* Not a data byte, it's the inter-frame status byte */ |
if (state[`RX_BEGIN_STATE+2]) |
mrxerr <= rx; |
if (state[`RX_BEGIN_STATE+3]) |
speed <= rx; |
if (state[`RX_BEGIN_STATE+4]) |
duplex <= rx; |
if (state[`RX_BEGIN_STATE+5]) |
begin |
link <= rx; |
mrxdv <= 1'b0; |
end |
if (state[`RX_BEGIN_STATE+6]) |
jabber <= rx; |
end |
end // else: !if(rst) |
|
always @ (posedge clk or posedge rst) |
if (rst) |
mrx_clk_tmp <= 1'b0; |
else |
//if ((state[1] | state[6]) & (rx_cnt == 4'd0)) |
if (((state[`RX_BEGIN_STATE+3] | state[`RX_BEGIN_STATE-1]) & (rx_cnt == 4'd0) & speed) |
| ((((state[`RX_BEGIN_STATE+3] & (rx_cnt == 4'd0)) | (state[`RX_BEGIN_STATE-1]) & (rx_cnt == 4'd1) & !speed ) ))) |
mrx_clk_tmp <= 1'b1; |
//else if (state[3] | state[8]) |
else if (state[`RX_BEGIN_STATE+5] | state[`RX_BEGIN_STATE+1]) |
mrx_clk_tmp <= 1'b0; |
|
`ifdef ACTEL |
gbuf bufg2 |
( |
.CLK(mrx_clk_tmp), |
.GL(mrx_clk) |
); |
`else |
assign mrx_clk = mrx_clk_tmp; |
`endif |
|
assign mcoll = mcrs & mtxen & !duplex; |
|
|
endmodule // smii_top |
|
module smii_sync |
( |
// SMII sync |
output sync, |
// internal |
output reg [10:1] state, |
// clock amd reset |
input clk, |
input rst |
); |
|
// sync shall go high every 10:th cycle |
always @ (posedge clk or posedge rst) |
if (rst) |
state <= 10'b0000000001; |
else |
state <= {state[9:1],state[10]}; |
|
assign sync = state[1]; |
|
endmodule // smii_sync |
|
module obufdff |
( |
input d, |
output reg pad, |
input clk, |
input rst |
); |
always @ (posedge clk or posedge rst) |
if (rst) |
pad <= 1'b0; |
else |
pad <= d; |
endmodule |
module ibufdff |
( |
input pad, |
output reg q, |
input clk, |
input rst |
); |
always @ (posedge clk or posedge rst) |
if (rst) |
q <= 1'b0; |
else |
q <= pad; |
endmodule |
module iobuftri |
( |
input i, |
input oe, |
output o, |
inout pad |
); |
assign pad = oe ? i : 1'bz; |
assign o = pad; |
endmodule |
module obuf |
( |
input i, |
inout pad |
); |
assign pad = i; |
endmodule |
/rtl/verilog/components/debug_if/dbg_cpu.v
685,7 → 685,8
else if (set_addr_cpu && (!set_addr_cpu_q)) // Setting starting address |
cpu_addr_dsff <= #1 adr; |
else if (cpu_ack_i && (!cpu_ack_q)) |
cpu_addr_dsff <= #1 cpu_addr_dsff + 3'd4; |
//cpu_addr_dsff <= #1 cpu_addr_dsff + 3'd4; |
cpu_addr_dsff <= #1 cpu_addr_dsff + 3'd1; // Increment by just 1, to allow block reading -- jb 090901 |
end |
|
|
/rtl/verilog/components/or1200r2/or1200_du.v
830,9 → 830,9
`ifdef OR1200_DU_DCR0 |
always @(posedge clk or posedge rst) |
if (rst) |
dcr0 <= 8'h00; |
dcr0 <= 8'h01; |
else if (dcr0_sel && spr_write) |
dcr0 <= #1 spr_dat_i[7:0]; |
dcr0[7:1] <= #1 spr_dat_i[7:1]; |
`else |
assign dcr0 = 8'h00; |
`endif |
843,9 → 843,9
`ifdef OR1200_DU_DCR1 |
always @(posedge clk or posedge rst) |
if (rst) |
dcr1 <= 8'h00; |
dcr1 <= 8'h01; |
else if (dcr1_sel && spr_write) |
dcr1 <= #1 spr_dat_i[7:0]; |
dcr1[7:1] <= #1 spr_dat_i[7:1]; |
`else |
assign dcr1 = 8'h00; |
`endif |
856,9 → 856,9
`ifdef OR1200_DU_DCR2 |
always @(posedge clk or posedge rst) |
if (rst) |
dcr2 <= 8'h00; |
dcr2 <= 8'h01; |
else if (dcr2_sel && spr_write) |
dcr2 <= #1 spr_dat_i[7:0]; |
dcr2[7:1] <= #1 spr_dat_i[7:1]; |
`else |
assign dcr2 = 8'h00; |
`endif |
869,9 → 869,9
`ifdef OR1200_DU_DCR3 |
always @(posedge clk or posedge rst) |
if (rst) |
dcr3 <= 8'h00; |
dcr3 <= 8'h01; |
else if (dcr3_sel && spr_write) |
dcr3 <= #1 spr_dat_i[7:0]; |
dcr3[7:1] <= #1 spr_dat_i[7:1]; |
`else |
assign dcr3 = 8'h00; |
`endif |
882,9 → 882,9
`ifdef OR1200_DU_DCR4 |
always @(posedge clk or posedge rst) |
if (rst) |
dcr4 <= 8'h00; |
dcr4 <= 8'h01; |
else if (dcr4_sel && spr_write) |
dcr4 <= #1 spr_dat_i[7:0]; |
dcr4[7:1] <= #1 spr_dat_i[7:1]; |
`else |
assign dcr4 = 8'h00; |
`endif |
895,9 → 895,9
`ifdef OR1200_DU_DCR5 |
always @(posedge clk or posedge rst) |
if (rst) |
dcr5 <= 8'h00; |
dcr5 <= 8'h01; |
else if (dcr5_sel && spr_write) |
dcr5 <= #1 spr_dat_i[7:0]; |
dcr5[7:1] <= #1 spr_dat_i[7:1]; |
`else |
assign dcr5 = 8'h00; |
`endif |
908,9 → 908,9
`ifdef OR1200_DU_DCR6 |
always @(posedge clk or posedge rst) |
if (rst) |
dcr6 <= 8'h00; |
dcr6 <= 8'h01; |
else if (dcr6_sel && spr_write) |
dcr6 <= #1 spr_dat_i[7:0]; |
dcr6[7:1] <= #1 spr_dat_i[7:1]; |
`else |
assign dcr6 = 8'h00; |
`endif |
921,9 → 921,9
`ifdef OR1200_DU_DCR7 |
always @(posedge clk or posedge rst) |
if (rst) |
dcr7 <= 8'h00; |
dcr7 <= 8'h01; |
else if (dcr7_sel && spr_write) |
dcr7 <= #1 spr_dat_i[7:0]; |
dcr7[7:1] <= #1 spr_dat_i[7:1]; |
`else |
assign dcr7 = 8'h00; |
`endif |
1111,34 → 1111,44
default:match_cond0_stb = dcpu_cycstb_i; // any load/store |
endcase |
|
// |
// Match Condition 0 |
// |
always @(match_cond0_stb or dcr0 or dvr0 or match_cond0_ct) |
casex ({match_cond0_stb, dcr0[`OR1200_DU_DCR_CC]}) |
4'b0_xxx, |
4'b1_000, |
4'b1_111: match0 = 1'b0; |
4'b1_001: match0 = |
((match_cond0_ct[31] ^ dcr0[`OR1200_DU_DCR_SC]) == |
(dvr0[31] ^ dcr0[`OR1200_DU_DCR_SC])); |
4'b1_010: match0 = |
((match_cond0_ct[31] ^ dcr0[`OR1200_DU_DCR_SC]) < |
(dvr0[31] ^ dcr0[`OR1200_DU_DCR_SC])); |
4'b1_011: match0 = |
((match_cond0_ct[31] ^ dcr0[`OR1200_DU_DCR_SC]) <= |
(dvr0[31] ^ dcr0[`OR1200_DU_DCR_SC])); |
4'b1_100: match0 = |
((match_cond0_ct[31] ^ dcr0[`OR1200_DU_DCR_SC]) > |
(dvr0[31] ^ dcr0[`OR1200_DU_DCR_SC])); |
4'b1_101: match0 = |
((match_cond0_ct[31] ^ dcr0[`OR1200_DU_DCR_SC]) >= |
(dvr0[31] ^ dcr0[`OR1200_DU_DCR_SC])); |
4'b1_110: match0 = |
((match_cond0_ct[31] ^ dcr0[`OR1200_DU_DCR_SC]) != |
(dvr0[31] ^ dcr0[`OR1200_DU_DCR_SC])); |
endcase |
// Debugging hwbkpoint match conditions |
wire match0_dbg1; |
assign match0_dbg1 = (match_cond0_ct[31] ^ dcr0[`OR1200_DU_DCR_SC]); |
wire match0_dbg2; |
assign match0_dbg2 = (dvr0[31] ^ dcr0[`OR1200_DU_DCR_SC]); |
|
|
// |
// Match Condition 0 |
// |
always @(match_cond0_stb or dcr0 or dvr0 or match_cond0_ct) |
casex ({match_cond0_stb, dcr0[`OR1200_DU_DCR_CC]}) |
4'b0_xxx, |
4'b1_000, |
4'b1_111: match0 = 1'b0; |
4'b1_001: match0 = ( match_cond0_ct[30:0] == dvr0[30:0] ); |
4'b1_010: match0 = |
((match_cond0_ct[31] ^ dcr0[`OR1200_DU_DCR_SC]) < |
(dvr0[31] ^ dcr0[`OR1200_DU_DCR_SC]))&& |
( match_cond0_ct[30:0] < dvr0[30:0]); |
4'b1_011: match0 = |
((match_cond0_ct[31] ^ dcr0[`OR1200_DU_DCR_SC]) <= |
(dvr0[31] ^ dcr0[`OR1200_DU_DCR_SC]))&& |
( match_cond0_ct[30:0] <= dvr0[30:0]); |
4'b1_100: match0 = |
((match_cond0_ct[31] ^ dcr0[`OR1200_DU_DCR_SC]) > |
(dvr0[31] ^ dcr0[`OR1200_DU_DCR_SC]))&& |
( match_cond0_ct[30:0] > dvr0[30:0]); |
4'b1_101: match0 = |
((match_cond0_ct[31] ^ dcr0[`OR1200_DU_DCR_SC]) >= |
(dvr0[31] ^ dcr0[`OR1200_DU_DCR_SC]))&& |
( match_cond0_ct[30:0] >= dvr0[30:0]); |
4'b1_110: match0 = |
((match_cond0_ct[31] ^ dcr0[`OR1200_DU_DCR_SC]) != |
(dvr0[31] ^ dcr0[`OR1200_DU_DCR_SC]))&& |
( match_cond0_ct[30:0] != dvr0[30:0]); |
endcase |
|
// |
// Watchpoint 0 |
// |
1175,33 → 1185,36
default:match_cond1_stb = dcpu_cycstb_i; // any load/store |
endcase |
|
// |
// Match Condition 1 |
// |
always @(match_cond1_stb or dcr1 or dvr1 or match_cond1_ct) |
casex ({match_cond1_stb, dcr1[`OR1200_DU_DCR_CC]}) |
4'b0_xxx, |
4'b1_000, |
4'b1_111: match1 = 1'b0; |
4'b1_001: match1 = |
((match_cond1_ct[31] ^ dcr1[`OR1200_DU_DCR_SC]) == |
(dvr1[31] ^ dcr1[`OR1200_DU_DCR_SC])); |
4'b1_010: match1 = |
((match_cond1_ct[31] ^ dcr1[`OR1200_DU_DCR_SC]) < |
(dvr1[31] ^ dcr1[`OR1200_DU_DCR_SC])); |
4'b1_011: match1 = |
((match_cond1_ct[31] ^ dcr1[`OR1200_DU_DCR_SC]) <= |
(dvr1[31] ^ dcr1[`OR1200_DU_DCR_SC])); |
4'b1_100: match1 = |
((match_cond1_ct[31] ^ dcr1[`OR1200_DU_DCR_SC]) > |
(dvr1[31] ^ dcr1[`OR1200_DU_DCR_SC])); |
4'b1_101: match1 = |
((match_cond1_ct[31] ^ dcr1[`OR1200_DU_DCR_SC]) >= |
(dvr1[31] ^ dcr1[`OR1200_DU_DCR_SC])); |
4'b1_110: match1 = |
((match_cond1_ct[31] ^ dcr1[`OR1200_DU_DCR_SC]) != |
(dvr1[31] ^ dcr1[`OR1200_DU_DCR_SC])); |
endcase |
// |
// Match Condition 1 |
// |
always @(match_cond1_stb or dcr1 or dvr1 or match_cond1_ct) |
casex ({match_cond1_stb, dcr1[`OR1200_DU_DCR_CC]}) |
4'b0_xxx, |
4'b1_000, |
4'b1_111: match1 = 1'b0; |
4'b1_001: match1 = ( match_cond1_ct[30:0] == dvr1[30:0] ); |
4'b1_010: match1 = |
((match_cond1_ct[31] ^ dcr1[`OR1200_DU_DCR_SC]) < |
(dvr1[31] ^ dcr1[`OR1200_DU_DCR_SC]))&& |
( match_cond1_ct[30:0] < dvr1[30:0]); |
4'b1_011: match1 = |
((match_cond1_ct[31] ^ dcr1[`OR1200_DU_DCR_SC]) <= |
(dvr1[31] ^ dcr1[`OR1200_DU_DCR_SC]))&& |
( match_cond1_ct[30:0] <= dvr1[30:0]); |
4'b1_100: match1 = |
((match_cond1_ct[31] ^ dcr1[`OR1200_DU_DCR_SC]) > |
(dvr1[31] ^ dcr1[`OR1200_DU_DCR_SC]))&& |
( match_cond1_ct[30:0] > dvr1[30:0]); |
4'b1_101: match1 = |
((match_cond1_ct[31] ^ dcr1[`OR1200_DU_DCR_SC]) >= |
(dvr1[31] ^ dcr1[`OR1200_DU_DCR_SC]))&& |
( match_cond1_ct[30:0] >= dvr1[30:0]); |
4'b1_110: match1 = |
((match_cond1_ct[31] ^ dcr1[`OR1200_DU_DCR_SC]) != |
(dvr1[31] ^ dcr1[`OR1200_DU_DCR_SC]))&& |
( match_cond1_ct[30:0] != dvr1[30:0]); |
endcase |
|
// |
// Watchpoint 1 |
1239,34 → 1252,38
default:match_cond2_stb = dcpu_cycstb_i; // any load/store |
endcase |
|
// |
// Match Condition 2 |
// |
always @(match_cond2_stb or dcr2 or dvr2 or match_cond2_ct) |
casex ({match_cond2_stb, dcr2[`OR1200_DU_DCR_CC]}) |
4'b0_xxx, |
4'b1_000, |
4'b1_111: match2 = 1'b0; |
4'b1_001: match2 = |
((match_cond2_ct[31] ^ dcr2[`OR1200_DU_DCR_SC]) == |
(dvr2[31] ^ dcr2[`OR1200_DU_DCR_SC])); |
4'b1_010: match2 = |
((match_cond2_ct[31] ^ dcr2[`OR1200_DU_DCR_SC]) < |
(dvr2[31] ^ dcr2[`OR1200_DU_DCR_SC])); |
4'b1_011: match2 = |
((match_cond2_ct[31] ^ dcr2[`OR1200_DU_DCR_SC]) <= |
(dvr2[31] ^ dcr2[`OR1200_DU_DCR_SC])); |
4'b1_100: match2 = |
((match_cond2_ct[31] ^ dcr2[`OR1200_DU_DCR_SC]) > |
(dvr2[31] ^ dcr2[`OR1200_DU_DCR_SC])); |
4'b1_101: match2 = |
((match_cond2_ct[31] ^ dcr2[`OR1200_DU_DCR_SC]) >= |
(dvr2[31] ^ dcr2[`OR1200_DU_DCR_SC])); |
4'b1_110: match2 = |
((match_cond2_ct[31] ^ dcr2[`OR1200_DU_DCR_SC]) != |
(dvr2[31] ^ dcr2[`OR1200_DU_DCR_SC])); |
endcase |
|
// |
// Match Condition 2 |
// |
always @(match_cond2_stb or dcr2 or dvr2 or match_cond2_ct) |
casex ({match_cond2_stb, dcr2[`OR1200_DU_DCR_CC]}) |
4'b0_xxx, |
4'b1_000, |
4'b1_111: match2 = 1'b0; |
4'b1_001: match2 = ( match_cond2_ct[30:0] == dvr2[30:0] ); |
4'b1_010: match2 = |
((match_cond2_ct[31] ^ dcr2[`OR1200_DU_DCR_SC]) < |
(dvr2[31] ^ dcr2[`OR1200_DU_DCR_SC]))&& |
( match_cond2_ct[30:0] < dvr2[30:0]); |
4'b1_011: match2 = |
((match_cond2_ct[31] ^ dcr2[`OR1200_DU_DCR_SC]) <= |
(dvr2[31] ^ dcr2[`OR1200_DU_DCR_SC]))&& |
( match_cond2_ct[30:0] <= dvr2[30:0]); |
4'b1_100: match2 = |
((match_cond2_ct[31] ^ dcr2[`OR1200_DU_DCR_SC]) > |
(dvr2[31] ^ dcr2[`OR1200_DU_DCR_SC]))&& |
( match_cond2_ct[30:0] > dvr2[30:0]); |
4'b1_101: match2 = |
((match_cond2_ct[31] ^ dcr2[`OR1200_DU_DCR_SC]) >= |
(dvr2[31] ^ dcr2[`OR1200_DU_DCR_SC]))&& |
( match_cond2_ct[30:0] >= dvr2[30:0]); |
4'b1_110: match2 = |
((match_cond2_ct[31] ^ dcr2[`OR1200_DU_DCR_SC]) != |
(dvr2[31] ^ dcr2[`OR1200_DU_DCR_SC]))&& |
( match_cond2_ct[30:0] != dvr2[30:0]); |
endcase |
|
// |
// Watchpoint 2 |
// |
1303,33 → 1320,37
default:match_cond3_stb = dcpu_cycstb_i; // any load/store |
endcase |
|
// |
// Match Condition 3 |
// |
always @(match_cond3_stb or dcr3 or dvr3 or match_cond3_ct) |
casex ({match_cond3_stb, dcr3[`OR1200_DU_DCR_CC]}) |
4'b0_xxx, |
4'b1_000, |
4'b1_111: match3 = 1'b0; |
4'b1_001: match3 = |
((match_cond3_ct[31] ^ dcr3[`OR1200_DU_DCR_SC]) == |
(dvr3[31] ^ dcr3[`OR1200_DU_DCR_SC])); |
4'b1_010: match3 = |
((match_cond3_ct[31] ^ dcr3[`OR1200_DU_DCR_SC]) < |
(dvr3[31] ^ dcr3[`OR1200_DU_DCR_SC])); |
4'b1_011: match3 = |
((match_cond3_ct[31] ^ dcr3[`OR1200_DU_DCR_SC]) <= |
(dvr3[31] ^ dcr3[`OR1200_DU_DCR_SC])); |
4'b1_100: match3 = |
((match_cond3_ct[31] ^ dcr3[`OR1200_DU_DCR_SC]) > |
(dvr3[31] ^ dcr3[`OR1200_DU_DCR_SC])); |
4'b1_101: match3 = |
((match_cond3_ct[31] ^ dcr3[`OR1200_DU_DCR_SC]) >= |
(dvr3[31] ^ dcr3[`OR1200_DU_DCR_SC])); |
4'b1_110: match3 = |
((match_cond3_ct[31] ^ dcr3[`OR1200_DU_DCR_SC]) != |
(dvr3[31] ^ dcr3[`OR1200_DU_DCR_SC])); |
endcase |
|
// |
// Match Condition 3 |
// |
always @(match_cond3_stb or dcr3 or dvr3 or match_cond3_ct) |
casex ({match_cond3_stb, dcr3[`OR1200_DU_DCR_CC]}) |
4'b0_xxx, |
4'b1_000, |
4'b1_111: match3 = 1'b0; |
4'b1_001: match3 = ( match_cond3_ct[30:0] == dvr3[30:0] ); |
4'b1_010: match3 = |
((match_cond3_ct[31] ^ dcr3[`OR1200_DU_DCR_SC]) < |
(dvr3[31] ^ dcr3[`OR1200_DU_DCR_SC]))&& |
( match_cond3_ct[30:0] < dvr3[30:0]); |
4'b1_011: match3 = |
((match_cond3_ct[31] ^ dcr3[`OR1200_DU_DCR_SC]) <= |
(dvr3[31] ^ dcr3[`OR1200_DU_DCR_SC]))&& |
( match_cond3_ct[30:0] <= dvr3[30:0]); |
4'b1_100: match3 = |
((match_cond3_ct[31] ^ dcr3[`OR1200_DU_DCR_SC]) > |
(dvr3[31] ^ dcr3[`OR1200_DU_DCR_SC]))&& |
( match_cond3_ct[30:0] > dvr3[30:0]); |
4'b1_101: match3 = |
((match_cond3_ct[31] ^ dcr3[`OR1200_DU_DCR_SC]) >= |
(dvr3[31] ^ dcr3[`OR1200_DU_DCR_SC]))&& |
( match_cond3_ct[30:0] >= dvr3[30:0]); |
4'b1_110: match3 = |
((match_cond3_ct[31] ^ dcr3[`OR1200_DU_DCR_SC]) != |
(dvr3[31] ^ dcr3[`OR1200_DU_DCR_SC]))&& |
( match_cond3_ct[30:0] != dvr3[30:0]); |
endcase |
|
// |
// Watchpoint 3 |
1367,34 → 1388,39
default:match_cond4_stb = dcpu_cycstb_i; // any load/store |
endcase |
|
// |
// Match Condition 4 |
// |
always @(match_cond4_stb or dcr4 or dvr4 or match_cond4_ct) |
casex ({match_cond4_stb, dcr4[`OR1200_DU_DCR_CC]}) |
4'b0_xxx, |
4'b1_000, |
4'b1_111: match4 = 1'b0; |
4'b1_001: match4 = |
((match_cond4_ct[31] ^ dcr4[`OR1200_DU_DCR_SC]) == |
(dvr4[31] ^ dcr4[`OR1200_DU_DCR_SC])); |
4'b1_010: match4 = |
((match_cond4_ct[31] ^ dcr4[`OR1200_DU_DCR_SC]) < |
(dvr4[31] ^ dcr4[`OR1200_DU_DCR_SC])); |
4'b1_011: match4 = |
((match_cond4_ct[31] ^ dcr4[`OR1200_DU_DCR_SC]) <= |
(dvr4[31] ^ dcr4[`OR1200_DU_DCR_SC])); |
4'b1_100: match4 = |
((match_cond4_ct[31] ^ dcr4[`OR1200_DU_DCR_SC]) > |
(dvr4[31] ^ dcr4[`OR1200_DU_DCR_SC])); |
4'b1_101: match4 = |
((match_cond4_ct[31] ^ dcr4[`OR1200_DU_DCR_SC]) >= |
(dvr4[31] ^ dcr4[`OR1200_DU_DCR_SC])); |
4'b1_110: match4 = |
((match_cond4_ct[31] ^ dcr4[`OR1200_DU_DCR_SC]) != |
(dvr4[31] ^ dcr4[`OR1200_DU_DCR_SC])); |
endcase |
|
// |
// Match Condition 4 |
// |
always @(match_cond4_stb or dcr4 or dvr4 or match_cond4_ct) |
casex ({match_cond4_stb, dcr4[`OR1200_DU_DCR_CC]}) |
4'b0_xxx, |
4'b1_000, |
4'b1_111: match4 = 1'b0; |
4'b1_001: match4 = ( match_cond4_ct[30:0] == dvr4[30:0] ); |
4'b1_010: match4 = |
((match_cond4_ct[31] ^ dcr4[`OR1200_DU_DCR_SC]) < |
(dvr4[31] ^ dcr4[`OR1200_DU_DCR_SC]))&& |
( match_cond4_ct[30:0] < dvr4[30:0]); |
4'b1_011: match4 = |
((match_cond4_ct[31] ^ dcr4[`OR1200_DU_DCR_SC]) <= |
(dvr4[31] ^ dcr4[`OR1200_DU_DCR_SC]))&& |
( match_cond4_ct[30:0] <= dvr4[30:0]); |
4'b1_100: match4 = |
((match_cond4_ct[31] ^ dcr4[`OR1200_DU_DCR_SC]) > |
(dvr4[31] ^ dcr4[`OR1200_DU_DCR_SC]))&& |
( match_cond4_ct[30:0] > dvr4[30:0]); |
4'b1_101: match4 = |
((match_cond4_ct[31] ^ dcr4[`OR1200_DU_DCR_SC]) >= |
(dvr4[31] ^ dcr4[`OR1200_DU_DCR_SC]))&& |
( match_cond4_ct[30:0] >= dvr4[30:0]); |
4'b1_110: match4 = |
((match_cond4_ct[31] ^ dcr4[`OR1200_DU_DCR_SC]) != |
(dvr4[31] ^ dcr4[`OR1200_DU_DCR_SC]))&& |
( match_cond4_ct[30:0] != dvr4[30:0]); |
endcase |
|
|
// |
// Watchpoint 4 |
// |
1431,33 → 1457,37
default:match_cond5_stb = dcpu_cycstb_i; // any load/store |
endcase |
|
// |
// Match Condition 5 |
// |
always @(match_cond5_stb or dcr5 or dvr5 or match_cond5_ct) |
casex ({match_cond5_stb, dcr5[`OR1200_DU_DCR_CC]}) |
4'b0_xxx, |
4'b1_000, |
4'b1_111: match5 = 1'b0; |
4'b1_001: match5 = |
((match_cond5_ct[31] ^ dcr5[`OR1200_DU_DCR_SC]) == |
(dvr5[31] ^ dcr5[`OR1200_DU_DCR_SC])); |
4'b1_010: match5 = |
((match_cond5_ct[31] ^ dcr5[`OR1200_DU_DCR_SC]) < |
(dvr5[31] ^ dcr5[`OR1200_DU_DCR_SC])); |
4'b1_011: match5 = |
((match_cond5_ct[31] ^ dcr5[`OR1200_DU_DCR_SC]) <= |
(dvr5[31] ^ dcr5[`OR1200_DU_DCR_SC])); |
4'b1_100: match5 = |
((match_cond5_ct[31] ^ dcr5[`OR1200_DU_DCR_SC]) > |
(dvr5[31] ^ dcr5[`OR1200_DU_DCR_SC])); |
4'b1_101: match5 = |
((match_cond5_ct[31] ^ dcr5[`OR1200_DU_DCR_SC]) >= |
(dvr5[31] ^ dcr5[`OR1200_DU_DCR_SC])); |
4'b1_110: match5 = |
((match_cond5_ct[31] ^ dcr5[`OR1200_DU_DCR_SC]) != |
(dvr5[31] ^ dcr5[`OR1200_DU_DCR_SC])); |
endcase |
|
// |
// Match Condition 5 |
// |
always @(match_cond5_stb or dcr5 or dvr5 or match_cond5_ct) |
casex ({match_cond5_stb, dcr5[`OR1200_DU_DCR_CC]}) |
4'b0_xxx, |
4'b1_000, |
4'b1_111: match5 = 1'b0; |
4'b1_001: match5 = ( match_cond5_ct[30:0] == dvr5[30:0] ); |
4'b1_010: match5 = |
((match_cond5_ct[31] ^ dcr5[`OR1200_DU_DCR_SC]) < |
(dvr5[31] ^ dcr5[`OR1200_DU_DCR_SC]))&& |
( match_cond5_ct[30:0] < dvr5[30:0]); |
4'b1_011: match5 = |
((match_cond5_ct[31] ^ dcr5[`OR1200_DU_DCR_SC]) <= |
(dvr5[31] ^ dcr5[`OR1200_DU_DCR_SC]))&& |
( match_cond5_ct[30:0] <= dvr5[30:0]); |
4'b1_100: match5 = |
((match_cond5_ct[31] ^ dcr5[`OR1200_DU_DCR_SC]) > |
(dvr5[31] ^ dcr5[`OR1200_DU_DCR_SC]))&& |
( match_cond5_ct[30:0] > dvr5[30:0]); |
4'b1_101: match5 = |
((match_cond5_ct[31] ^ dcr5[`OR1200_DU_DCR_SC]) >= |
(dvr5[31] ^ dcr5[`OR1200_DU_DCR_SC]))&& |
( match_cond5_ct[30:0] >= dvr5[30:0]); |
4'b1_110: match5 = |
((match_cond5_ct[31] ^ dcr5[`OR1200_DU_DCR_SC]) != |
(dvr5[31] ^ dcr5[`OR1200_DU_DCR_SC]))&& |
( match_cond5_ct[30:0] != dvr5[30:0]); |
endcase |
|
// |
// Watchpoint 5 |
1495,34 → 1525,39
default:match_cond6_stb = dcpu_cycstb_i; // any load/store |
endcase |
|
// |
// Match Condition 6 |
// |
always @(match_cond6_stb or dcr6 or dvr6 or match_cond6_ct) |
casex ({match_cond6_stb, dcr6[`OR1200_DU_DCR_CC]}) |
4'b0_xxx, |
4'b1_000, |
4'b1_111: match6 = 1'b0; |
4'b1_001: match6 = |
((match_cond6_ct[31] ^ dcr6[`OR1200_DU_DCR_SC]) == |
(dvr6[31] ^ dcr6[`OR1200_DU_DCR_SC])); |
4'b1_010: match6 = |
((match_cond6_ct[31] ^ dcr6[`OR1200_DU_DCR_SC]) < |
(dvr6[31] ^ dcr6[`OR1200_DU_DCR_SC])); |
4'b1_011: match6 = |
((match_cond6_ct[31] ^ dcr6[`OR1200_DU_DCR_SC]) <= |
(dvr6[31] ^ dcr6[`OR1200_DU_DCR_SC])); |
4'b1_100: match6 = |
((match_cond6_ct[31] ^ dcr6[`OR1200_DU_DCR_SC]) > |
(dvr6[31] ^ dcr6[`OR1200_DU_DCR_SC])); |
4'b1_101: match6 = |
((match_cond6_ct[31] ^ dcr6[`OR1200_DU_DCR_SC]) >= |
(dvr6[31] ^ dcr6[`OR1200_DU_DCR_SC])); |
4'b1_110: match6 = |
((match_cond6_ct[31] ^ dcr6[`OR1200_DU_DCR_SC]) != |
(dvr6[31] ^ dcr6[`OR1200_DU_DCR_SC])); |
endcase |
|
// |
// Match Condition 6 |
// |
always @(match_cond6_stb or dcr6 or dvr6 or match_cond6_ct) |
casex ({match_cond6_stb, dcr6[`OR1200_DU_DCR_CC]}) |
4'b0_xxx, |
4'b1_000, |
4'b1_111: match6 = 1'b0; |
4'b1_001: match6 = ( match_cond6_ct[30:0] == dvr6[30:0] ); |
4'b1_010: match6 = |
((match_cond6_ct[31] ^ dcr6[`OR1200_DU_DCR_SC]) < |
(dvr6[31] ^ dcr6[`OR1200_DU_DCR_SC]))&& |
( match_cond6_ct[30:0] < dvr6[30:0]); |
4'b1_011: match6 = |
((match_cond6_ct[31] ^ dcr6[`OR1200_DU_DCR_SC]) <= |
(dvr6[31] ^ dcr6[`OR1200_DU_DCR_SC]))&& |
( match_cond6_ct[30:0] <= dvr6[30:0]); |
4'b1_100: match6 = |
((match_cond6_ct[31] ^ dcr6[`OR1200_DU_DCR_SC]) > |
(dvr6[31] ^ dcr6[`OR1200_DU_DCR_SC]))&& |
( match_cond6_ct[30:0] > dvr6[30:0]); |
4'b1_101: match6 = |
((match_cond6_ct[31] ^ dcr6[`OR1200_DU_DCR_SC]) >= |
(dvr6[31] ^ dcr6[`OR1200_DU_DCR_SC]))&& |
( match_cond6_ct[30:0] >= dvr6[30:0]); |
4'b1_110: match6 = |
((match_cond6_ct[31] ^ dcr6[`OR1200_DU_DCR_SC]) != |
(dvr6[31] ^ dcr6[`OR1200_DU_DCR_SC]))&& |
( match_cond6_ct[30:0] != dvr6[30:0]); |
endcase |
|
|
// |
// Watchpoint 6 |
// |
1558,36 → 1593,39
3'b001: match_cond7_stb = 1'b1; // insn fetch EA |
default:match_cond7_stb = dcpu_cycstb_i; // any load/store |
endcase |
|
// |
// Match Condition 7 |
// |
always @(match_cond7_stb or dcr7 or dvr7 or match_cond7_ct) |
casex ({match_cond7_stb, dcr7[`OR1200_DU_DCR_CC]}) |
4'b0_xxx, |
4'b1_000, |
4'b1_111: match7 = 1'b0; |
4'b1_001: match7 = ( match_cond7_ct[30:0] == dvr7[30:0] ); |
4'b1_010: match7 = |
((match_cond7_ct[31] ^ dcr7[`OR1200_DU_DCR_SC]) < |
(dvr7[31] ^ dcr7[`OR1200_DU_DCR_SC]))&& |
( match_cond7_ct[30:0] < dvr7[30:0]); |
4'b1_011: match7 = |
((match_cond7_ct[31] ^ dcr7[`OR1200_DU_DCR_SC]) <= |
(dvr7[31] ^ dcr7[`OR1200_DU_DCR_SC]))&& |
( match_cond7_ct[30:0] <= dvr7[30:0]); |
4'b1_100: match7 = |
((match_cond7_ct[31] ^ dcr7[`OR1200_DU_DCR_SC]) > |
(dvr7[31] ^ dcr7[`OR1200_DU_DCR_SC]))&& |
( match_cond7_ct[30:0] > dvr7[30:0]); |
4'b1_101: match7 = |
((match_cond7_ct[31] ^ dcr7[`OR1200_DU_DCR_SC]) >= |
(dvr7[31] ^ dcr7[`OR1200_DU_DCR_SC]))&& |
( match_cond7_ct[30:0] >= dvr7[30:0]); |
4'b1_110: match7 = |
((match_cond7_ct[31] ^ dcr7[`OR1200_DU_DCR_SC]) != |
(dvr7[31] ^ dcr7[`OR1200_DU_DCR_SC]))&& |
( match_cond7_ct[30:0] != dvr7[30:0]); |
endcase |
|
// |
// Match Condition 7 |
// |
always @(match_cond7_stb or dcr7 or dvr7 or match_cond7_ct) |
casex ({match_cond7_stb, dcr7[`OR1200_DU_DCR_CC]}) |
4'b0_xxx, |
4'b1_000, |
4'b1_111: match7 = 1'b0; |
4'b1_001: match7 = |
((match_cond7_ct[31] ^ dcr7[`OR1200_DU_DCR_SC]) == |
(dvr7[31] ^ dcr7[`OR1200_DU_DCR_SC])); |
4'b1_010: match7 = |
((match_cond7_ct[31] ^ dcr7[`OR1200_DU_DCR_SC]) < |
(dvr7[31] ^ dcr7[`OR1200_DU_DCR_SC])); |
4'b1_011: match7 = |
((match_cond7_ct[31] ^ dcr7[`OR1200_DU_DCR_SC]) <= |
(dvr7[31] ^ dcr7[`OR1200_DU_DCR_SC])); |
4'b1_100: match7 = |
((match_cond7_ct[31] ^ dcr7[`OR1200_DU_DCR_SC]) > |
(dvr7[31] ^ dcr7[`OR1200_DU_DCR_SC])); |
4'b1_101: match7 = |
((match_cond7_ct[31] ^ dcr7[`OR1200_DU_DCR_SC]) >= |
(dvr7[31] ^ dcr7[`OR1200_DU_DCR_SC])); |
4'b1_110: match7 = |
((match_cond7_ct[31] ^ dcr7[`OR1200_DU_DCR_SC]) != |
(dvr7[31] ^ dcr7[`OR1200_DU_DCR_SC])); |
endcase |
|
// |
// Watchpoint 7 |
// |
always @(dmr1 or match7 or wp) |
/rtl/verilog/components/or1200r2/or1200_cfgr.v
79,158 → 79,158
`include "or1200_defines.v" |
|
module or1200_cfgr( |
// RISC Internal Interface |
spr_addr, spr_dat_o |
); |
// RISC Internal Interface |
spr_addr, spr_dat_o |
); |
|
// |
// RISC Internal Interface |
// |
input [31:0] spr_addr; // SPR Address |
output [31:0] spr_dat_o; // SPR Read Data |
// |
// RISC Internal Interface |
// |
input [31:0] spr_addr; // SPR Address |
output [31:0] spr_dat_o; // SPR Read Data |
|
// |
// Internal wires & registers |
// |
reg [31:0] spr_dat_o; // SPR Read Data |
// |
// Internal wires & registers |
// |
reg [31:0] spr_dat_o; // SPR Read Data |
|
`ifdef OR1200_CFGR_IMPLEMENTED |
|
// |
// Implementation of VR, UPR and configuration registers |
// |
always @(spr_addr) |
`ifdef OR1200_SYS_FULL_DECODE |
if (~|spr_addr[31:4]) |
`endif |
case(spr_addr[3:0]) // synopsys parallel_case |
`OR1200_SPRGRP_SYS_VR: begin |
spr_dat_o[`OR1200_VR_REV_BITS] = `OR1200_VR_REV; |
spr_dat_o[`OR1200_VR_RES1_BITS] = `OR1200_VR_RES1; |
spr_dat_o[`OR1200_VR_CFG_BITS] = `OR1200_VR_CFG; |
spr_dat_o[`OR1200_VR_VER_BITS] = `OR1200_VR_VER; |
end |
`OR1200_SPRGRP_SYS_UPR: begin |
spr_dat_o[`OR1200_UPR_UP_BITS] = `OR1200_UPR_UP; |
spr_dat_o[`OR1200_UPR_DCP_BITS] = `OR1200_UPR_DCP; |
spr_dat_o[`OR1200_UPR_ICP_BITS] = `OR1200_UPR_ICP; |
spr_dat_o[`OR1200_UPR_DMP_BITS] = `OR1200_UPR_DMP; |
spr_dat_o[`OR1200_UPR_IMP_BITS] = `OR1200_UPR_IMP; |
spr_dat_o[`OR1200_UPR_MP_BITS] = `OR1200_UPR_MP; |
spr_dat_o[`OR1200_UPR_DUP_BITS] = `OR1200_UPR_DUP; |
spr_dat_o[`OR1200_UPR_PCUP_BITS] = `OR1200_UPR_PCUP; |
spr_dat_o[`OR1200_UPR_PMP_BITS] = `OR1200_UPR_PMP; |
spr_dat_o[`OR1200_UPR_PICP_BITS] = `OR1200_UPR_PICP; |
spr_dat_o[`OR1200_UPR_TTP_BITS] = `OR1200_UPR_TTP; |
spr_dat_o[`OR1200_UPR_RES1_BITS] = `OR1200_UPR_RES1; |
spr_dat_o[`OR1200_UPR_CUP_BITS] = `OR1200_UPR_CUP; |
end |
`OR1200_SPRGRP_SYS_CPUCFGR: begin |
spr_dat_o[`OR1200_CPUCFGR_NSGF_BITS] = `OR1200_CPUCFGR_NSGF; |
spr_dat_o[`OR1200_CPUCFGR_HGF_BITS] = `OR1200_CPUCFGR_HGF; |
spr_dat_o[`OR1200_CPUCFGR_OB32S_BITS] = `OR1200_CPUCFGR_OB32S; |
spr_dat_o[`OR1200_CPUCFGR_OB64S_BITS] = `OR1200_CPUCFGR_OB64S; |
spr_dat_o[`OR1200_CPUCFGR_OF32S_BITS] = `OR1200_CPUCFGR_OF32S; |
spr_dat_o[`OR1200_CPUCFGR_OF64S_BITS] = `OR1200_CPUCFGR_OF64S; |
spr_dat_o[`OR1200_CPUCFGR_OV64S_BITS] = `OR1200_CPUCFGR_OV64S; |
spr_dat_o[`OR1200_CPUCFGR_RES1_BITS] = `OR1200_CPUCFGR_RES1; |
end |
`OR1200_SPRGRP_SYS_DMMUCFGR: begin |
spr_dat_o[`OR1200_DMMUCFGR_NTW_BITS] = `OR1200_DMMUCFGR_NTW; |
spr_dat_o[`OR1200_DMMUCFGR_NTS_BITS] = `OR1200_DMMUCFGR_NTS; |
spr_dat_o[`OR1200_DMMUCFGR_NAE_BITS] = `OR1200_DMMUCFGR_NAE; |
spr_dat_o[`OR1200_DMMUCFGR_CRI_BITS] = `OR1200_DMMUCFGR_CRI; |
spr_dat_o[`OR1200_DMMUCFGR_PRI_BITS] = `OR1200_DMMUCFGR_PRI; |
spr_dat_o[`OR1200_DMMUCFGR_TEIRI_BITS] = `OR1200_DMMUCFGR_TEIRI; |
spr_dat_o[`OR1200_DMMUCFGR_HTR_BITS] = `OR1200_DMMUCFGR_HTR; |
spr_dat_o[`OR1200_DMMUCFGR_RES1_BITS] = `OR1200_DMMUCFGR_RES1; |
end |
`OR1200_SPRGRP_SYS_IMMUCFGR: begin |
spr_dat_o[`OR1200_IMMUCFGR_NTW_BITS] = `OR1200_IMMUCFGR_NTW; |
spr_dat_o[`OR1200_IMMUCFGR_NTS_BITS] = `OR1200_IMMUCFGR_NTS; |
spr_dat_o[`OR1200_IMMUCFGR_NAE_BITS] = `OR1200_IMMUCFGR_NAE; |
spr_dat_o[`OR1200_IMMUCFGR_CRI_BITS] = `OR1200_IMMUCFGR_CRI; |
spr_dat_o[`OR1200_IMMUCFGR_PRI_BITS] = `OR1200_IMMUCFGR_PRI; |
spr_dat_o[`OR1200_IMMUCFGR_TEIRI_BITS] = `OR1200_IMMUCFGR_TEIRI; |
spr_dat_o[`OR1200_IMMUCFGR_HTR_BITS] = `OR1200_IMMUCFGR_HTR; |
spr_dat_o[`OR1200_IMMUCFGR_RES1_BITS] = `OR1200_IMMUCFGR_RES1; |
end |
`OR1200_SPRGRP_SYS_DCCFGR: begin |
spr_dat_o[`OR1200_DCCFGR_NCW_BITS] = `OR1200_DCCFGR_NCW; |
spr_dat_o[`OR1200_DCCFGR_NCS_BITS] = `OR1200_DCCFGR_NCS; |
spr_dat_o[`OR1200_DCCFGR_CBS_BITS] = `OR1200_DCCFGR_CBS; |
spr_dat_o[`OR1200_DCCFGR_CWS_BITS] = `OR1200_DCCFGR_CWS; |
spr_dat_o[`OR1200_DCCFGR_CCRI_BITS] = `OR1200_DCCFGR_CCRI; |
spr_dat_o[`OR1200_DCCFGR_CBIRI_BITS] = `OR1200_DCCFGR_CBIRI; |
spr_dat_o[`OR1200_DCCFGR_CBPRI_BITS] = `OR1200_DCCFGR_CBPRI; |
spr_dat_o[`OR1200_DCCFGR_CBLRI_BITS] = `OR1200_DCCFGR_CBLRI; |
spr_dat_o[`OR1200_DCCFGR_CBFRI_BITS] = `OR1200_DCCFGR_CBFRI; |
spr_dat_o[`OR1200_DCCFGR_CBWBRI_BITS] = `OR1200_DCCFGR_CBWBRI; |
spr_dat_o[`OR1200_DCCFGR_RES1_BITS] = `OR1200_DCCFGR_RES1; |
end |
`OR1200_SPRGRP_SYS_ICCFGR: begin |
spr_dat_o[`OR1200_ICCFGR_NCW_BITS] = `OR1200_ICCFGR_NCW; |
spr_dat_o[`OR1200_ICCFGR_NCS_BITS] = `OR1200_ICCFGR_NCS; |
spr_dat_o[`OR1200_ICCFGR_CBS_BITS] = `OR1200_ICCFGR_CBS; |
spr_dat_o[`OR1200_ICCFGR_CWS_BITS] = `OR1200_ICCFGR_CWS; |
spr_dat_o[`OR1200_ICCFGR_CCRI_BITS] = `OR1200_ICCFGR_CCRI; |
spr_dat_o[`OR1200_ICCFGR_CBIRI_BITS] = `OR1200_ICCFGR_CBIRI; |
spr_dat_o[`OR1200_ICCFGR_CBPRI_BITS] = `OR1200_ICCFGR_CBPRI; |
spr_dat_o[`OR1200_ICCFGR_CBLRI_BITS] = `OR1200_ICCFGR_CBLRI; |
spr_dat_o[`OR1200_ICCFGR_CBFRI_BITS] = `OR1200_ICCFGR_CBFRI; |
spr_dat_o[`OR1200_ICCFGR_CBWBRI_BITS] = `OR1200_ICCFGR_CBWBRI; |
spr_dat_o[`OR1200_ICCFGR_RES1_BITS] = `OR1200_ICCFGR_RES1; |
end |
`OR1200_SPRGRP_SYS_DCFGR: begin |
spr_dat_o[`OR1200_DCFGR_NDP_BITS] = `OR1200_DCFGR_NDP; |
spr_dat_o[`OR1200_DCFGR_WPCI_BITS] = `OR1200_DCFGR_WPCI; |
spr_dat_o[`OR1200_DCFGR_RES1_BITS] = `OR1200_DCFGR_RES1; |
end |
default: spr_dat_o = 32'h0000_0000; |
endcase |
`ifdef OR1200_SYS_FULL_DECODE |
else |
spr_dat_o = 32'h0000_0000; |
`endif |
// |
// Implementation of VR, UPR and configuration registers |
// |
always @(spr_addr) |
`ifdef OR1200_SYS_FULL_DECODE |
if (~|spr_addr[31:4]) |
`endif |
case(spr_addr[3:0]) // synopsys parallel_case |
`OR1200_SPRGRP_SYS_VR: begin |
spr_dat_o[`OR1200_VR_REV_BITS] = `OR1200_VR_REV; |
spr_dat_o[`OR1200_VR_RES1_BITS] = `OR1200_VR_RES1; |
spr_dat_o[`OR1200_VR_CFG_BITS] = `OR1200_VR_CFG; |
spr_dat_o[`OR1200_VR_VER_BITS] = `OR1200_VR_VER; |
end |
`OR1200_SPRGRP_SYS_UPR: begin |
spr_dat_o[`OR1200_UPR_UP_BITS] = `OR1200_UPR_UP; |
spr_dat_o[`OR1200_UPR_DCP_BITS] = `OR1200_UPR_DCP; |
spr_dat_o[`OR1200_UPR_ICP_BITS] = `OR1200_UPR_ICP; |
spr_dat_o[`OR1200_UPR_DMP_BITS] = `OR1200_UPR_DMP; |
spr_dat_o[`OR1200_UPR_IMP_BITS] = `OR1200_UPR_IMP; |
spr_dat_o[`OR1200_UPR_MP_BITS] = `OR1200_UPR_MP; |
spr_dat_o[`OR1200_UPR_DUP_BITS] = `OR1200_UPR_DUP; |
spr_dat_o[`OR1200_UPR_PCUP_BITS] = `OR1200_UPR_PCUP; |
spr_dat_o[`OR1200_UPR_PMP_BITS] = `OR1200_UPR_PMP; |
spr_dat_o[`OR1200_UPR_PICP_BITS] = `OR1200_UPR_PICP; |
spr_dat_o[`OR1200_UPR_TTP_BITS] = `OR1200_UPR_TTP; |
spr_dat_o[`OR1200_UPR_RES1_BITS] = `OR1200_UPR_RES1; |
spr_dat_o[`OR1200_UPR_CUP_BITS] = `OR1200_UPR_CUP; |
end |
`OR1200_SPRGRP_SYS_CPUCFGR: begin |
spr_dat_o[`OR1200_CPUCFGR_NSGF_BITS] = `OR1200_CPUCFGR_NSGF; |
spr_dat_o[`OR1200_CPUCFGR_HGF_BITS] = `OR1200_CPUCFGR_HGF; |
spr_dat_o[`OR1200_CPUCFGR_OB32S_BITS] = `OR1200_CPUCFGR_OB32S; |
spr_dat_o[`OR1200_CPUCFGR_OB64S_BITS] = `OR1200_CPUCFGR_OB64S; |
spr_dat_o[`OR1200_CPUCFGR_OF32S_BITS] = `OR1200_CPUCFGR_OF32S; |
spr_dat_o[`OR1200_CPUCFGR_OF64S_BITS] = `OR1200_CPUCFGR_OF64S; |
spr_dat_o[`OR1200_CPUCFGR_OV64S_BITS] = `OR1200_CPUCFGR_OV64S; |
spr_dat_o[`OR1200_CPUCFGR_RES1_BITS] = `OR1200_CPUCFGR_RES1; |
end |
`OR1200_SPRGRP_SYS_DMMUCFGR: begin |
spr_dat_o[`OR1200_DMMUCFGR_NTW_BITS] = `OR1200_DMMUCFGR_NTW; |
spr_dat_o[`OR1200_DMMUCFGR_NTS_BITS] = `OR1200_DMMUCFGR_NTS; |
spr_dat_o[`OR1200_DMMUCFGR_NAE_BITS] = `OR1200_DMMUCFGR_NAE; |
spr_dat_o[`OR1200_DMMUCFGR_CRI_BITS] = `OR1200_DMMUCFGR_CRI; |
spr_dat_o[`OR1200_DMMUCFGR_PRI_BITS] = `OR1200_DMMUCFGR_PRI; |
spr_dat_o[`OR1200_DMMUCFGR_TEIRI_BITS] = `OR1200_DMMUCFGR_TEIRI; |
spr_dat_o[`OR1200_DMMUCFGR_HTR_BITS] = `OR1200_DMMUCFGR_HTR; |
spr_dat_o[`OR1200_DMMUCFGR_RES1_BITS] = `OR1200_DMMUCFGR_RES1; |
end |
`OR1200_SPRGRP_SYS_IMMUCFGR: begin |
spr_dat_o[`OR1200_IMMUCFGR_NTW_BITS] = `OR1200_IMMUCFGR_NTW; |
spr_dat_o[`OR1200_IMMUCFGR_NTS_BITS] = `OR1200_IMMUCFGR_NTS; |
spr_dat_o[`OR1200_IMMUCFGR_NAE_BITS] = `OR1200_IMMUCFGR_NAE; |
spr_dat_o[`OR1200_IMMUCFGR_CRI_BITS] = `OR1200_IMMUCFGR_CRI; |
spr_dat_o[`OR1200_IMMUCFGR_PRI_BITS] = `OR1200_IMMUCFGR_PRI; |
spr_dat_o[`OR1200_IMMUCFGR_TEIRI_BITS] = `OR1200_IMMUCFGR_TEIRI; |
spr_dat_o[`OR1200_IMMUCFGR_HTR_BITS] = `OR1200_IMMUCFGR_HTR; |
spr_dat_o[`OR1200_IMMUCFGR_RES1_BITS] = `OR1200_IMMUCFGR_RES1; |
end |
`OR1200_SPRGRP_SYS_DCCFGR: begin |
spr_dat_o[`OR1200_DCCFGR_NCW_BITS] = `OR1200_DCCFGR_NCW; |
spr_dat_o[`OR1200_DCCFGR_NCS_BITS] = `OR1200_DCCFGR_NCS; |
spr_dat_o[`OR1200_DCCFGR_CBS_BITS] = `OR1200_DCCFGR_CBS; |
spr_dat_o[`OR1200_DCCFGR_CWS_BITS] = `OR1200_DCCFGR_CWS; |
spr_dat_o[`OR1200_DCCFGR_CCRI_BITS] = `OR1200_DCCFGR_CCRI; |
spr_dat_o[`OR1200_DCCFGR_CBIRI_BITS] = `OR1200_DCCFGR_CBIRI; |
spr_dat_o[`OR1200_DCCFGR_CBPRI_BITS] = `OR1200_DCCFGR_CBPRI; |
spr_dat_o[`OR1200_DCCFGR_CBLRI_BITS] = `OR1200_DCCFGR_CBLRI; |
spr_dat_o[`OR1200_DCCFGR_CBFRI_BITS] = `OR1200_DCCFGR_CBFRI; |
spr_dat_o[`OR1200_DCCFGR_CBWBRI_BITS] = `OR1200_DCCFGR_CBWBRI; |
spr_dat_o[`OR1200_DCCFGR_RES1_BITS] = `OR1200_DCCFGR_RES1; |
end |
`OR1200_SPRGRP_SYS_ICCFGR: begin |
spr_dat_o[`OR1200_ICCFGR_NCW_BITS] = `OR1200_ICCFGR_NCW; |
spr_dat_o[`OR1200_ICCFGR_NCS_BITS] = `OR1200_ICCFGR_NCS; |
spr_dat_o[`OR1200_ICCFGR_CBS_BITS] = `OR1200_ICCFGR_CBS; |
spr_dat_o[`OR1200_ICCFGR_CWS_BITS] = `OR1200_ICCFGR_CWS; |
spr_dat_o[`OR1200_ICCFGR_CCRI_BITS] = `OR1200_ICCFGR_CCRI; |
spr_dat_o[`OR1200_ICCFGR_CBIRI_BITS] = `OR1200_ICCFGR_CBIRI; |
spr_dat_o[`OR1200_ICCFGR_CBPRI_BITS] = `OR1200_ICCFGR_CBPRI; |
spr_dat_o[`OR1200_ICCFGR_CBLRI_BITS] = `OR1200_ICCFGR_CBLRI; |
spr_dat_o[`OR1200_ICCFGR_CBFRI_BITS] = `OR1200_ICCFGR_CBFRI; |
spr_dat_o[`OR1200_ICCFGR_CBWBRI_BITS] = `OR1200_ICCFGR_CBWBRI; |
spr_dat_o[`OR1200_ICCFGR_RES1_BITS] = `OR1200_ICCFGR_RES1; |
end |
`OR1200_SPRGRP_SYS_DCFGR: begin |
spr_dat_o[`OR1200_DCFGR_NDP_BITS] = `OR1200_DCFGR_NDP; |
spr_dat_o[`OR1200_DCFGR_WPCI_BITS] = `OR1200_DCFGR_WPCI; |
spr_dat_o[`OR1200_DCFGR_RES1_BITS] = `OR1200_DCFGR_RES1; |
end |
default: spr_dat_o = 32'h0000_0000; |
endcase |
`ifdef OR1200_SYS_FULL_DECODE |
else |
spr_dat_o = 32'h0000_0000; |
`endif |
|
`else |
|
// |
// When configuration registers are not implemented, only |
// implement VR and UPR |
// |
always @(spr_addr) |
`ifdef OR1200_SYS_FULL_DECODE |
if (spr_addr[31:4] == 28'h0) |
`endif |
case(spr_addr[3:0]) |
`OR1200_SPRGRP_SYS_VR: begin |
spr_dat_o[`OR1200_VR_REV_BITS] = `OR1200_VR_REV; |
spr_dat_o[`OR1200_VR_RES1_BITS] = `OR1200_VR_RES1; |
spr_dat_o[`OR1200_VR_CFG_BITS] = `OR1200_VR_CFG; |
spr_dat_o[`OR1200_VR_VER_BITS] = `OR1200_VR_VER; |
end |
`OR1200_SPRGRP_SYS_UPR: begin |
spr_dat_o[`OR1200_UPR_UP_BITS] = `OR1200_UPR_UP; |
spr_dat_o[`OR1200_UPR_DCP_BITS] = `OR1200_UPR_DCP; |
spr_dat_o[`OR1200_UPR_ICP_BITS] = `OR1200_UPR_ICP; |
spr_dat_o[`OR1200_UPR_DMP_BITS] = `OR1200_UPR_DMP; |
spr_dat_o[`OR1200_UPR_IMP_BITS] = `OR1200_UPR_IMP; |
spr_dat_o[`OR1200_UPR_MP_BITS] = `OR1200_UPR_MP; |
spr_dat_o[`OR1200_UPR_DUP_BITS] = `OR1200_UPR_DUP; |
spr_dat_o[`OR1200_UPR_PCUP_BITS] = `OR1200_UPR_PCUP; |
spr_dat_o[`OR1200_UPR_PMP_BITS] = `OR1200_UPR_PMP; |
spr_dat_o[`OR1200_UPR_PICP_BITS] = `OR1200_UPR_PICP; |
spr_dat_o[`OR1200_UPR_TTP_BITS] = `OR1200_UPR_TTP; |
spr_dat_o[`OR1200_UPR_RES1_BITS] = `OR1200_UPR_RES1; |
spr_dat_o[`OR1200_UPR_CUP_BITS] = `OR1200_UPR_CUP; |
end |
default: spr_dat_o = 32'h0000_0000; |
endcase |
`ifdef OR1200_SYS_FULL_DECODE |
else |
spr_dat_o = 32'h0000_0000; |
`endif |
// |
// When configuration registers are not implemented, only |
// implement VR and UPR |
// |
always @(spr_addr) |
`ifdef OR1200_SYS_FULL_DECODE |
if (spr_addr[31:4] == 28'h0) |
`endif |
case(spr_addr[3:0]) |
`OR1200_SPRGRP_SYS_VR: begin |
spr_dat_o[`OR1200_VR_REV_BITS] = `OR1200_VR_REV; |
spr_dat_o[`OR1200_VR_RES1_BITS] = `OR1200_VR_RES1; |
spr_dat_o[`OR1200_VR_CFG_BITS] = `OR1200_VR_CFG; |
spr_dat_o[`OR1200_VR_VER_BITS] = `OR1200_VR_VER; |
end |
`OR1200_SPRGRP_SYS_UPR: begin |
spr_dat_o[`OR1200_UPR_UP_BITS] = `OR1200_UPR_UP; |
spr_dat_o[`OR1200_UPR_DCP_BITS] = `OR1200_UPR_DCP; |
spr_dat_o[`OR1200_UPR_ICP_BITS] = `OR1200_UPR_ICP; |
spr_dat_o[`OR1200_UPR_DMP_BITS] = `OR1200_UPR_DMP; |
spr_dat_o[`OR1200_UPR_IMP_BITS] = `OR1200_UPR_IMP; |
spr_dat_o[`OR1200_UPR_MP_BITS] = `OR1200_UPR_MP; |
spr_dat_o[`OR1200_UPR_DUP_BITS] = `OR1200_UPR_DUP; |
spr_dat_o[`OR1200_UPR_PCUP_BITS] = `OR1200_UPR_PCUP; |
spr_dat_o[`OR1200_UPR_PMP_BITS] = `OR1200_UPR_PMP; |
spr_dat_o[`OR1200_UPR_PICP_BITS] = `OR1200_UPR_PICP; |
spr_dat_o[`OR1200_UPR_TTP_BITS] = `OR1200_UPR_TTP; |
spr_dat_o[`OR1200_UPR_RES1_BITS] = `OR1200_UPR_RES1; |
spr_dat_o[`OR1200_UPR_CUP_BITS] = `OR1200_UPR_CUP; |
end |
default: spr_dat_o = 32'h0000_0000; |
endcase |
`ifdef OR1200_SYS_FULL_DECODE |
else |
spr_dat_o = 32'h0000_0000; |
`endif |
|
`endif |
|
/rtl/verilog/components/or1200r2/or1200_except.v
226,7 → 226,7
// Internal regs and wires |
// |
reg [`OR1200_EXCEPT_WIDTH-1:0] except_type; |
reg [31:0] id_pc; |
reg [31:0] id_pc /* verilator public */; |
reg [31:0] ex_pc; |
reg [31:0] wb_pc /* verilator public */; |
reg [31:0] epcr; |
306,6 → 306,17
`endif |
|
|
`ifdef verilator |
// Function to access id_pc (for Verilator). Have to hide this from |
// simulator, since functions with no inputs are not allowed in IEEE |
// 1364-2001. |
function [31:0] get_id_pc; |
// verilator public |
get_id_pc = id_pc; |
endfunction // get_id_pc |
|
`endif |
|
// |
// PC and Exception flags pipelines |
// |
/rtl/verilog/components/or1200r2/or1200_ic_ram.v
141,7 → 141,7
`ifdef OR1200_IC_1W_512B |
or1200_spram # |
( |
.aw(9), |
.aw(7), |
.dw(32) |
) |
`endif |
/rtl/verilog/components/or1200r2/or1200_genpc.v
331,7 → 331,7
|
always @(pcreg_boot or pcreg_default or pcreg_select) |
if (pcreg_select) |
pcreg = pcreg_boot[31:2]; |
pcreg = pcreg_boot[31:2]; |
else |
pcreg = pcreg_default ; |
|
/rtl/verilog/components/or1200r2/or1200_ctrl.v
200,7 → 200,7
wire ex_macrc_op; |
`endif |
reg [`OR1200_SHROTOP_WIDTH-1:0] shrot_op; |
reg [31:0] id_insn; |
reg [31:0] id_insn /* verilator public */; |
reg [31:0] ex_insn; |
reg [31:0] wb_insn; |
reg [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrw; |
279,7 → 279,18
endfunction // get_wb_insn |
`endif |
|
`ifdef verilator |
// Function to access id_insn (for Verilator). Have to hide this from |
// simulator, since functions with no inputs are not allowed in IEEE |
// 1364-2001. |
function [31:0] get_id_insn; |
// verilator public |
get_id_insn = id_insn; |
endfunction // get_id_insn |
`endif |
|
|
|
// |
// Generation of sel_a |
// |
/sim/bin/Makefile
8,9 → 8,6
#### ORPSoC(v2) design. #### |
#### #### |
#### To do: #### |
#### * Arrange verilator make rules so that the whole thing #### |
#### isn't recompiled when a single SystemC module is #### |
#### updated. #### |
#### * Test if each software test file gets made properly #### |
#### before it's run in whatever model we're using #### |
#### * Expand software test-suite (uClibc, ecos tests, LTP?) #### |
210,19 → 207,8
# the cycle-accurate ORPSoC model to create the simulation executable. This |
# executable is the cycle-representation of the system. |
# |
# VCDs can be generated if the model is made with VCD=1 specified on the |
# command line. Specify a dump file with the "-vcd" option at runtime, eg: |
# "./Vorpsoc_top -vcd dump.vcd" |
# Note that this slows down the simulation. |
# Run the resulting executable with the -h switch for usage. |
# |
# Logging of the processor's execution can be done by specifying a log file |
# on the command line at runtime, eg: "./Vorpsoc_top -log or1200_exec.log" |
# Note that this slows down the simulation. |
# |
# There are performance metrics printed at the conclusion of simulations. To |
# disable these launch the executable with either the -q or --no-perf-summary |
# options. eg: "./Vorpsoc_top -q" |
# |
# The compilation is all done with the GNU c++ compiler, g++. |
# |
# The compilation process is a little more complicated than the event-driven |
246,6 → 232,7
# the system through its paces. |
# |
# |
# |
|
# Name of the directory we're currently in |
CUR_DIR=$(shell pwd) |
507,7 → 494,7
## Build the VPI library |
$(MAKE) -C $(VPI_C_DIR) $(VPI_LIB_NAME) |
|
clean_vpi: |
clean-vpi: |
$(MAKE) -C $(VPI_C_DIR) clean |
|
rtl-debug: prepare_sw_uart_printf prepare_rtl prepare_vpi prepare_dirs |
553,16 → 540,38
|
# List of System C models - use this list to link the sources into the Verilator |
# build directory |
SYSC_MODELS=OrpsocAccess TraceSC |
SYSC_MODELS=OrpsocAccess |
|
ifdef VCD |
VLT_FLAGS +=-trace |
ifdef VLT_DEBUG |
VLT_DEBUG_COMPILE_FLAGS = -g |
# Enabling the following generates a TON of debugging |
# when running verilator. Not so helpful. |
#VLT_DEBUG_OPTIONS = --debug --dump-tree |
VLT_SYSC_DEBUG_DEFINE = VLT_DEBUG=1 |
endif |
|
# If set on the command line we build the cycle accurate model which will generate verilator-specific profiling information. This is useful for checking the efficiency of the model - not really useful for checking code or the function of the model. |
ifdef VLT_ORPSOC_PROFILING |
VLT_CPPFLAGS=-g -pg |
VLT_DEBUG_OPTIONS +=-profile-cfuncs |
else |
VLT_CPPFLAGS=-fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -O3 |
endif |
|
ifdef VLT_DO_PROFILING |
VLT_CPPFLAGS=-O3 -ftest-coverage -fprofile-generate |
endif |
|
# VCD Enabled by default when building, enable it at runtime |
#ifdef VCD |
VLT_FLAGS +=-trace |
TRACE_FLAGS=-DVM_TRACE=1 -I${SYSTEMPERL}/src |
#endif |
|
# Only need the trace target if we are tracing |
ifneq (,$(findstring -trace, $(VLT_FLAGS))) |
#ifneq (,$(findstring -trace, $(VLT_FLAGS))) |
VLT_TRACEOBJ = SpTraceVcdC |
endif |
#endif |
|
# This is the list of extra models we'll issue make commands for |
# Included is the SystemPerl trace model |
573,12 → 582,12
$(SIM_VLT_DIR)/Vorpsoc_top: $(SIM_VLT_DIR)/libVorpsoc_top.a $(SIM_VLT_DIR)/OrpsocMain.o |
# Final linking of the simulation executable. Order of libraries here is important! |
@echo; echo "\tGenerating simulation executable"; echo |
cd $(SIM_VLT_DIR) && g++ -I$(BENCH_SYSC_INCLUDE_DIR) -I$(SIM_VLT_DIR) -I$(VERILATOR_ROOT)/include -I$(SYSTEMC)/include -o Vorpsoc_top -L. -L$(BENCH_SYSC_SRC_DIR) -L$(SYSTEMC)/$(SYSC_LIB_ARCH_DIR) OrpsocMain.o -lVorpsoc_top -lmodules -lsystemc |
cd $(SIM_VLT_DIR) && g++ $(VLT_DEBUG_COMPILE_FLAGS) $(VLT_CPPFLAGS) -I$(BENCH_SYSC_INCLUDE_DIR) -I$(SIM_VLT_DIR) -I$(VERILATOR_ROOT)/include -I$(SYSTEMC)/include -o Vorpsoc_top -L. -L$(BENCH_SYSC_SRC_DIR) -L$(SYSTEMC)/$(SYSC_LIB_ARCH_DIR) OrpsocMain.o -lVorpsoc_top -lmodules -lsystemc |
|
$(SIM_VLT_DIR)/OrpsocMain.o: |
# Now compile the top level systemC "testbench" module |
@echo; echo "\tCompiling top level SystemC testbench"; echo |
cd $(SIM_VLT_DIR) && g++ -I$(BENCH_SYSC_INCLUDE_DIR) -I$(SIM_VLT_DIR) -I$(VERILATOR_ROOT)/include -I$(SYSTEMC)/include -c $(BENCH_SYSC_SRC_DIR)/OrpsocMain.cpp |
cd $(SIM_VLT_DIR) && g++ $(VLT_DEBUG_COMPILE_FLAGS) $(VLT_CPPFLAGS) $(TRACE_FLAGS) -I$(BENCH_SYSC_INCLUDE_DIR) -I$(SIM_VLT_DIR) -I$(VERILATOR_ROOT)/include -I$(SYSTEMC)/include -c $(BENCH_SYSC_SRC_DIR)/OrpsocMain.cpp |
|
$(SIM_VLT_DIR)/libVorpsoc_top.a: $(SIM_VLT_DIR)/Vorpsoc_top__ALL.a vlt_modules_compile $(SIM_VLT_DIR)/verilated.o |
# Now archive all of the libraries from verilator witht he other modules we might have |
593,6 → 602,9
$(SIM_VLT_DIR)/verilated.o: |
@echo; echo "\tCompiling verilated.o"; echo |
@cd $(SIM_VLT_DIR) && \ |
export CXXFLAGS=$(VLT_DEBUG_COMPILE_FLAGS); \ |
export USER_CPPFLAGS="$(VLT_CPPFLAGS)"; \ |
export USER_LDDFLAGS="$(VLT_CPPFLAGS)"; \ |
$(MAKE) -f Vorpsoc_top.mk verilated.o |
|
.PHONY: vlt_modules_compile |
602,12 → 614,17
@cd $(SIM_VLT_DIR) && \ |
for SYSCMODEL in $(SYSC_MODELS_BUILD); do \ |
echo;echo "\t$$SYSCMODEL"; echo; \ |
$(MAKE) -f Vorpsoc_top.mk $$SYSCMODEL.o; \ |
done |
export CXXFLAGS=$(VLT_DEBUG_COMPILE_FLAGS); \ |
export USER_CPPFLAGS="$(VLT_CPPFLAGS)"; \ |
export USER_LDDFLAGS="$(VLT_CPPFLAGS)"; \ |
$(MAKE) -f Vorpsoc_top.mk $$SYSCMODEL.o; \ |
done |
|
$(SIM_VLT_DIR)/Vorpsoc_top__ALL.a: $(SIM_VLT_DIR)/Vorpsoc_top.mk |
@echo; echo "\tCompiling main design"; echo |
@cd $(SIM_VLT_DIR) && \ |
export USER_CPPFLAGS="$(VLT_CPPFLAGS)"; \ |
export USER_LDDFLAGS="$(VLT_CPPFLAGS)"; \ |
$(MAKE) -f Vorpsoc_top.mk Vorpsoc_top__ALL.a |
|
$(SIM_VLT_DIR)/Vorpsoc_top.mk: $(SIM_VLT_DIR)/$(VLT_COMMAND_FILE).generated $(SIM_VLT_DIR)/libmodules.a |
614,12 → 631,13
# Now call verilator to generate the .mk files |
@echo; echo "\tGenerating makefiles with Verilator"; echo |
cd $(SIM_VLT_DIR) && \ |
verilator -language 1364-2001 -Wno-lint --top-module orpsoc_top -Mdir . -sc $(VLT_FLAGS) -I$(BENCH_SYSC_INCLUDE_DIR) -I$(BENCH_SYSC_SRC_DIR) -f $(VLT_COMMAND_FILE).generated |
verilator -language 1364-2001 -Wno-lint --top-module orpsoc_top $(VLT_DEBUG_OPTIONS) -Mdir . -sc $(VLT_FLAGS) -I$(BENCH_SYSC_INCLUDE_DIR) -I$(BENCH_SYSC_SRC_DIR) -f $(VLT_COMMAND_FILE).generated |
|
# SystemC modules library |
$(SIM_VLT_DIR)/libmodules.a: |
@echo; echo "\tCompiling SystemC modules"; echo |
@$(MAKE) -C $(BENCH_SYSC_SRC_DIR) -f $(BENCH_SYSC_SRC_DIR)/Modules.make |
@export VLT_CPPFLAGS="$(VLT_CPPFLAGS)"; \ |
$(MAKE) -C $(BENCH_SYSC_SRC_DIR) -f $(BENCH_SYSC_SRC_DIR)/Modules.make $(VLT_SYSC_DEBUG_DEFINE) |
|
|
# Verilator command script |
678,7 → 696,21
done; \ |
echo "Test results: "$$TESTS_PASSED" out of "$$TESTS_PERFORMED" tests passed"; echo |
|
############################################################################### |
# Verilator profiled module make |
############################################################################### |
# To run this, first run a "make prepare_vlt VLT_DO_PROFILING=1" then do a |
# "make clean" and then a "make prepare_vlt_profiled" |
# This new make target copies athe results of the profiling back to the right |
# paths before we create everything again |
############################################################################### |
prepare_vlt_profiled: vlt_restore_profileoutput prepare_rtl vlt_model_links $(SIM_VLT_DIR)/Vorpsoc_top |
|
vlt_restore_profileoutput: |
@echo;echo "\tRestoring profiling outputs"; echo |
@mkdir -p ../vlt |
@cp /tmp/*.gc* $(SIM_VLT_DIR) |
@cp /tmp/*.gc* $(BENCH_SYSC_SRC_DIR) |
|
################################################################################ |
# Architectural simulator test loop |
722,7 → 754,7
# Cleaning rules |
################################################################################ |
|
clean: clean-sw clean-sim clean-sysc clean-rtl clean_vpi |
clean: clean-sw clean-sim clean-sysc clean-rtl clean-vpi |
|
clean-sw: |
@for SWDIR in `ls $(SW_DIR)`; do \ |
731,6 → 763,10
done |
|
clean-sim: |
#backup any profiling output files |
@if [ -f $(SIM_VLT_DIR)/OrpsocMain.gcda ]; then echo "\tBacking up verilator profiling output"; \ |
cp $(SIM_VLT_DIR)/*.gc* /tmp; \ |
cp $(BENCH_SYSC_SRC_DIR)/*.gc* /tmp; fi |
rm -rf $(SIM_RESULTS_DIR) $(SIM_RUN_DIR)/*.* $(SIM_VLT_DIR) |
|
clean-sysc: |
/sw/dhry/dhry.c
15,6 → 15,7
**************************************************************************** |
*/ |
#include "support.h" |
#include "time.h" |
#include "dhry.h" |
#ifndef NUM_RUNS |
#define NUM_RUNS (1) |
26,7 → 27,7
void buserr_except(){} |
void dpf_except(){} |
void ipf_except(){} |
void lpint_except(){} |
void lpint_except(){timer_interrupt();} |
void align_except(){} |
void illegal_except(){} |
void hpint_except(){} |
207,8 → 208,8
/***************/ |
|
/* printf("%d", my_test2(Number_Of_Runs));*/ |
start_timer(TIMER0); |
Begin_Time = read_timer(TIMER0); |
start_timer(TIMER0); |
Begin_Time = read_timer(TIMER0); |
|
for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) |
{ |
/sw/dhry/Makefile
9,7 → 9,7
else |
NUM_RUNS="(10)" |
endif |
|
GCC_OPT += -g |
all: $(cases) |
|
dhry-nocache-O0: dhry-O0.o ../support/reset-nocache.o $(common) |
/sw/support/time.c
0,0 → 1,44
#include "support.h" |
#include "board.h" |
#include "spr_defs.h" |
|
/* Tick timer period */ |
#define SYS_CLKS_PER_TICK (IN_CLK/TICKS_PER_SEC) |
#define USEC_PER_SEC (1000000) |
#define USEC_PER_MSEC (1000) |
#define MSEC_PER_SEC (1000) |
#define USEC_PER_TICK (USEC_PER_SEC/TICKS_PER_SEC) |
|
unsigned long tick_period = SYS_CLKS_PER_TICK; |
unsigned long usec, msec, sec; // simple usec counter |
|
/* Start the timer, enabling interrupt, self-restart and set the period */ |
void |
init_timer(void) |
{ |
/* enable counter interrupt */ |
mtspr(SPR_SR,(mfspr(SPR_SR)|SPR_SR_TEE)); |
|
/* Set counter period, enable timer and interrupt */ |
/* SPR_TTMR_RT bit makes timer reset and restart itself automatically */ |
/* This will start it, too. */ |
mtspr(SPR_TTMR, SPR_TTMR_IE | SPR_TTMR_RT | (SYS_CLKS_PER_TICK & SPR_TTMR_PERIOD)); |
usec = 0, msec=0, sec=0; |
} |
|
/* Update timecounters */ |
void |
timer_interrupt(void) |
{ |
/* Update our time counters */ |
usec += USEC_PER_TICK; |
if (usec >= USEC_PER_MSEC ){ usec -= USEC_PER_MSEC; msec++; } |
if (msec >= MSEC_PER_SEC ){ msec -= MSEC_PER_SEC; sec++; } |
} |
|
/* Return time in microseconds */ |
unsigned int |
read_time_us(void) |
{ |
return ((sec*((MSEC_PER_SEC*USEC_PER_MSEC)))+(msec*(USEC_PER_MSEC))+usec); |
} |
/sw/support/time.h
0,0 → 1,4
|
extern unsigned long usec, msec, sec; // simple usec counter |
void init_timer(void); |
unsigned int read_time_us(void); |
/sw/support/except.S
1,5 → 1,115
#include "spr_defs.h" |
|
/* Defines and macros to help us handle execptions */ |
#define INT_FRAME_SIZE 144 |
|
#include "or32_funcs.S" |
|
|
|
#define EXCEPTION_HANDLE(handler) \ |
/* First store the SP like it was before execption to a temporary location, we use addr 0x80 */ ;\ |
l.sw 0x80(r0), r1 ;\ |
l.addi r1,r1,-(INT_FRAME_SIZE) ;\ |
l.sw GPR12(r1),r12 ;\ |
l.mfspr r12,r0,SPR_EPCR_BASE ;\ |
l.sw PC(r1),r12 ;\ |
l.mfspr r12,r0,SPR_ESR_BASE ;\ |
l.sw SR(r1),r12 ;\ |
l.lwz r12, 0x80(r0) ;\ |
/* Now store the previous SP onto except. stack*/ ;\ |
l.sw SP(r1),r12 ;\ |
/* save exception r4, set r4 = EA */ ;\ |
l.sw GPR4(r1),r4 ;\ |
l.mfspr r4,r0,SPR_EEAR_BASE ;\ |
/* r31: EA address of handler */ ;\ |
LOAD_SYMBOL_2_GPR(r12,handler) ;\ |
l.mtspr r0,r12,SPR_EPCR_BASE ;\ |
l.rfe |
|
|
#define HANDLER_ENTRY(handler) \ |
.global handler ;\ |
handler: ;\ |
l.sw GPR2(r1),r2 ;\ |
l.sw GPR3(r1),r3 ;\ |
/*l.sw GPR4(r1),r4*/ ;\ |
l.sw GPR5(r1),r5 ;\ |
l.sw GPR6(r1),r6 ;\ |
l.sw GPR7(r1),r7 ;\ |
l.sw GPR8(r1),r8 ;\ |
l.sw GPR9(r1),r9 ;\ |
l.sw GPR10(r1),r10 ;\ |
l.sw GPR11(r1),r11 ;\ |
/*l.sw GPR12(r1),r12*/ ;\ |
l.sw GPR13(r1),r13 ;\ |
l.sw GPR14(r1),r14 ;\ |
l.sw GPR15(r1),r15 ;\ |
l.sw GPR16(r1),r16 ;\ |
l.sw GPR17(r1),r17 ;\ |
l.sw GPR18(r1),r18 ;\ |
l.sw GPR19(r1),r19 ;\ |
l.sw GPR20(r1),r20 ;\ |
l.sw GPR21(r1),r21 ;\ |
l.sw GPR22(r1),r22 ;\ |
l.sw GPR23(r1),r23 ;\ |
l.sw GPR24(r1),r24 ;\ |
l.sw GPR25(r1),r25 ;\ |
l.sw GPR26(r1),r26 ;\ |
l.sw GPR27(r1),r27 ;\ |
l.sw GPR28(r1),r28 ;\ |
l.sw GPR29(r1),r29 ;\ |
l.sw GPR30(r1),r30 ;\ |
l.sw GPR31(r1),r31 ;\ |
l.sw RESULT(r1),r0 ;\ |
|
/* |
* We need to disable interrupts at beginning of RESTORE_ALL |
* since interrupt might come in after we've loaded EPC return address |
* and overwrite EPC with address somewhere in RESTORE_ALL |
* which is of course wrong! |
*/ |
|
#define RESTORE_ALL \ |
DISABLE_INTERRUPTS(r3,r4) ;\ |
l.lwz r3,PC(r1) ;\ |
l.mtspr r0,r3,SPR_EPCR_BASE ;\ |
l.lwz r3,SR(r1) ;\ |
l.mtspr r0,r3,SPR_ESR_BASE ;\ |
l.lwz r2,GPR2(r1) ;\ |
l.lwz r3,GPR3(r1) ;\ |
l.lwz r4,GPR4(r1) ;\ |
l.lwz r5,GPR5(r1) ;\ |
l.lwz r6,GPR6(r1) ;\ |
l.lwz r7,GPR7(r1) ;\ |
l.lwz r8,GPR8(r1) ;\ |
l.lwz r9,GPR9(r1) ;\ |
l.lwz r10,GPR10(r1) ;\ |
l.lwz r11,GPR11(r1) ;\ |
l.lwz r12,GPR12(r1) ;\ |
l.lwz r13,GPR13(r1) ;\ |
l.lwz r14,GPR14(r1) ;\ |
l.lwz r15,GPR15(r1) ;\ |
l.lwz r16,GPR16(r1) ;\ |
l.lwz r17,GPR17(r1) ;\ |
l.lwz r18,GPR18(r1) ;\ |
l.lwz r19,GPR19(r1) ;\ |
l.lwz r20,GPR20(r1) ;\ |
l.lwz r21,GPR21(r1) ;\ |
l.lwz r22,GPR22(r1) ;\ |
l.lwz r23,GPR23(r1) ;\ |
l.lwz r24,GPR24(r1) ;\ |
l.lwz r25,GPR25(r1) ;\ |
l.lwz r26,GPR26(r1) ;\ |
l.lwz r27,GPR27(r1) ;\ |
l.lwz r28,GPR28(r1) ;\ |
l.lwz r29,GPR29(r1) ;\ |
l.lwz r30,GPR30(r1) ;\ |
l.lwz r31,GPR31(r1) ;\ |
l.lwz r1,SP(r1) ;\ |
l.rfe |
|
|
// Linked from 0x200, so add 0x200 to the .org for the physical address |
.section .vectors, "ax" |
|
33,11 → 143,27
l.nop |
|
.org 0x300 |
|
_except_500: |
|
_except_500: |
#if 0 |
l.nop |
l.j _lpint_except |
l.nop |
#else |
/* First unset the timer interrupt bit */ |
l.addi r1,r1,-8 |
l.sw 0(r1),r31 |
l.sw 4(r1),r30 |
l.mfspr r31,r0,SPR_TTMR /* want to clear SPR_TTMR_IP bit from this reg*/ |
l.movhi r30,hi(SPR_TTMR_IP) |
l.ori r30,r30,lo(SPR_TTMR_IP) |
l.xor r31, r31, r30 |
l.mtspr r0,r31,SPR_TTMR |
l.lwz r31,0(r1) |
l.lwz r30,4(r1) |
l.addi r1, r1, 8 |
EXCEPTION_HANDLE(_timer_handler) |
#endif |
|
.org 0x400 |
|
109,3 → 235,37
l.j _res2_except |
l.nop |
|
|
.section .text, "ax" |
|
/* ---[ 0x500: Timer exception ]----------------------------------------- */ |
HANDLER_ENTRY(_timer_handler) |
l.addi r3,r1,0 |
LOAD_SYMBOL_2_GPR(r8,_timer_interrupt) |
l.jalr r8 |
l.nop |
l.j _ret_from_intr |
|
/* ---[ End of Timer exception ]----------------------------------------- */ |
|
ENTRY(_ret_from_intr) |
// i386 version: |
// GET_CURRENT(%ebx) |
|
ENTRY(_ret_from_exception) |
l.lwz r4,SR(r1) |
l.andi r3,r4,SPR_SR_SM |
l.sfeqi r3,0 |
l.bnf _restore_all |
l.nop |
/* |
* return to usermode |
*/ |
|
ENTRY(_restore_all) |
// we need to save KSP here too |
// or else fork's 'eat' stack space |
l.addi r4,r1,INT_FRAME_SIZE |
l.sw (TI_KSP)(r10),r4 |
RESTORE_ALL |
|
/sw/support/support.c
5,6 → 5,7
#endif |
|
#include "spr_defs.h" |
#include "time.h" |
#include "support.h" |
#include "int.h" |
|
14,9 → 15,9
#include "uart.h" |
#endif |
|
#if OR32 |
|
void excpt_dummy(); |
void int_main(); |
//void int_main(); |
|
unsigned long excpt_buserr = (unsigned long) excpt_dummy; |
unsigned long excpt_dpfault = (unsigned long) excpt_dummy; |
92,18 → 93,6
l.nop %0": :"K" (NOP_PRINTF), "r" (fmt), "r" (args)); |
} |
|
/* |
void *memcpy (void *__restrict dstvoid, |
__const void *__restrict srcvoid, size_t length) |
{ |
char *dst = dstvoid; |
const char *src = (const char *) srcvoid; |
|
while (length--) |
*dst++ = *src++; |
return dst; |
} |
*/ |
#endif |
|
|
125,6 → 114,7
/* start_TIMER */ |
void start_timer(int x) |
{ |
init_timer(); |
} |
|
/* read_TIMER */ |
131,12 → 121,7
/* Returns a value since started in uS */ |
unsigned int read_timer(int x) |
{ |
unsigned long count = 0; |
|
/* Read the Time Stamp Counter */ |
/* asm("simrdtsc %0" :"=r" (count)); */ |
/*asm("l.sys 201"); */ |
return count; |
return read_time_us(); |
} |
|
/* For writing into SPR. */ |
153,30 → 138,5
return value; |
} |
|
#else |
void report(unsigned long value) |
{ |
printf("report(0x%x);\n", (unsigned) value); |
} |
|
/* start_TIMER */ |
void start_timer(int tmrnum) |
{ |
} |
|
/* read_TIMER */ |
/* Returns a value since started in uS */ |
unsigned int read_timer(int tmrnum) |
{ |
struct timeval tv; |
struct timezone tz; |
|
gettimeofday(&tv, &tz); |
|
return(tv.tv_sec*1000000+tv.tv_usec); |
} |
|
#endif |
|
|
void excpt_dummy() {} |
/sw/support/orp.ld
7,13 → 7,22
icm : ORIGIN = 0x00800000, LENGTH = 0x00004000 |
} |
*/ |
|
MEMORY |
{ |
reset : ORIGIN = 0x00000000, LENGTH = 0x00000200 |
vectors : ORIGIN = 0x00000200, LENGTH = 0x00001000 |
ram : ORIGIN = 0x00001200, LENGTH = 0x00FFED00 |
vectors : ORIGIN = 0x00000200, LENGTH = 0x00001E00 |
ram : ORIGIN = 0x00002000, LENGTH = 0x00FFE000 |
} |
|
/* |
MEMORY |
{ |
reset : ORIGIN = 0xc0000000, LENGTH = 0x00000200 |
vectors : ORIGIN = 0xc0000200, LENGTH = 0x00001000 |
ram : ORIGIN = 0xc0001200, LENGTH = 0x00FFED00 |
} |
*/ |
SECTIONS |
{ |
.reset : |
/sw/support/support.h
8,9 → 8,8
#include <stdarg.h> |
#include <stddef.h> |
#include <limits.h> |
#define OR1K 1 //ME added |
#if OR1K |
|
|
/* Register access macros */ |
#define REG8(add) *((volatile unsigned char *)(add)) |
#define REG16(add) *((volatile unsigned short *)(add)) |
24,12 → 23,7
/* For reading SPR. */ |
unsigned long mfspr(unsigned long spr); |
|
#else /* OR1K */ |
|
#include <stdio.h> |
|
#endif /* OR1K */ |
|
/* Function to be called at entry point - not defined here. */ |
int main (); |
|
/sw/support/int.c
5,8 → 5,8
#include "spr_defs.h" |
#include "int.h" |
|
#ifdef OR1K |
|
|
/* Interrupt handlers table */ |
struct ihnd int_handlers[MAX_INT_HANDLERS]; |
|
42,7 → 42,7
{ |
if(vect >= MAX_INT_HANDLERS) |
return -1; |
|
|
mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(0x00000001L << vect)); |
|
return 0; |
76,4 → 76,4
} |
} |
|
#endif |
|
/sw/support/Makefile
2,13 → 2,17
|
all: libsupport.a reset-nocache.o reset-ic.o reset-dc.o reset-icdc.o |
|
libsupport.a: support.o int.o except.o uart.o vfnprintf.o |
$(OR32_TOOL_PREFIX)-ar cru libsupport.a support.o except.o int.o uart.o vfnprintf.o |
libsupport.a: support.o int.o except.o uart.o vfnprintf.o time.o |
$(OR32_TOOL_PREFIX)-ar cru libsupport.a $? |
$(OR32_TOOL_PREFIX)-ranlib libsupport.a |
|
support.o: support.c |
# A generic rule for c |
%.o: %.c |
$(OR32_TOOL_PREFIX)-gcc $(GCC_OPT) -O2 -c -o $@ $? |
|
# A generic rule for assembly files |
%.o: %.S |
$(OR32_TOOL_PREFIX)-gcc $(GCC_OPT) -O2 -c -o $@ $? |
# Rules for each specific reset type we want |
reset-nocache.o: reset.S |
$(OR32_TOOL_PREFIX)-gcc $(GCC_OPT) -O2 -c -DIC=0 -DDC=0 -o $@ $? |
|
21,17 → 25,3
reset-icdc.o: reset.S |
$(OR32_TOOL_PREFIX)-gcc $(GCC_OPT) -O2 -c -DIC=1 -DDC=1 -o $@ $? |
|
except.o: except.S |
$(OR32_TOOL_PREFIX)-gcc $(GCC_OPT) -O2 -c -o $@ $? |
|
uart.o: uart.c |
$(OR32_TOOL_PREFIX)-gcc $(GCC_OPT) -O2 -c -o $@ $? |
|
#snprintf.o: snprintf.c |
# $(OR32_TOOL_PREFIX)-gcc $(GCC_OPT) -O2 -c -o $@ $? |
|
vfnprintf.o: vfnprintf.c |
$(OR32_TOOL_PREFIX)-gcc $(GCC_OPT) -O2 -c -o $@ $? |
|
int.o: int.c |
$(OR32_TOOL_PREFIX)-gcc $(GCC_OPT) -O2 -c -o $@ $? |