Skip to content

Commit

Permalink
isasim: testing, more functional style, cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
schoeberl committed Sep 27, 2016
1 parent 1c06418 commit b59aebd
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 104 deletions.
28 changes: 13 additions & 15 deletions doc/handbook/patmos_handbook.tex
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,8 @@ \section*{Acknowledgment}
ISA design and trade-offs.
Gernot Gebhard and Christoph Cullmann gave valuable feedback on the ISA
related to WCET analysis.
Sahar Abbaspourseyedi is working on the stack
cache and verifies the ideas and concepts presented here. We thank
Sahar Abbaspourseyedi has been working on the stack
cache to verify the ideas and concepts presented here. We thank
Rasmus Bo S{\o}rensen for fixing some documentation errors.

This work was partially funded under the
Expand Down Expand Up @@ -490,13 +490,13 @@ \section{Instruction Formats}
of the instruction format. Black fields are not used.

\begin{itemize}
\item ALUi -- Arithmetic Immediate \\[2ex]
\item AluImm -- Arithmetic Immediate (ALUi) \\[2ex]
\begin{bytefield}{32}
\bitheader{0-31} \\
\bitbox{1}{x} & \bitbox{4}{Pred} & \bitbox{2}{00} & \bitbox{3}{Func} &
\bitbox{5}{Rd} & \bitbox{5}{Rs1} & \bitbox{12}{Immediate} \\
\end{bytefield}
\item ALUl -- Long Immediate \\[2ex]
\item AluLongImm -- Long Immediate (ALUl) \\[2ex]
\begin{bytefield}{32}
\bitheader{0-31} \\
\bitbox{1}{1} & \bitbox{4}{Pred} & \bitbox{5}{11111} &
Expand All @@ -505,7 +505,7 @@ \section{Instruction Formats}
\bitheader{0-31} \\
\bitbox{32}{Long Immediate} \\
\end{bytefield}
\item ALU -- Arithmetic \\[2ex]
\item Alu -- Arithmetic (ALU) \\[2ex]
\begin{bytefield}{32}
\bitheader{0-31} \\
\bitbox{1}{x} & \bitbox{4}{Pred} & \bitbox{5}{01000} &
Expand All @@ -514,7 +514,7 @@ \section{Instruction Formats}
\end{bytefield}

\begin{bytefield}[leftcurly=.]{32}
\begin{leftwordgroup}{\parbox{8em}{ALUr -- Register}}
\begin{leftwordgroup}{\parbox{8em}{AluReg -- Register (ALUr)}}
\bitheader{0-31} \\
\bitbox{1}{x} & \bitbox{4}{Pred} & \bitbox{5}{01000} &
\bitbox{5}{Rd} & \bitbox{5}{Rs1} & \bitbox{5}{Rs2} &
Expand Down Expand Up @@ -687,35 +687,33 @@ \section{Instruction Opcodes}
\label{sec:instruction_opcodes}

This section defines the instruction set architecture, the instruction opcodes,
and the behavior of the respective instructions of Patmos. This section should
be less used for discussions and should slowly converge to a final definition
of the instruction set.
and the behavior of the respective instructions of Patmos.

\subsection{Binary Arithmetic}

Applies to the ALUr, ALUi, and ALUl formats. Operand \texttt{Op2}
Applies to the AluReg, AluImm, and AluLongImm formats. Operand \texttt{Op2}
denotes either the \texttt{Rs2}, or the \texttt{Immediate} operand, or
the \texttt{Long Immediate}. The immediate operand is zero-extended. For
shift and rotate operations, only the lower $5$ bits of the operand
shift and rotate operations, only the lower 5 bits of the operand
are considered. Table~\ref{tab:alufunc} shows the encoding of the
\texttt{func} field; for ALUi instructions, only functions in the
\texttt{func} field; for AluImm instructions, only functions in the
upper half of that table are available.

\begin{itemize}
\item ALUr -- Register \\[2ex]
\item AluReg -- Register (ALUr) \\[2ex]
\begin{bytefield}{32}
\bitheader{0-31} \\
\bitbox{1}{x} & \bitbox{4}{Pred} & \bitbox{5}{01000} &
\bitbox{5}{Rd} & \bitbox{5}{Rs1} & \bitbox{5}{Rs2} &
\bitbox{3}{000} & \bitbox{4}{Func} \\
\end{bytefield}
\item ALUi -- Arithmetic Immediate \\[2ex]
\item AluImm -- Arithmetic Immediate (ALUi) \\[2ex]
\begin{bytefield}{32}
\bitheader{0-31} \\
\bitbox{1}{x} & \bitbox{4}{Pred} & \bitbox{2}{00} & \bitbox{3}{Func} &
\bitbox{5}{Rd} & \bitbox{5}{Rs1} & \bitbox{12}{Immediate} \\
\end{bytefield}
\item ALUl -- Long Immediate\\[2ex]
\item AluLongImm -- Long Immediate (ALUl)\\[2ex]
\begin{bytefield}{32}
\bitheader{0-31} \\
\bitbox{1}{1} & \bitbox{4}{Pred} & \bitbox{5}{11111} &
Expand Down
152 changes: 80 additions & 72 deletions isasim/src/main/scala/PatSim.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,77 +42,46 @@

package patsim

import scala.io.Source
import scala.collection.mutable.Map

import Constants._
import Opcode._
import OpcodeExt._
import Function._

class PatSim(instructions: Array[Int]) {

var pc = 1 // method length at address 0
var pc = 1 // We start on second word as method length is at address 0
var reg = new Array[Int](32)
reg(0) = 0

var halt = false

val NOP = 0 // Using R0 as destination is a noop

def tick() = {
val instrA = instructions(pc)
val dualFetch = (instrA & 0x80000000) != 0
val longImmInstr = (((instrA >> 22) & 0x1f) == 0x1f)
val dualIssue = dualFetch && !longImmInstr

val instrB = if (dualFetch) {
instructions(pc + 2)
} else {
NOP
}
execute(instrA)
if (dualIssue) execute(instrB)
if (dualFetch) pc += 2 else pc += 1
}
val instrB = if (dualFetch) instructions(pc + 1) else 0

def alu(func: Int, op1: Int, op2: Int): Int = {
val longImmInstr = (((instrA >> 22) & 0x1f) == AluLongImm)

val scale = if (func == FUNC_SHADD) {
1
} else if (func == FUNC_SHADD2) {
2
val dualIssue = dualFetch && !longImmInstr

if (dualIssue) {
execute(instrA, 0)
execute(instrB, 0)
} else {
0
}
val scaledOp1 = op1 << scale

val sum = scaledOp1 + op2
var result = sum // some default
val shamt = op2 & 0x1f
// is there a more functional approach for this?
func match {
case FUNC_ADD => result = sum
case FUNC_SUB => result = op1 - op2
case FUNC_XOR => result = op1 ^ op2
case FUNC_SL => result = op1 << shamt
case FUNC_SR => result = op1 >>> shamt
case FUNC_SRA => result = op1 >> shamt
case FUNC_OR => result = op1 | op2
case FUNC_AND => result = op1 & op2
case FUNC_NOR => result = ~(op1 | op2)
case FUNC_SHADD => result = sum
case FUNC_SHADD2 => result = sum
case _ => result = sum
execute(instrA, instrB)
}
result
}

def execute(instr: Int) = {
def execute(instr: Int, longImm: Int) = {

val pred = (instr >> 27) & 0x0f
val opcode = (instr >> 22) & 0x1f
val rd = (instr >> 17) & 0x1f
val rs1 = (instr >> 12) & 0x1f
val rs2 = (instr >> 7) & 0x1f
val opc = (instr >> 4) & 0x07
val imm22 = instr & 0x3ffff
val aluImm = (opcode >> 3) == 0
val func = if (aluImm) {
opcode & 0x7
Expand All @@ -123,46 +92,85 @@ class PatSim(instructions: Array[Int]) {
val op1 = reg(rs1)
val op2 = if (aluImm) {
// always sign extend?
// Actually docu says zero extended - see if any test case caches this
(instr << 20) >> 20
} else {
reg(rs2)
}
val aluResult = alu(func, op1, op2)
val doExecute = rd != 0 // add predicates, but R0 only on ops with rd
val pcNext = pc + 1

// default, which is ok for ALU immediate as well
var result = aluResult
def alu(func: Int, op1: Int, op2: Int): Int = {

if (aluImm) {
result = aluResult
} else if (opcode < OPCODE_CFL_LOW) {
opcode match {
case OPCODE_ALU => {
opc match {
case OPC_ALUR => result = aluResult
case _ => println(opc + " not implemented (opc)")
}
}
case _ => println(opcode + " not implemented")
val scale = if (func == SHADD) {
1
} else if (func == SHADD2) {
2
} else {
0
}
val scaledOp1 = op1 << scale

val sum = scaledOp1 + op2
val shamt = op2 & 0x1f
func match {
case ADD => sum
case SUB => op1 - op2
case XOR => op1 ^ op2
case SL => op1 << shamt
case SR => op1 >>> shamt
case SRA => op1 >> shamt
case OR => op1 | op2
case AND => op1 & op2
case NOR => ~(op1 | op2)
case SHADD => sum
case SHADD2 => sum
case _ => sum
}
}

// Execute the instruction and return a tuple for the result:
// (ALU result, writeReg, writePred, next PC)
val result = if (aluImm) {
(alu(func, op1, op2), true, false, pcNext)
} else {
if (((opcode >> 1) == CFLOP_BRCF) && ((instr & 0x3ffff) == 0)) {
// 'halt' instruction
halt = true
} else {
println("Unimplemented control flow " + opcode + " " + (opcode >> 1))
opcode match {
// case AluImm => (alu(funct3, sraSub, rs1Val, imm), true, pcNext)
case Alu => opc match {
case AluReg => (alu(func, op1, op2), true, false, pcNext)
case _ => throw new Exception("OpcodeExt " + opc + " not (yet) implemented")
}
case Branch => throw new Exception("Branch")
case BranchCf => (0, false, false, imm22)
// case Branch => (0, false, if (compare(funct3, rs1Val, rs2Val)) pc + imm else pcNext)
// case Load => (load(funct3, rs1Val, imm), true, pcNext)
// case Store =>
// store(funct3, rs1Val, imm, rs2Val); (0, false, pcNext)
// case Lui => (imm, true, pcNext)
// case AuiPc => (pc + imm, true, pcNext)
// case Jal => (pc + 4, true, pc + imm)
// case JalR => (pc + 4, true, (rs1Val + imm) & 0xfffffffe)
// case Fence => (0, false, pcNext)
// case SCall => (scall(), true, pcNext)
case _ => throw new Exception("Opcode " + opcode + " not (yet) implemented")
}
}

// write result back
// -- need to distinguish between doExecute, write back, R0...
if (doExecute) {
reg(rd) = result
// distinguish between R0, register update, predicate update,
// and the special cases...
if (rd != 0 && result._2) {
reg(rd) = result._1
}
log
}

def executeLong(instr: Int, imm: Int) {
// increment program counter
pc = result._4

// Quick hack for the halt instruction
if (result._4 == 0) {
halt = true
}

log
}

def error(s: String) {
Expand All @@ -171,7 +179,7 @@ class PatSim(instructions: Array[Int]) {
}

def log() = {
print(pc*4 + " - ")
print(pc * 4 + " - ")
for (i <- 0 to 31) {
print(reg(i) + " ")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,37 +40,58 @@

package patsim

import scala.io.Source
import scala.collection.mutable.Map
/**
* Opcodes are 5 bit, Arithmetic short immediate use 3 of the 8 bits for
* for the function.
*/
object Opcode {
val AluImm = 0x00
val Alu = 0x08
val AluLongImm = 0x1f
val Branch = 0x13
val BranchCf = 0x15
}
/**
* The Opc field. Not sure if I like two opcode fields
*/
object OpcodeExt {
val AluReg = 0x00
}

/**
* Function for an ALU operation
*/
object Function {
val ADD = 0x0
val SUB = 0x1
val XOR = 0x2
val SL = 0x3
val SR = 0x4
val SRA = 0x5
val OR = 0x6
val AND = 0x7
val NOR = 0xb
val SHADD = 0xc
val SHADD2 = 0xd
}
/**
* These constants could be shared between the hardware
* definition and the simulation.
*/
object Constants {

val FUNC_ADD = 0x0
val FUNC_SUB = 0x1
val FUNC_XOR = 0x2
val FUNC_SL = 0x3
val FUNC_SR = 0x4
val FUNC_SRA = 0x5
val FUNC_OR = 0x6
val FUNC_AND = 0x7
val FUNC_NOR = 0xb
val FUNC_SHADD = 0xc
val FUNC_SHADD2 = 0xd

// only two bits for immediate
val OPCODE_ALUI = 0x0

val OPCODE_ALU = 0x08
// only two bits for immediate
// val OPCODE_ALUI = 0x0
//
// val OPCODE_ALU = 0x08
val OPCODE_SPC = 0x09
val OPCODE_LDT = 0x0a
val OPCODE_STT = 0x0b
val OPCODE_STC = 0x0c

val OPCODE_ALUL = 0x1f
// val OPCODE_ALUL = 0x1f

val OPCODE_CFL_LOW = 0x10
// opcode for control flow is 4 bits plus delayed bit
Expand Down
Loading

0 comments on commit b59aebd

Please sign in to comment.