![]() |
|
|
|
|
Language
IntroductionAn architecture description in ArchC is divided in two parts: the Instruction Set Architecture (AC_ISA) description and the Architecture elements (AC_ARCH) description. In the AC_ISA description the designer provides all details about the instruction set such as: instruction names, formats, sizes as well as each instruction behavior and the information required to decode it. In the AC_ARCH description the designer lists architectural resources like storage modules, pipeline structure etc.AC_ARCH DescriptionArchC uses structural information about the resources available in the architecture in order to automatically generate a simulator. The designer must provide such information in the (AC_ARCH) description, which is basically composed of storage elements and pipeline declarations.The level of detail used in this description will depend on the abstraction level that the designer wants for his/her model. For example, one may want to simulate the instruction set of the MIPS architecture, without considering its pipeline. This makes the instruction behavior description very simple and also demands few structural information. On the other hand, for cycle-accurate models, the designer must provide ArchC with more details about the processor structure, as shown in the figure below: AC_ARCH(mips){ ac_wordsize 32; ac_mem MEM:256K; ac_regbank RB:34; ac_pipe pipe = {IF, ID, EX, MEM, WB}; ac_format Fmt_IF_ID = "%npc:32"; ac_format Fmt_ID_EX = "%npc:32 %data1:32 %data2:32 %imm:32:s rs:5 %rt:5 %rd:5 %regwrite:1 %memread:1 %memwrite:1" ; ac_format Fmt_EX_MEM = "%alures:32 %wdata:32 %rdest:5 %regwrite:1 %memread:1 %memwrite:1"; ac_format Fmt_MEM_WB = "%wbdata:32 %rdest:5 %regwrite:1"; ac_reg<Fmt_IF_ID> IF_ID; ac_reg<Fmt_ID_EX> ID_EX; ac_reg<Fmt_EX_MEM> EX_MEM; ac_reg<Fmt_MEM_WB> MEM_WB; ARCH_CTOR(mips) { ac_isa("mips_isa.ac"); set_endian("big"); }; }; Figure 1: AC_ARCH Description Example AC_ISA DescriptionThe AC_ISA description gives ArchC all information it needs to automatically synthesize a decoder, along with the behavior of each instruction in the architecture. This description is divided into two files, one containing the instruction and format declarations and another containing the instruction behavior.Figure 2 shows an example of an AC_ISA description extracted from our MIPS model. It contains instructions, formats, decoding information and assembly syntax declarations, illustrating the main characteristics of an ISA description in ArchC. Every instruction must have a previously declared format associated to it. The designer declares an instruction through the keyword ac_instr and he/she can assign it a format by using C++ style templates. In the example, format Type_R is associated to instruction add. This allows the designer to access each instruction field individually when describing instruction behaviors. Assembly language symbols, like register names, can be grouped through the ac_asm_map construct. The instruction syntaxes and operand encoding are specified by the set_asm construct, which resembles the printf/scanf family of functions in the C language. Furthermore, pseudo instructions can be described based on previously created instructions through the pseudo_insn construct. In the example, we declared the MIPS register names (using the reg identifier) and used them as an operand type in the declaration of the syntax of the add instruction. We also created the MIPS pseudo instruction li (load immediate). AC_ISA(mips){ ac_format Type_R = "%op:6 %rs:5 %rt:5 %rd:5 0x00:5 %func:6"; ac_format Type_I = "%op:6 %rs:5 %rt:5 %imm:16:s"; ac_format Type_J = "%op:6 %addr:26"; ac_instr<Type_R> add, sub, instr_and, instr_or, mult, div; ac_instr<Type_R> mfhi, mflo, slt, jr; ac_instr<Type_R> addu, subu, multu, divu, sltu; ac_instr<Type_R> sll, srl; ac_instr<Type_I> lw, sw, beq, bne; ac_instr<Type_I> addi, andi, ori, lui, slti; ac_instr<Type_I> addiu, sltiu; ac_instr<Type_J> j, jal; ac_asm_map reg { "$"[0..31] = [0..31]; "$zero" = 0; "$at" = 1; "$kt"[0..1] = [26..27]; "$gp" = 28; "$sp" = 29; "$fp" = 30; "$ra" = 31; } ISA_CTOR(mips){ lw.set_asm("lw %reg, %imm(%reg)", rt, imm, rs); lw.set_decoder(op=0x23); sw.set_asm("sw %reg, %imm(%reg)", rt, imm, rs); sw.set_decoder(op=0x2B); add.set_asm("add %reg, %reg, %reg", rd, rs, rt); add.set_decoder(op=0x00, func=0x20); addu.set_asm("addu %reg, %reg, %reg", rd, rs, rt); addu.set_decoder(op=0x00, func=0x21); ... pseudo_instr("li %reg, %imm") { "lui %0, \%hi(%1)"; "ori %0, %0, %1"; } ... }; }; Figure 2: AC_ISA Description Example Figure 3 shows an example of a behavior description in ArchC. It presents part of the behavior of the MIPS instruction add. Notice that the code is divided, by means of a C++ switch statement, so that ArchC can identify which operations are executed at each pipeline stage. A similar switch statement can also be used to describe multi-cycle instructions when required. ArchC allows behavior descriptions to be expressed in several levels of abstraction. For example, at the very early stages of the design, cycle-accuracy may not be important. Normally, the first model of a new architecture does not have timing information. For this preliminary model, the behavior of a given instruction would be just a sequence of C++ statements representing the operations that this instruction would execute in the hardware. In this last case, the generated simulator would execute one instruction per cycle. void ac_behavior( add, stage ){ switch(stage) { case IF: IF_ID.npc = ac_pc + 4; break; case ID: break; case EX: EX_MEM.alu_result = ID_EX.rs + ID_EX.rt; ... break; case MEM: MEM_WB.alu_result = EX_MEM.alu_result; MEM_WB.rd = EX_MEM.rd; ... break; case WB: RB.write(MEM_WB.rd, MEM_WB.alu_result); break; default: break; } }; Figure 3: Behavior Description Example Memory HierarchyAll storage device objects in ArchC are instances of the same base class, called ac_storage. This class provides a number of simulation features, like delayed assignment support, update logs for simulation debugging, statistics for architecture exploration, support for various architecture wordsizes, etc. Considering how data is stored, these objects act like containers, i.e., the data is stored into arrays and is accessible through read and write methods.In order to allow a more detailed description, including a memory subsystem, we created a Storage Class Hierarchy, inheriting the base class ac_storage mentioned above, and specializing it to model registers, register banks, and even caches. An object of the cache simulation class, called ac_cache, can be customized by the designer, by defining the following attributes: number of words at each cache line, number of lines in the cache, set associativity, replacement policy, and writing scheme. Figure 4 shows a memory hierarchy composed of three levels: 2 caches (L1 e L2), and one memory (MEM). L1 is declared as a direct-mapped, 128 lines (blocks), 2 words/line, write-through, write-around cache. L2 is declared as a two-way set-associative, 256 lines, 1 word/line, randomly replaced, write-through, write-around cache. In ArchC, hierarchies are described by the cache's method bindsTo. This method takes as argument the cache device which is the next cache level down in the hierarchy. In Figure 5, L1 is supplied by L2, that is supplied by the lower level MEM, as shown by the two last lines of the description. Below are all possibilities available for cache declaration arguments in ArchC, following the argument order in the ac_cache declaration: 1. Associativity: "dm", "2w", "4w", ..., "fully" 2. Number of Lines (blocks) 3. Number of words at each line (block) 4. Replacement strategy (not used for direct-mapped ("dm") caches): "lru" (LEAST RECENTLY USED) "random" (RANDOM) 5. Write policy: "wt" (WRITE-THROUGH) "wb" (WRITE-BACK) 6. Write policy: "war" (WRITE-AROUND) "wal" (WRITE-ALLOCATE) Direct-mapped cache declarations take five arguments instead of six, just because the fourth argument (replacement strategy) does not make sense in this case. Finally, any of the arguments can be given in both upper or lower case. AC_ARCH(sparcv8){ ac_wordsize 32; ac_mem MEM:5M; ac_cache L1("dm", 128, 2, "wt","war"); ac_cache L2("2w", 256, 1,"random","wt","war"); ac_regbank RG:8; ac_regbank RB:256; ac_reg PSR; ac_reg Y; ARCH_CTOR(sparcv8) { ac_isa("sparcv8_isa.ac"); set_endian("big"); // Hierarchy: L1->L2->MEM L1.bindsTo( L2 ); L2.bindsTo( MEM ); }; }; Figure 4: A Three-level Memory Hierarchy In Figure 5, we illustrate the use of separate caches for instructions and data. The designer has declared a direct-mapped instruction cache (IC) and a 2-way set-associative data cache (DC). Both are connected to the memory object (MEM). This forms a two-level memory hierarchy, with the two caches placed at the same (first) level. Notice that, in this situation, the designer must indicate to ArchC the appropriate device for fetching instructions and reading/writing data. This is easily accomplished by using the keywords ac_icache and ac_dcache for cache object declarations. AC_ARCH(sparcv8){ ac_wordsize 32; ac_mem MEM:5M; ac_icache IC("dm", 2048, 1, "wt","war"); ac_dcache DC("2w", 1024, 1,"lru","wb","wal"); ac_regbank RG:8; ac_regbank RB:256; ac_reg PSR; ac_reg Y; ARCH_CTOR(sparcv8) { ac_isa("sparcv8_isa.ac"); set_endian("big"); // Hierarchy: IC->MEM // DC->MEM IC.bindsTo( MEM ); DC.bindsTo( MEM ); }; }; Figure 5: Separate Instruction and Data Caches More InformationReaders should refer to the ArchC Language Reference Manual for more detailed information on ArchC descriptions, keywords, syntax, behaviors and tools.
|