Tuesday, February 26, 2013

Architecture simulators, SystemC and ArchC

I've been looking into existing literature and simulators for the heterogeneous simulator I'll be developing, and after discussing some of the options with my supervisor Magnus the final conclusion was to use SystemC together with ArchC for the simulation infrastructure. To give a brief overview of what they are:

  • SystemC is a set of C++ libraries and a simulation kernel, with plenty of useful functionality for creating models of complex hardware systems at different levels. Combining the object oriented paradigm with extra modelling capabilities for concurrency, timing and communication results in a flexible and powerful tool, and you get to decide the level of detail you would like for your models - anything from RTL (a hardware-synthesizable subset exists!) to expressing a whole processor instruction execution cycle with a switch statement. 
  • ArchC is an open-source architecture description language that was built to allow researchers or companies quickly prototype new computer architecture ideas. It can create SystemC simulations of the proposed architecture or create compiled versions for more speed, and it can even generate a GNU bintools suite targeting the architecture you specified!
So what's the first thing you'd like to see when someone starts talking about some new/esoteric language? You'd probably want to see examples. Here's a SystemC example from Wikipedia:

#include "systemc.h"
 
SC_MODULE(adder)          // module (class) declaration
{
  sc_in<int> a, b;        // ports
  sc_out<int> sum;
 
  void do_add()           // process
  {
    sum.write(a.read() + b.read()); //or just sum = a + b
  }
 
  SC_CTOR(adder)          // constructor
  {
    SC_METHOD(do_add);    // register do_add to kernel
    sensitive << a << b;  // sensitivity list of do_add
  }
};

ArchC syntax looks pretty similar (it's inspired by SystemC in any case) with specific language constructs to specify the instruction set architecture (ISA) and the microarchitecture. They have ArchC models for a number of different cores at the ArchC website, check it out!

So the microarchitecture description (well, it's not a complete microarchitecture description, but you can always customize the connections and the components if you want to) looks like this in ArchC:

AC_ARCH(mips1){

  ac_mem   DM:5M; // 5 megs of direct access memory
  ac_regbank RB:32; // register bank
  ac_reg npc;
  ac_reg hi, lo;

  ac_wordsize 32; // 32-bit words

  ARCH_CTOR(mips1) {

    ac_isa("mips1_isa.ac"); // set ISA
    set_endian("big"); // big endian

  };
};

And here is an excerpt from the ISA description and a instruction behaviour description:

AC_ISA(mips1){

  // declare the format of a group of instructions for decoding
  // this can be thought of as parameter type/count declaration
  ac_format Type_R  = "%op:6 %rs:5 %rt:5 %rd:5 %shamt:5 %func:6";
  
  // ... insert more instruction formats here
  
  // which instructions belong to which format?
  ac_instr add, addu, sub, subu, slt, sltu;
  
  // ... insert more instruction-format matchings here
  
  // assembly equivalent of instructions, for bintools generation
addi.set_asm("addi %reg, %reg, %exp", rt, rs, imm);
addi.set_asm("add %reg, %reg, %exp", rt, rs, imm);
addi.set_decoder(op=0x08);
// ...
};
...

// Instruction addi behavior method.
void ac_behavior( addi )
{
  dbg_printf("addi r%d, r%d, %d\n", rt, rs, imm & 0xFFFF);
  RB[rt] = RB[rs] + imm;
  dbg_printf("Result = %#x\n", RB[rt]);
  //Test overflow
  if ( ((RB[rs] & 0x80000000) == (imm & 0x80000000)) &&
       ((imm & 0x80000000) != (RB[rt] & 0x80000000)) ) {
    fprintf(stderr, "EXCEPTION(addi): integer overflow.\n"); exit(EXIT_FAILURE);
  }
};

No comments:

Post a Comment