\chapter{Processor}
\label{tp}


%-----------------------------------------------------------------------------
\section{Architecture}
\label{tp:arch}

\begin{figure}[htb]
 \centering
 \includegraphics*[width=15cm]{chap_tp/block1.eps}
 \caption[Block diagram of the Processor core]{Block diagram of the CPU core.}
 \label{fig:cpu}
\end{figure}


%-----------------------------------------------------------------------------
\subsection{Local and Global Bus}
\label{tp:arch:lgio}

The I/O space of the CPUs is divided into Local and Global space.
By Local bus access the address space is 12 bit only, therefore
all local addresses in this document are printed using 3 hex digits. The event buffers and NI
registers in the local I/O need one extra clock by reading. This is illustrated in the
examples to the assembler instructions for local I/O. The timer/counter has no
latency.

By Global bus access the CPU core activates a request to the Arbiter.
The priorities in Arbiter are fixed:

highest: SCSN read $\rightarrow $ read CPU0 $\rightarrow $ read CPU1 $\rightarrow $ 
read CPU2 $\rightarrow $ read CPU3 $\rightarrow $ SCSN write $\rightarrow $ write CPU0 
$\rightarrow $ write CPU1 $\rightarrow $ write CPU2 $\rightarrow $ write CPU3 (lowest)

When some CPU needs to write, it must check first if its bus flag is set and wait until
the bus flag is cleared. Then the CPU writes some data at some address. They will be stored
in address/data registers in arbiter. The CPU doesn't need to do anything more.
The arbiter makes the write transaction on the global bus (see the priority).

\begin{figure}[htb]
 \centering
 \includegraphics*[width=12cm]{chap_tp/arbiter.eps}
 \caption[Arbiter block diagram]{Arbiter block diagram.}
 \label{fig:arb}
\end{figure}

When some CPU wants to read, it must check first if its bus flag is set and wait until
the bus flag is cleared. Then the CPU starts the read, the address will be stored in the address
register in the arbiter. The arbiter makes the read transaction on the bus (see the priority).
The data coming from the global device will be stored in one of the two temp registers.
When the CPU sees that the bus flag is cleared, this means the read data are already stored.
They can be read by the CPU on its local bus. By default, the first register
(at 0x300) is to be used by 'normal' programs, the second (at 0x301) - by interrupt programs.

\register{GBUSR0}{0x300}{Global bus read register 0 in local IO}
{Global bus read register 0 in local IO}
{RRRR RRRR RRRR RRRR RRRR RRRR RRRR RRRR}
{---- ---- ---- ---- ---- ---- ---- ----}
{R & the arbiter writes here the data read from the global IO\\
}

\register{GBUSR1}{0x301}{Global bus read register 1 in local IO}
{Global bus read register 1 in local IO}
{RRRR RRRR RRRR RRRR RRRR RRRR RRRR RRRR}
{---- ---- ---- ---- ---- ---- ---- ----}
{R & the arbiter writes here the data read from the global IO\\
}

The timing on the global bus can be programmed independently for read and write transactions. After reset
both will be set to the slowest access by writing to the register ARBTIM. From simulations it is expected
that except for the DFF based tables in Filter/Preprocessor, the read timing can be the fastest. For
write timing the fastest should be OK on all cases.

\begin{figure}[htb]
 \centering
 \includegraphics*[width=15cm]{chap_tp/arb_rd.eps}
 \caption[Arbiter read timing ]{Arbiter read timing (00, 01, 10, 11).}
 \label{fig:arb_rd}
\end{figure}

\begin{figure}[htb]
 \centering
 \includegraphics*[width=15cm]{chap_tp/arb_wr.eps}
 \caption[Arbiter write timing]{Arbiter write timing (00, 01, 10, 11).}
 \label{fig:arb_wr}
\end{figure}

\register{ARBTIM}{0x0A3F}{Configuration of the timing on the global bus}
{Register to configure the timing on the global bus}
{---- ---- ---- ---- ---- ---- ---- wwrr}
{---- ---- ---- ---- ---- ---- ---- 0000}
{w & timing by write transactions on the global bus. "00" - the slowest, "11" -
the fastest. Recommended "11". See Figure \ref{fig:arb_wr}\\
r & timing by read transactions on the global bus. "00" - the slowest, "11" -
the fastest. Recommended "01". See Figure \ref{fig:arb_rd}\\
}

NOTE: Avoid using the shortest read timing. In this case it is possible to have read errors when accessing some
configuration registers in Filter/Preprocessor. Second, as the memories are synchronous, only one clock is not
enough to latch the address and to get the data, instead the data corresponding to the previous address will appear
on the bus.

%-----------------------------------------------------------------------------
\subsection{Instruction and data memory}
\label{tp:arch:memo}

The data memory is 1k x 32(+7 hamming bits)-bit, quad ported - each CPU can independently on the others read or write.

For CPUs the data memory address is BYTE address (0x0000..0x0FFF). The most significant part of the 32 bit data
word has higher address. Writing is possible only in 32-bit words at aligned addresses
(4*k). Reading can be either 32-bit at 32-bit aligned addresses (4*k), or 16-bit at
16-bit aligned addresses (4*k, 4*k+2), or 8-bit (4*k, 4*k+1, 4*k+2, 4*k+3). The last
two read modes are shown on Figure \ref{fig:memr}. The unused address bits by reading
(32 and 16 bit access) and writing are simply ignored. When reading/writing DMEM through the global bus
(this is the case for SCSN access), the address is 32-bit word address
(from 0 to 0x3FF).

\begin{figure}[htb]
 \centering
 \includegraphics*[width=15cm]{chap_tp/memr.eps}
 \caption[Data memory, 8-bit and 16-bit memory read mode]{Data memory, 8-bit and 16-bit memory read mode.}
 \label{fig:memr}
\end{figure}

The instruction memory is 4 x 4k x 24(+6 hamming bits)-bit single ported. The address is
24-bit word address. Each CPU has a separate IMEM block (4k x 24).

The data and instruction memory blocks can be accessed through the global bus by the
SCSN slave or by the CPUs. This is only possible, when the corresponding CPU is
switched off (has no clock) for IMEM and if CPU3 is switched off for DMEM. 
The first method for accessing IMEM/DMEM is in the address window 0xE000-0xEFFF and the configuration
register MEMRW. For IMEM
bit 0 in MEMRW must be set, in addition must be specified either the read block 
by reading or the write enables for each block by writing (see MEMRW). Then the IMEM
block(s) will be mapped to the global bus address space 0xE000 ... 0xEFFF.

For DMEM bit 0 in MEMRW must be cleared. Then the port 3 (of CPU3) of DMEM will be
mapped to the global bus address space 0xE000 ... 0xF3FF (full custom QPMEM). Note that the access to the DMEM is only in 
32 bit mode and the address is word address (unlike the CPU access).

\register{MEMRW}{0xD000}{Configuration Global bus access to IMEM/DMEM}
{Register to configure the Global bus access to IMEM/DMEM}
{---- ---- ---- ---- ---- ---- -www wrri}
{---- ---- ---- ---- ---- ---- -111 1001}
{i & selects between IMEM (1) and DMEM (0).\\
w & write mask for IMEM of CPU 3..0. If set, writing to IMEM will write to the
corresponding IMEM block. So it is possible to write simultaneously common 
parts of the code. Ignored for writing to DMEM.\\
r & read IMEM bank. Ignored in the case of DMEM read.\\
}

There is an other way to specify dynamically the IMEM write mask. If the bit 31
of the write data is set, then the write mask will be taken from write data bits 
27 .. 24 instead from the MEMRW.w register.

Each IMEM block and DMEM have an independent address windows in the IO space. This is practical for
reading, because there is no need to reprogram the register MEMRW. For writing in IMEM the most
flexible method is by using the dynamical write mask.
In addition, there is a general purpose memory bank (256 x 32 bit) which is accessible
only through the global IO. Table \ref{tab:memio} shows the complete memory to IO map.

\begin{table}[htb]
 \centering
 \scriptsize
\begin{tabular}{|c|c|c|c|c|c|c|c|}\hline
MEM             & IMEM0  & IMEM1  & IMEM2  & IMEM3  & DMEM  & DBANK   & using MEMRW\\ \hline
from IO address & 0x8000 & 0x9000 & 0xA000 & 0xB000 & 0xC000 & 0xF000 & 0xE000     \\ \hline
to IO address   & 0x8FFF & 0x9FFF & 0xAFFF & 0xBFFF & 0xC3FF & 0xF0FF & 0xEFFF     \\ \hline
\end{tabular}
\caption[IO mapping IMEM/DMEM]
{IO mapping IMEM/DMEM}
 \label{tab:memio}
\end{table}

The hamming correction by reading from the IMEM, DMEM and DBANK can be bypassed by
clearing the corresponding bits in MEMCOR. This will not affect the writing - the
hamming bits will be always written together with the normal data bits.

\register{MEMCOR}{0xD001}{Configuration hamming correction IMEM/DMEM}
{Register to configure the hamming correction in IMEM/DMEM}
{---- ---- ---- ---- ---- ---b dddd iiii}
{---- ---- ---- ---- ---- ---0 0000 0000}
{b & enable (when 1) the hamming correction in the DBANK read port.\\
 d & enable (when 1) the hamming correction in the corresponding DMEM read port (3..0).\\
 i & enable (when 1) the hamming correction in the corresponding IMEM read port (3..0).\\
}

The internal timing in the DMEM can be adjusted via the two registers \reg{DMDELA} and
\reg{DMDELS}.

\register{DMDELA}{0xD002}{Configuration internal timing in DMEM address lines}
{Register to configure the internal timing in DMEM address lines}
{---- ---- ---- ---- ---- ---- ---- aaaa}
{---- ---- ---- ---- ---- ---- ---- 1000}
{a & internal timing in DMEM address lines\\
}

The recommended value of \reg{DMDELA} is 2.

\register{DMDELS}{0xD003}{Configuration internal timing in DMEM sense amplifiers}
{Register to configure the internal timing in DMEM sense amplifiers}
{---- ---- ---- ---- ---- ---- ---- ssss}
{---- ---- ---- ---- ---- ---- ---- 1000}
{a & internal timing in DMEM sense amplifiers\\
}

The recommended value of \reg{DMDELS} is 15.

The hamming counters count the number of correctable, parity and non-correctable read errors, independly
on the hamming bypass (it is for data path only). If some of the three hamming counter in a group is 0x3FF, all
three counters will be disabled. The IMEM hamming counters can be cleared individually by writing to the
corresponding address something. All DMEM hamming counters can be cleared simultaneously by writing to
one of the four addresses something. There are no hamming counters attached to the DBANK.

\register{HCNTI0}{0xD010}{Hamming counters IMEM0}
{Hamming counters IMEM0}
{O0CC CCCC CCCC PPPP PPPP PPNN NNNN NNNN}
{0000 0000 0000 0000 0000 0000 0000 0000}
{O & overflow in some of the counters\\
 C & number of correctable errors\\
 P & number of parity errors\\
 N & number of non-correctable errors\\
}

\register{HCNTI1}{0xD011}{Hamming counters IMEM1}
{Hamming counters IMEM1}
{O0CC CCCC CCCC PPPP PPPP PPNN NNNN NNNN}
{0000 0000 0000 0000 0000 0000 0000 0000}
{O & overflow in some of the counters\\
 C & number of correctable errors\\
 P & number of parity errors\\
 N & number of non-correctable errors\\
}

\register{HCNTI2}{0xD012}{Hamming counters IMEM2}
{Hamming counters IMEM2}
{O0CC CCCC CCCC PPPP PPPP PPNN NNNN NNNN}
{0000 0000 0000 0000 0000 0000 0000 0000}
{O & overflow in some of the counters\\
 C & number of correctable errors\\
 P & number of parity errors\\
 N & number of non-correctable errors\\
}

\register{HCNTI3}{0xD013}{Hamming counters IMEM3}
{Hamming counters IMEM3}
{O0CC CCCC CCCC PPPP PPPP PPNN NNNN NNNN}
{0000 0000 0000 0000 0000 0000 0000 0000}
{O & overflow in some of the counters\\
 C & number of correctable errors\\
 P & number of parity errors\\
 N & number of non-correctable errors\\
}

Note: writing to HCNTI0,1,2,3 will clear the corresponding hamming counters.

\register{HCNTD0}{0xD014}{Hamming counters DMEM0}
{Hamming counters DMEM0}
{O0CC CCCC CCCC PPPP PPPP PPNN NNNN NNNN}
{0000 0000 0000 0000 0000 0000 0000 0000}
{O & overflow in some of the counters\\
 C & number of correctable errors\\
 P & number of parity errors\\
 N & number of non-correctable errors\\
}

\register{HCNTD1}{0xD015}{Hamming counters DMEM1}
{Hamming counters DMEM1}
{O0CC CCCC CCCC PPPP PPPP PPNN NNNN NNNN}
{0000 0000 0000 0000 0000 0000 0000 0000}
{O & overflow in some of the counters\\
 C & number of correctable errors\\
 P & number of parity errors\\
 N & number of non-correctable errors\\
}

\register{HCNTD2}{0xD016}{Hamming counters DMEM2}
{Hamming counters DMEM2}
{O0CC CCCC CCCC PPPP PPPP PPNN NNNN NNNN}
{0000 0000 0000 0000 0000 0000 0000 0000}
{O & overflow in some of the counters\\
 C & number of correctable errors\\
 P & number of parity errors\\
 N & number of non-correctable errors\\
}

\register{HCNTD3}{0xD017}{Hamming counters DMEM3}
{Hamming counters DMEM3}
{O0CC CCCC CCCC PPPP PPPP PPNN NNNN NNNN}
{0000 0000 0000 0000 0000 0000 0000 0000}
{O & overflow in some of the counters\\
 C & number of correctable errors\\
 P & number of parity errors\\
 N & number of non-correctable errors\\
}

Note: writing to any of HCNTD0,1,2,3 will clear all hamming counters of DMEM.


%-----------------------------------------------------------------------------
\subsection{Constants}
\label{tp:arch:cons}

The CPU core can use 16 constants like normal registers (read only). Eight of them
are fixed (0..7), see Table \ref{tab:const}. CPU\_ID is from 0 to 3 and is the
simplest way for one CPU to see its ID.

\begin{table}[htb]
 \centering
 \scriptsize
\begin{tabular}{|l|c|c|c|c|c|c|c|c|}\hline
Const\# & 0 & 1 & 2 & 3 & 4 & 5       &  6 &  7\\ \hline
value   & 0 & 1 & 2 & 3 & 4 & CPU\_ID & -2 & -1\\ \hline
\end{tabular}
\caption[Hardwired constants, CPU\_ID is 0, 1, 2 or 3.]
{Hardwired constants}
 \label{tab:const}
\end{table}

The next four constants (8..11) are programmable
individually for each CPU core. The last four are programmable but common for all CPU
cores. Table \ref{tab:constgio} shows how to program the constants through the global
bus. Note that the common constants are mapped four times in the address space.

\begin{table}[htb]
 \centering
 \scriptsize
\begin{tabular}{|c|c|c|l|}\hline
Address in Global IO  &   CPU   & Const\#   & Comment \\ \hline \hline
{\ttfamily 0x0C00}   &    0    &   8      & privat \\\hline
{\ttfamily 0x0C01}   &    0    &   9      & privat \\\hline
{\ttfamily 0x0C02}   &    0    &  10      & privat \\\hline
{\ttfamily 0x0C03}   &    0    &  11      & privat \\\hline
                     &         &          &        \\\hline
{\ttfamily 0x0C08}   &    1    &   8      & privat \\\hline
{\ttfamily 0x0C09}   &    1    &   9      & privat \\\hline
{\ttfamily 0x0C0A}   &    1    &  10      & privat \\\hline
{\ttfamily 0x0C0B}   &    1    &  11      & privat \\\hline
                     &         &          &        \\\hline
{\ttfamily 0x0C10}   &    2    &   8      & privat \\\hline
{\ttfamily 0x0C11}   &    2    &   9      & privat \\\hline
{\ttfamily 0x0C12}   &    2    &  10      & privat \\\hline
{\ttfamily 0x0C13}   &    2    &  11      & privat \\\hline
                     &         &          &        \\\hline
{\ttfamily 0x0C18}   &    3    &   8      & privat \\\hline
{\ttfamily 0x0C19}   &    3    &   9      & privat \\\hline
{\ttfamily 0x0C1A}   &    3    &  10      & privat \\\hline
{\ttfamily 0x0C1B}   &    3    &  11      & privat \\\hline
                     &         &          &        \\\hline
{\ttfamily 0x0C04, 0x0C0C, 0x0C14, 0x0C1C}   &   ALL   &  12      & common \\\hline
{\ttfamily 0x0C05, 0x0C0D, 0x0C15, 0x0C1D}   &   ALL   &  13      & common \\\hline
{\ttfamily 0x0C06, 0x0C0E, 0x0C16, 0x0C1E}   &   ALL   &  14      & common \\\hline
{\ttfamily 0x0C07, 0x0C0F, 0x0C17, 0x0C1F}   &   ALL   &  15      & common \\\hline

\end{tabular}
\caption[Programmable constants]
{Programmable constants}
\label{tab:constgio}
\end{table}


%-----------------------------------------------------------------------------
\section{Interrupts}
\label{tp:intr}

Each CPU core has its own interrupt controller. Most of the interrupts are common for
all CPU cores, some are local (LTIMER, NI0, NI1, NI2). In order to use some interrupt
one must specify the corresponding bits in the three mask registers and the start
address of the interrupt procedure.

If IRQHL(i) is set, the i-th interrupt is a high-level interrupt.
If IRQHW(i) is set, the i-th interrupt is enabled as hardware interrupt.
If IRQSW(i) is set, the i-th interrupt is enabled as software interrupt.

\begin{figure}[htb]
 \centering
 \includegraphics*[width=8cm]{chap_tp/irq.eps}
 \caption[I/O map of interrupt controller registers]{I/O map of interrupt controller registers.}
 \label{fig:irq}
\end{figure}

If the high-level bit is set, the interrupt is enabled as both hardware and
software. Each high-level interrupt can wake up the CPU, for this bit t and
bits mm in CPUnCLK register must be set, see Chapter \ref{sm:dia}.
After high-level interrupt the CPU will jump to the programmed address in the
interrupt table. No return address and status will be stored.

IRQ 0 has the highest priority, IRQ 12 the lowest priority, within one and the same 
group (high level or low level).

In the case of low-level interrupt, the return address and the status (flags) will be
stored in temporary registers and restored after executing IRT (interrupt return).
All low level interrupts can be disabled by the instruction CLI and enabled by the
instruction STI.

Any unused hardware interrupt can be used as software interrupt - this is a simple
way to organize subroutines.

The external interrupt input pin is active low. It will be synchronized with the
system clock and differentiated digitally - so it is edge sensitive.

After reset the low level interrupts are disabled, IRQSW will be filled with '1',
IRQHW and IRQHL will be cleared.

See the information and examples for the instructions \hlink{CLI}, \hlink{STI}, \hlink{INT}, \hlink{COPIRQ},
\hlink{IRQCLR},
\hlink{IRT} in Chapter \ref{tp:instr}.

As all four interrupt controllers are identical, the internal registers are shown as
generic. The base addresses (BA) for the four controllers are given in Table
\ref{tab:irqio}.

13 interrupt addresses for i=0 to 12:

\register{IA[i]}{BA+i}{Interrupt address}
{Interrupt address for interrupt i and CPU c}
{---- ---- ---- ---- ---- aaaa aaaa aaaa}
{---- ---- ---- ---- ---- 0000 0000 0000}
{a & address of the interrupt procedure\\
}

\register{IRQSW}{BA+0x0D}{Mask software interrupts}
{Mask software interrupts for CPU c}
{---- ---- ---- ---- ---m mmmm mmmm mmmm}
{---- ---- ---- ---- ---1 1111 1111 1111}
{m & enable (1)/disable (0) the interrupt as software interrupt\\
}

\register{IRQHW}{BA+0x0E}{Mask hardware interrupts}
{Mask hardware interrupts for CPU c}
{---- ---- ---- ---- ---m mmmm mmmm mmmm}
{---- ---- ---- ---- ---0 0000 0000 0000}
{m & enable (1)/disable (0) the interrupt as hardware interrupt\\
}

\register{IRQHL}{BA+0x0F}{Mask high-level interrupts}
{Mask high-level interrupts for CPU c}
{---- ---- ---- ---- ---m mmmm mmmm mmmm}
{---- ---- ---- ---- ---0 0000 0000 0000}
{m & enable (1)/disable (0) the interrupt as high-level interrupt\\
}

\begin{table}[htb]
 \centering
 \scriptsize
\begin{tabular}{|l|c|c|c|c|}\hline
CPU\#       & 0      & 1       & 2      & 3      \\ \hline
Base Address & 0x0B00 & 0x0B20  & 0x0B40 & 0x0B60 \\ \hline
\end{tabular}
\caption[Base Addresses of the interrupt controllers.]
{Base addresses of the interrupt controllers}
 \label{tab:irqio}
\end{table}

%-----------------------------------------------------------------------------
\section{Synchronization}
\label{tp:sync}

Each CPU has its own synchronization register. When some CPU writes to GRF[i] then the i-th bit in all
four synchronization registers will be cleared. The typical synchronization procedure is:

1) CPUn sets its synchronization register by the instruction \hlink{SEM}.

2) CPUn waits until some other CPU(s) write to the GRF registers corresponding to the bits set by the
\hlink{SEM} instruction. This can be done in two ways: hardware and software.

- hardware: by using the \hlink{SYN} instruction. The CPUn will stop until the synchronization mask is cleared.

- software: CPUn checks by the instruction \hlink{SYT} its synchronization register and uses some conditional
jump.

The hardware method saves power, while the software method allows to use the CPUn for something else
until the other CPU(s) are ready.

\begin{figure}[htb]
 \centering
 \includegraphics*[width=6cm]{chap_tp/grf_sync.eps}
 \caption[Synchronization registers in GRF]{Synchronization registers in GRF.}
 \label{fig:grfsync}
\end{figure}

%-----------------------------------------------------------------------------
\section{Counter/timer}
\label{tp:cnttm}

There is one common counter/timer unit for all CPUs, which is mapped to the global IO.
Each CPU has a privat counter timer, which is mapped to the local IO.

\register{CTGDINI}{0x0B80}{Global Counter/timer init data}
{Global Counter/timer init data}
{dddd dddd dddd dddd dddd dddd dddd dddd}
{0000 0000 0000 0000 0000 0000 0000 0000}
{d & 32 bit initial data\\
}

\register{CTGCTRL}{0x0B81}{Global Counter/timer control/status}
{Global Counter/timer control/status}
{---- ---- ---- ---- ---S idce essb bbbb}
{---- ---- ---- ---- ---- 1110 0011 1111}
{S & overflow status (read only), if i-bit is 0 will remain 1 after overflow\\
 i & interrupt mode: when '0' the interrupt will be activated only once after overflow/underflow (in
counter mode only), else will be activated periodically\\
 d & direction: 1/0 for up/down (in counter mode), xnor/xor (in pseudo random mode)\\
 c & 1/0 for counter/pseudo random mode\\
 e & external select, see Table \ref{tab:cntsrc}\\
 s & counter input select: 00 for external, 01 after read, 1X continuous\\
 b & length-1 (in bits) of the pseudo random shift register\\
}

Note: writing to any address of the counter will reenable the interrupt, if configuration bit i is 0.

\register{CTGDOUT}{0x0B82}{Global Counter/timer output data}
{Global Counter/timer output data}
{DDDD DDDD DDDD DDDD DDDD DDDD DDDD DDDD}
{0000 0000 0000 0000 0000 0000 0000 0000}
{D & 32 bit output data (read only)\\
}

Note: in pseudorandom mode the output will be not masked to get only the programmed number of bits.

\begin{table}[htb]
 \centering
 \scriptsize
\begin{tabular}{|c|c|c|c|c|c|}\hline
ext sel$\downarrow$ counter$\rightarrow$ & Local 0 & Local 1 & Local 2 & Local 3 & Global \\ \hline
0 & NI\_P0\_STRB & NI\_P1\_STRB & NI\_P2\_STRB & NI\_P3\_STRB & SLOW\_CLK 10MHz \\ \hline
1 & L0R & L1R  & L2R & Clear decoded & Clear decoded \\ \hline
2 & L0A & L1A  & L2A & Pretrigger decoded & Pretrigger decoded \\ \hline
3 & IRQext & IRQext  & IRQext & IRQext & RESRV decoded \\ \hline
\end{tabular}
\caption[Counter inputs]
{Counter inputs}
 \label{tab:cntsrc}
\end{table}


\register{CTPDINI}{0x200}{Privat Counter/timer init data}
{Privat Counter/timer init data}
{dddd dddd dddd dddd dddd dddd dddd dddd}
{0000 0000 0000 0000 0000 0000 0000 0000}
{d & 32 bit initial data\\
}

\register{CTPCTRL}{0x201}{Privat Counter/timer control/status}
{Privat Counter/timer control/status}
{---- ---- ---- ---- ---S idce essb bbbb}
{---- ---- ---- ---- ---- 1110 0011 1111}
{S & overflow status (read only), if i-bit is 0 will remain 1 after overflow\\
 i & interrupt mode: when '0' the interrupt will be activated only once after overflow/underflow (in
counter mode only), else will be activated periodically\\
 d & direction: 1/0 for up/down (in counter mode), xnor/xor (in pseudo random mode)\\
 c & 1/0 for counter/pseudo random mode\\
 e & external select, see Table \ref{tab:cntsrc}\\
 s & counter input select: 00 for external, 01 after read, 1X continuous\\
 b & length-1 (in bits) of the pseudo random shift register\\
}

Note: writing to any address of the counter will reenable the interrupt, if configuration bit i is 0.

\register{CTPDOUT}{0x202}{Privat Counter/timer output data}
{Privat Counter/timer output data}
{DDDD DDDD DDDD DDDD DDDD DDDD DDDD DDDD}
{0000 0000 0000 0000 0000 0000 0000 0000}
{D & 32 bit output data (read only)\\
}

Note: in pseudorandom mode the output will be NOT masked to get only the programmed number of bits.

\clearpage

%-----------------------------------------------------------------------------
\section{Instruction Set}
\label{tp:instr}

\minisec{Notations}
\begin{tabular}{p{3.2cm}p{10.8cm}}
  PRF & Privat Register File, any of the 16 32 bit registers \\
  PRF[n] or rn & the n-th PRF, where n is from 0 to 15 \\
  PRF[n]..PRF[k] & all registers from n to k \\
  GRF & Global Register File, any of the 16 32 bit registers \\
  GRF[n] or gn & the n-th GRF, where n is from 0 to 15 \\
  GRF[n]..GRF[k] & all registers from n to k \\
  FIT & Fit Register File, any of the 16 32 bit read only registers \\
  FIT[n] or fn & the n-th FIT, where n is from 0 to 15 \\
  FIT[n]..FIT[k] & all registers from n to k (for the meaning of the fit register see Chapter \ref{tpp}) \\
  CON & CONstants file, any of the 16 32 bit read only registers \\
  CON[n] or cn & the n-th CON, where n is from 0 to 15 \\
  CON[n]..CON[k] & all constants from n to k \\
  CON[0]..CON[7] & hardwired to 0, 1, 2, 3, 4, CPU-ID, -2, -1 where CPU-ID is 0 to 3 for the different CPUs, see
  Table \ref{tab:const}\\
  CON[8]..CON[11] & programmable individually for each CPU, see Table \ref{tab:constgio} \\
  CON[12]..CON[15] & programmable and common for the four CPUs, see Table \ref{tab:constgio}) \\
  IMM1 & immediate unsigned 1 bit operand \\
  IMM2 & immediate unsigned 2 bit operand \\
  IMM5 & immediate signed 5 bit operand \\
  IMM12 & immediate unsigned 12 bit operand \\
  IMM13 & immediate unsigned 13 bit operand \\
  IMM16 & immediate unsigned 16 bit operand \\
  IMM17 & immediate signed 17+12 bit operand used to extend the range of IMM12e \\
  IMM12e & extendable immediate unsigned 12 bit operand (see the examples with \hlink{CMP},
  \hlink{MOV}, \hlink{SGIO}, \hlink{IEXT}) \\
  cc\_cond & immediate unsigned 5 bit operand, used in \hlink{JMP} \\
  Label & 12 bit operand, which will be automatically calculated by the assembler \\
  PC\_OFFS & 5 bit signed operand \\
  name(n:m) & bits n to m of name \\
  MSB(name) & Most Significant Bit of name \\
  LSB(name) & Least Significant Bit of name \\
  $\oplus$ & XOR (exclusive OR) \\
  PIO & Privat Input Output bus \\
  LIO & Local Input Output bus, the same as PIO \\
  GIO & Global Input Output bus \\
\end{tabular}

\minisec{Instructions have the following format}
\begin{tabular}{p{3.2cm}p{10.8cm}}
OPC(23:17)  & opcode, where OPC(17) is write back (wb) flag \\
Destination & (xxxx xxxx xxxx xxxx xxxt tttt): \\
	    & OPC(4) selects PRF when 0 otherwise GRF \\
	    & OPC(3:0) selects the register inside PRF/GRF \\
Source 2    & (xxxx xxxx xxxx xbbbb bbbx xxxx) \\
	    & OPC(10:9) selects block \\
            & "00" = PRF \\
            & "01" = GRF \\
            & "10" = FIT \\
            & "11" = CON \\
	    & OPC(8:5) selects the register inside PRF/GRF/FIT/CON \\
Source 1    & (xxxx xxxa aaaa xxxxx xxxx xxxx) \\
	    & OPC(16) selects PRF when 0, otherwise FIT \\
	    & OPC(15:12) selects the register inside PRF/FIT \\
\end{tabular}

\minisec{Immediate data/addresse}
\begin{tabular}{p{3.2cm}p{10.8cm}}
- \hlink{SHL}, \hlink{SHA}  & OPC(16:12) is the distance (signed) \\
- \hlink{MOV}	  & OPC(16:5) is a 12 bit immediate value \\
- \hlink{JMP}, \hlink{LPIO} & OPC(16:5) is a 12 bit immediate address \\
- \hlink{LGIO}	  & OPC(15:0) is a 16 bit immediate address \\
- \hlink{LRA+}, \hlink{LRA} & OPC(16:15) is the read mode "00" 32 bit, "01" 16 bit, "11" 8 bit \\
- \hlink{SPIO}	  & OPC(11:0) is a 12 bit immediate address \\
- \hlink{SRA}	  & OPC(11:0) is a 12 bit immediate byte address, Bits(1:0) are\\
          & ignored as the memory write is always in 32 bit mode. \\
- \hlink{CMP}	  & OPC(11:0) is 12 bit immediate value \\
- \hlink{SEM}	  & OPC(15:0) is 16 bit immediate mask \\
- \hlink{INT}	  & OPC(15:0) is 16 bit immediate mask \\
- \hlink{IEXT}	  & OPC(16:0) is 17 bit immediate value, sign extended internally \\
\end{tabular}

\minisec{Autoincrement}
\begin{tabular}{p{3.2cm}p{10.8cm}}
- \hlink{SGIO+}, \hlink{LGIO+} & PRF[14] will be post incremented by 1 \\
- \hlink{SRA+}	     & PRF[15] will be post incremented by 4 (32-bit write access only) \\
- \hlink{LRA+}	     & PRF[15] will be post incremented by 1 (8-bit read access), 2 (16-bit
read access), 4 (32-bit read access) \\
\end{tabular}

\minisec{The flags}

\begin{tabular}{p{3.2cm}p{2cm}p{8.8cm}}
Zero  & Z & result in ALU = Zero\\
Negative  & N & Negative result in ALU, =MSB of result\\
TCO  & V & two's complement oVerflow\\
Carry  & C & Carry output in ALU\\
Signed  & S & Negative $\oplus$ TCO\\
Busy  & B & arbiter Busy (see \hlink{LGIO}, \hlink{SGIO})\\
Errdiv  & E & Error in divider (see \hlink{DIV}, \hlink{DIE})\\
Divbusy & D & Divider busy (see \hlink{DIV}, \hlink{DIE})\\
\end{tabular}

\minisec{The predefined constants for the conditional jumps}

\begin{tabular}{p{3.2cm}p{5cm}p{5.8cm}}
cc\_signed  & 0x14 & S flag is set\\
cc\_nsigned & 0x04 & S flag is not set \\
cc\_zero    & 0x11 & Z flag is set\\
cc\_nzero   & 0x01 & Z flag is not set\\
cc\_overfl  & 0x13 & V flag is set\\
cc\_noverfl & 0x03 & V flag is not set\\
cc\_neg     & 0x12 & N flag is set\\
cc\_nneg    & 0x02 & N flag is not set\\
cc\_carry   & 0x10 & C flag is set\\
cc\_ncarry  & 0x00 & C flag is not set\\
cc\_busy    & 0x17 & B flag is set\\
cc\_nbusy   & 0x07 & B flag is not set\\
cc\_divb    & 0x15 & D flag is set\\
cc\_ndivb   & 0x05 & D flag is not set\\
cc\_errdiv  & 0x16 & E flag is set\\
cc\_nerrdiv & 0x06 & E flag is not set\\
cc\_uncond  & 0x0F & unconditional\\
\end{tabular}

\minisec{The predefined constants for the conditional jumps suitable for use after CMP $a$, $b$ or
SUB $a$, $b$, $r$}

\begin{tabular}{p{3.2cm}p{5cm}p{5.8cm}}

cc\_eq      & 0x11 & $a =  b$\\
cc\_neq     & 0x01 & $a \neq b$\\
cc\_neg     & 0x12 & $r <  0$\\
cc\_pos0    & 0x02 & $r \geq 0$\\
cc\_lts     & 0x14 & $a <  b$ signed\\
cc\_ges     & 0x04 & $a \geq b$ signed\\
cc\_ltu     & 0x10 & $a <  b$ unsigned\\
cc\_geu     & 0x00 & $a \geq b$ unsigned\\
cc\_les      & 0x19 & $a \leq b$ signed\\
cc\_gts      & 0x09 & $a >  b$ signed\\
cc\_leu      & 0x18 & $a \leq b$ unsigned\\
cc\_gtu      & 0x08 & $a >  b$ unsigned\\

\end{tabular}

\minisec{Predefined constants for RAM read mode}
\begin{tabular}{p{3.2cm}p{10.8cm}}
rr\_byte  & 3 \\
rr\_word  & 1 \\
rr\_dword & 0 \\
\end{tabular}

\minisec{An other possibility is to use the aliases}
\begin{tabular}{p{3.2cm}p{5cm}p{5.8cm}}
LRA4 & = \hlink{LRA} 0, & 32 bit read\\
LRA2 & = \hlink{LRA} 1, & 16 bit read\\
LRA1 & = \hlink{LRA} 3, & 8 bit read\\
\end{tabular}

\clearpage
\input{chap_tp/instructions.tex}
\clearpage

%-----------------------------------------------------------------------------
\section{Assembler Environment}
\label{tp:ass}

%-----------------------------------------------------------------------------
\subsection{Installation}
\label{tp:ass:inst}

DOS-Windows version: Copy the two files {\ttfamily asm\_mimd.exe} and {\ttfamily
asm\_mimd.inc} in the same directory, add (if necessary) the directory to the {\ttfamily PATH}.

Linux version: Copy the two files {\ttfamily asm\_mimd} and {\ttfamily asm\_mimd.inc}
in the same directory (for example {\ttfamily/usr/local/bin/} or
{\ttfamily $\sim$/bin}), be sure they are in the {\ttfamily PATH}.

For both operating systems:

If you wish to have some common aliases, edit the file asm\_mimd.inc. It must
remain in the same directory with the executable. It is possible to include other files in the
source, see later.

\subsection{Usage}
\label{tp:ass:use}

{\ttfamily asm\_mimd -i source\_file[.asm] [-o<x> out\_file] [options]}

Input file:

The default extension for the source files is {\ttfamily .asm}, but if it is different and
fully specified, the assembler will read the file correctly.

Output file(s):

{\ttfamily -o<x> output\_filename - specify the output format and the filename

r - scsb (.o)}

This output format is used in the scsb program of R.Gareus, it is very similar
to the Altera MIF format.

{\ttfamily m - Altera MIF (.mif)}

This format can be used to initialize memory blocks in Altera FPGA while 
prototyping the processor core in Altera FPGA.

{\ttfamily h - Intel HEX (.hex)}

This format is an industry standard, it can be used for simulations with
ModelSim to initialize the memory direct in VHDL, not using the slow control serial
network. The address in .hex file is word (not byte!) address.

{\ttfamily d - dat (.dat)}

This format is currently used for simulation and tests. \# is used for
comment. It looks like:

{\ttfamily  command address data slave}

\begin{verbatim}
# one slow control command per line
# command_code address data [slave_pos]
# all in decimal! Data is 32 bit signed.
# command_codes: 10 for write
# for the other codes see Chapter \ref{scsn}
# Example (for single chip simulation/test) :
10 57344 8979040
10 57345 262320
# Example (for multiple chip simulation/test) :
# send to slave 5
10 57344 8979040 5
# send to all slaves (broadcast)
10 57344 8979040 127
\end{verbatim}

If for some reasons the different CPUs should get different instructions
(programs), the sources must be compiled separately and the .dat files merged
with some additional write transactions inbetween. See \ref{tp:arch:memo},
\ref{tp:ass:condcomp}, \ref{tp:ass:codem}.

{\ttfamily l - log (.log)}

The log file contains some additional information like the binary instruction
code and the compiler messages (warnings and errors). It will be created during the
first pass of the assembler, therefore the jump instructions contain only the
opcode but no destination address. The labels will be computed after the first
pass. In the MIF file you can find the complete opcode in binary.

Options (the switches are not case sensitive) :

{\ttfamily -Pm - program memory size (for .mif format only), m=256,512,1024,2048 or 4096 words (default: 4096)}

{\ttfamily -d<const> - define const, the same as \#def const= ; in the source code}

This option is useful for conditional compilation.

{\ttfamily -n[C] - no comments in the output .mif file (default: with
comments)}

{\ttfamily -T - print the table with the instruction set and quit}
\par This is very useful to get a quick reference of the supported instruction set.

{\ttfamily -V<x> - overflow in constants: n or i - ignore, w - warning(default), e - error}

This option allows to establish the responce of the assembler to overflow
in immediate values.

{\ttfamily -S<n> - slave position [n=1..127] in .dat file}

This option is only for .dat format. Normally in this format there are 3 decimal
numbers per line:

{\ttfamily command address data}

This is useful for single chip simulation or test. If there are more than one chip
in the slow control serial network chain, a fourth column is necessary to specify
the slave position in the chain (from 1 to 127, see Chapter \ref{scsn}).

A short help how to use the assembler can be get by starting the program
without parameters:

{\ttfamily asm\_mimd}


Example:

{\ttfamily asm\_mimd -i test -od testout.dat -ol test.log -dcpu0 -dNs=10}

Input file is test.asm, output file is testout.dat, logfile is test.log, the constants cpu0
and Ns with value 10 are defined.

\subsection{Syntax}

\label{tp:ass:synth}

%comma ,
%semicolon ;
%colon :

The Assembler is not case sensitive. It expects one instruction 
per line. Tabs are interpreted as spaces. 
Therefore we will speak simply of white spaces.
The leading whitespaces of the line are ignored. The symbols
semicolon (;), slash (/), minus (-), \# can be used to start a comment to the end
of the line. \# has additional functions.

{\ttfamily ;$|$/$|$-$|$\# comment to the end of the line}

\subsection{Define constants with \#def}
\label{tp:ass:defconst}

{\ttfamily \#def name=string;} The assembler will substitute {\ttfamily name} with
{\ttfamily string}.

Example:
\begin{verbatim}
;condition check constants for JMP, JMPR
#def cc_signed=0x14;
#def cc_nsigned=0x04;
#def cc_zero=0x11;
\end{verbatim}

\subsection{Conditional compilation with \#ifdef / \#ifndef \#else \#endif}

\label{tp:ass:condcomp}

\begin{verbatim}
#ifdef version1
    mov con[5], prf[5]
    cmp prf[5], 2
    jmp cc_zero, cpu2only 
#else
  #ifdef cpu2
      jmp cc_zero, cpu2only
  #else
      nop
  #endif
#endif
\end{verbatim}

The value of the constant that is used for conditional compiling will be ignored. 
So it is possible to generate specific codes for the different CPUs, instead of checking
the CPU id. In such a case it is necessary to compile the assembler program up to four times - for the
four CPUs. After that the resulting .dat files must be merged into one.
Note that the constants cpu0, cpu1, cpu2, cpu3 are not reserved for this purpose, but it is strongly 
recommended to use them.

It is not possible
to use logical expressions in \#ifdef (except for not by using \#ifndef), but the next example shows
a simple way to implement OR and AND relation.
\begin{verbatim}
#ifdef cpu2
    #def cpu2or1= ;
#endif
#ifdef cpu1
    #def cpu2or1= ;
#endif
...
; generate only if cpu1 OR cpu2 are defined
#ifdef cpu2or1
     ; some code for cpu1 and cpu2 only
     ...
#else
     ; some code for cpu0 and cpu3 only
     ...
#endif
...
; generate only if version1 AND cpu1 are defined
#ifdef version1
   #ifdef cpu1
     ...
   #endif
#endif
\end{verbatim}

\subsection{Include files with \#inc}
\label{tp:ass:inclf}
Include files in the assembler source file.
\begin{verbatim}
; suppose asm_mimd is in /usr/local/bin, then the next
; will include the file /usr/local/bin/mimd.inc
#inc <mimd.inc>

; suppose the file with the main assembler source code is in ./ASM,
; the the next will include the file ./ASM/endprog.asm
#inc "endprog.asm"

; independent on the location of the main file and the program file,
; the next will include the file absolute.asm from the current directory

#inc absolute.asm
\end{verbatim}
In the include file can be included an other file and so on.

\subsection{Set the address with ORG}
\label{tp:ass:initaddr}
{\ttfamily ORG n} is used to say to the assembler to continue the translation
at address {\ttfamily n}. An error message will be generated if the new address
is not greater than the last address used.

Example:
\begin{verbatim}
; put the beginning of the program at some address
      JMP cc_uncond, main;
      ...
ORG   0x200;
main: ...
\end{verbatim}

\subsection{Instructions}
\label{tp:ass:instr}
Each instruction starts optionally with a label followed by a colon, white space,
instruction name, whitespace, operand1, whitespace or comma, operand2, whitespace or comma, operand3
and optional comment beginning with ; or / or - or \#.

{\ttfamily [label:] instr [operand1,] [operand2,] [operand3]
[;$|$/$|$-$|$\#]}

The registers are accessed by the name (GRF, PRF, CON, FIT) and the number 
in square brackets [n], where n is from 0 to 15. An alternative way to access
the registers is using:

{\ttfamily r0, r1, ..., r15} for {\ttfamily PRF[0], PRF[1], ..., PRF[15]}\\
{\ttfamily g0, g1, ..., g15} for {\ttfamily GRF[0], GRF[1], ..., GRF[15]}\\
{\ttfamily c0, c1, ..., c15} for {\ttfamily CON[0], CON[1], ..., CON[15]}\\
{\ttfamily f0, f1, ..., f15} for {\ttfamily FIT[0], FIT[1], ..., FIT[15]}

The immediate data are in binary, decimal or hexadecimal. For example:

{\ttfamily b1000\_0111, b10000111, 0x87, 135}

represent the same number.

Example:
\begin{verbatim}
;short delay
    MOV 100, r4;
tl: SUB r4, c1, r4;
    JMP cc_nzero, tl
\end{verbatim}

\subsection{Merge specific codes for the different CPUs into one .dat file}
\label{tp:ass:codem}

As described in \ref{tp:ass:condcomp}, with conditional compilation we can compile different 
assembler codes for the different CPUs. A typical script to do this is shown below:

\begin{verbatim}
asm_mimd -i ASM/$1.asm -od tmp0 -ol tmp0.log -dcpu0 <other options>
asm_mimd -i ASM/$1.asm -od tmp1 -ol tmp1.log -dcpu1 <other options>
asm_mimd -i ASM/$1.asm -od tmp2 -ol tmp2.log -dcpu2 <other options>
asm_mimd -i ASM/$1.asm -od tmp3 -ol tmp3.log -dcpu3 <other options>
codem -i0 tmp0 -i1 tmp1 -i2 tmp2 -i3 tmp3 -o ASM/$1.dat -s127
rm tmp?
\end{verbatim}

The program {\ttfamily codem} reads up to four .dat files created by the assembler and merges them into one
.dat file, suitable for initialising the four IMEM blocks inside the TRAP chip. Keep in mind, to get compact .dat file, the 
portions of code that differ for the separated CPUs must be equal long. Add some NOPs if necessary to minimize
the initialization time. Otherwise, if the runtime speed is more important, the separate CPUs could have
completely different codes, the program {\ttfamily codem} will merge the assembler output files correctly.
The option -s127 adds slave 127 to the generated .dat file (for .dat format see \ref{tp:ass:use}). This is usefull 
when working with many chips that have the same portions of instruction code.

In order to prepare read and verify script for the IMEM, the program {\ttfamily codem} can be
started with the option {\ttfamily -r}. Be careful, this is not just replacing the scsn code for write
with the code for read! This can be done for all other configuration registers but not for IMEM, because of the
special way of accessing IMEM in the global bus (see Table \ref{tab:memio} in \ref{tp:arch:memo}).

%-----------------------------------------------------------------------------
\subsection{Assembler Code Examples}
\label{tp:ass:expl}

Please have a look at the examples in the instruction set section.
