LOGIN   :::   RECOVER PASS   :::   GET ACCOUNT    
Browse
  • Projects
  • Code (CVS)
  • Forums
  • News
  • Articles
  • Polls
  •  
    OpenCores
  • FAQ
  • CVS HowTo
  • Mission
  • Media
  • Tools
  • Advertise
  • Mirrors
  • Logos
  • Contact us
  • Job Opportunity
  •  
    Tools
  • Search
      
  • Download Cores (CVSGet)
  •  
    More
  • Wishbone
  • Perlilog
  • EDA tools
  • OpenTech CD
  •  
    Navigation: All forums > Cvs-checkins > Message List > Message Post

    Message

    Reply | Reply all
    Date Prev | Date Next | Thread Prev | Thread Next Date Index | Thread Index

    From: cvs at opencores.org<cvs@o...>
    Date: Wed Jul 23 00:17:33 CEST 2008
    Subject: [cvs-checkins] MODIFIED: jop ...
    Top
    Date: 00/08/07 23:00:17

    Modified: jop/doc/book/cmp cmp.tex
    Log:
    Start CMP section


    Revision Changes Path
    1.2 jop/doc/book/cmp/cmp.tex

    http://www.opencores.org/cvsweb.shtml/jop/doc/book/cmp/cmp.tex.diff?r1=1.1&r2=1.2

    (In the diff below, changes in quantity of whitespace are not shown.)

    Index: cmp.tex
    ===================================================================
    RCS file: /cvsroot/martin/jop/doc/book/cmp/cmp.tex,v
    retrieving revision 1.1
    retrieving revision 1.2
    diff -u -b -r1.1 -r1.2
    --- cmp.tex 22 Jul 2008 21:56:01 -0000 1.1
    +++ cmp.tex 22 Jul 2008 22:17:33 -0000 1.2
    @@ -1,3 +1,5 @@
    +\index{CMP}
    +
    This chapter describes the configuration of a chip multiprocessor
    (CMP) version of JOP. The various SimpCon based arbiters have been
    developed by Christof Pitter and are described in \cite{jop:dma,
    @@ -9,8 +11,73 @@

    \section{Booting a CMP System}

    +\index{CMP!booting}
    +
    +One interesting issue for a CMP system is the question how the
    +startup or boot-up is performed. Before we explain the CMP solution,
    +we need an understanding of the boot-up sequence of JOP in an FPGA.
    +On power-up, the FPGA starts the configuration state machine to read
    +the FPGA configuration data either from a Flash or via a download
    +cable (for development). When the configuration has finished an
    +internal reset is generated. After that reset, microcode instructions
    +are executed starting from address 0. At this stage, we have not yet
    +loaded any application program (Java bytecode). The first sequence in
    +microcode performs this task. The Java application can be loaded from
    +an external Flash or via a serial line (or USB port) from a PC. The
    +microcode assembly configured the mode. Consequently, the Java
    +application is loaded into the main memory. To simplify the startup
    +code we perform the rest of the startup in Java itself, even when
    +some parts of the JVM are not yet setup.
    +
    +In the next step, a minimal stack frame is generated and the special
    +method \code{Startup.boot()} is invoked. From now on JOP runs in Java
    +mode. The method \code{boot()} performs the following steps:
    +\begin{samepage}
    +\begin{itemize}
    + \item Send a greeting message to \emph{stdout}
    + \item Detect the size of the main memory
    + \item Initialize the data structures for the garbage
    + collector
    + \item Initialize \code{java.lang.System}
    + \item Print out JOP's version number, detected clock speed,
    + and memory size
    + \item Invoke the static class initializers in a predefined
    + order
    + \item Invoke the \code{main} method of the application class
    +\end{itemize}
    +\end{samepage}
    +
    +The boot-up process is the same for all processors until the
    +generation of the internal reset and the execution of the first
    +microcode instruction. From that point on, we have to take care that
    +\emph{only one} processor performs the initialization steps.
    +
    +All processors in the CMP are functionally identical. Only one
    +processor is designated to boot-up and initialize the whole system.
    +Therefore, it is necessary to distinguish between the different CPUs.
    +We assign a unique CPU identity number (CPU ID) to each processor.
    +Only processor CPU0 is designated to do all the boot-up and
    +initialization work. The other CPUs have to wait until CPU0 completes
    +the boot-up and initialization sequence. At the beginning of the
    +booting sequence, CPU0 loads the Java application. Meanwhile, all
    +other processors are waiting for an \emph{initialization finished}
    +signal of CPU0. This busy wait is performed in microcode. When the
    +other CPUs are enabled, they will run the same sequence as CPU0.
    +Therefore, the initialization steps are guarded by a condition on the
    +CPU ID.
    +
    +In our current prototype, we let all additional CPUs also invoke the
    +main method of the application. This is a shortcut for a simple
    +evaluation of the system\footnote{In the main method we execute
    +different applications based on the CPU ID.}. In a future version,
    +the additional CPUs will invoke a system method to be integrated into
    +the normal scheduling system.
    +
    +
    \section{CMP Scheduling}

    +\index{CMP!scheduling}
    +
    There are two possibilities to run multiple threads on the CMP
    system:

    @@ -19,4 +86,150 @@ \item Several threads on each processor \end{enumerate} -For the configuration of one thread per processor +For the configuration of one thread per processor the scheduler does +not need to be started. Running several threads on each core is +managed via the JOP real-time threads \code{RtThread}. On each core a +local preemptive, priority based scheduler runs. Threads cannot +migrate from one core to another one. + +\subsection{One Thread per Core} + + +The first processor executes, as usual, \code{main()}. To execute +code on the other cores a \code{Runnable} has to be registered for +each core. After registering those Runnables the other cores need to +be started. The following code shows an example that can be found in +\dirent{test/cmp/HelloCMP.java}. + +\begin{verbatim} +public class HelloCMP implements Runnable { + + int id; + + static Vector msg; + + public HelloCMP(int i) { + id = i; + } + + /** + * @param args + */ + public static void main(String[] args) { + + msg = new Vector(); + + System.out.println("Hello World from CPU 0"); + + SysDevice sys = IOFactory.getFactory().getSysDevice(); + for (int i=0; i<sys.nrCpu-1; ++i) { + Runnable r = new HelloCMP(i+1); + Startup.setRunnable(r, i); + } + + // start the other CPUs + sys.signal = 1; + + // print their messages + for (;;) { + int size = msg.size(); + if (size!=0) { + StringBuffer sb = (StringBuffer) msg.remove(0); + System.out.println(sb); + } + } + } + + public void run() { + + StringBuffer sb = new StringBuffer(); + sb.append("Hello World from CPU "); + sb.append(id); + msg.addElement(sb); + } + +} +\end{verbatim} + +\subsection{Scheduling on the CMP System} + +Running several threads on each core is possible with \code{RtThread} +and setting the core for each thread with +\code{RtThread.setProcessor(nr)}. The following example +(\code{test/cmp/RtHelloCMP.java}) shows registering 50 threads on +three cores. On \code{missionStart()} the threads are distributed to +the cores, a scheduler for each core registered as timer interrupt +handler, and the other cores started. + +\begin{verbatim} +public class RtHelloCMP extends RtThread { + + public RtHelloCMP(int prio, int us) { + super(prio, us); + } + + int id; + + public static Vector msg; + + final static int NR_THREADS = 50; + + /** + * @param args + */ + public static void main(String[] args) { + + msg = new Vector(); + + System.out.println("Hello World from CPU 0"); + + SysDevice sys = IOFactory.getFactory().getSysDevice(); + for (int i=0; i<NR_THREADS; ++i) { + RtHelloCMP th = new RtHelloCMP(1, 1000*1000); + th.id = i; + th.setProcessor(i%sys.nrCpu); + } + + System.out.println("Start mission"); + // start mission and other CPUs + RtThread.startMission(); + System.out.println("Mission started"); + + // print their messages + for (;;) { + RtThread.sleepMs(5); + int size = msg.size(); + if (size!=0) { + StringBuffer sb = (StringBuffer) msg.remove(0); + // System.out.print(sb); + // converts StringBuffer to a String and creates garbage + for (int i=0; i<sb.length(); ++i) { + System.out.print(sb.charAt(i)); + } + } + } + } + + public void run() { + + StringBuffer sb = new StringBuffer(); + StringBuffer ping = new StringBuffer(); + + sb.append("Thread "); + sb.append((char) ('A'+id)); + sb.append(" start on CPU "); + sb.append(IOFactory.getFactory().getSysDevice().cpuId); + sb.append("\r\n"); + msg.addElement(sb); + waitForNextPeriod(); + + for (;;) { + ping.setLength(0); + ping.append((char) ('A'+id)); + msg.addElement(ping); + waitForNextPeriod(); + } + } + +} +\end{verbatim}

     
    Copyright (c) 1999 OPENCORES.ORG. All rights reserved.