Introduction to BSim

BSim is a simulator for the 6.004 Beta architecture. BSim provides a simple editor for typing in your program and some tools for assembling the program into binary, loading the program into the simulated Beta's memory, executing the program and examining the results.

BSim incorporates CodeMirror for editing your .uasm files. CodeMirror supports many common edit operations — please see the table at the end of this document for the mapping from keystrokes to edit operations. Whenever you click the contents of your edit buffers will be saved on the server. Use the tabs in the editor window to select a particular buffer to edit. Tabs marked with are read-only -- you can view their contents but not make any modifications.

To test your code, click on in the editor's toolbar. This will assemble the current buffer, i.e., convert it into binary and load it into the simulated Beta's memory. Any errors detected will be flagged in the editor window and described in the message area at the bottom of the window. If the assembly completes successfully, a pane showing the Beta datapath is displayed from which you can start execution of the program.

The Simulation pane has some additional toolbar buttons that are used to control the simulation. The values shown in the window reflect the values on Beta signals after the current instruction has been fetched and executed but just before the register file and memory are updated at the end of the cycle.

Pause execution.
Reset the contents of the PC and registers to 0, and memory locations to the values they had just after assembly was complete.
Start simulation and run until a HALT() instruction is executed or a breakpoint is reached. You can stop a running simulation using the pause control described above. The display will be updated every cycle.
The same as the play button described above, but only updates the display once every 25,000 cycles for maximum simulation speed.
Execute the program for a single cycle and then update the display. Very useful for following your program's operation instruction-by-instruction.
Undo the last cycle and update the display. Very useful after clicking the single cycle button more times than intended. This button can only go back a limited number of steps.
Display the animated datapath in place of the programmer's panel.
Display the programmer's panel in place of the animated datapath.

To switch between the editor and simulation panes, use the "Editor" and "Simulation" buttons at the top left of the window. "Split" will divide the screen evenly between the two. It is also possible to drag the dividers between panes to resize them individually. When both the editor and simulation panes are visible, clicking "Assemble" will not alter the layout of the window.

If .options tty is specified by the program, the small typeout window at the bottom of the simulation pane may be accessed by the running program. You can output characters to this window by executing a WRCHAR() instruction after placing the character value in R0. The tty option also allows for type-in: any character typed by the user causes an interrupt to location 12; RDCHAR() can be used to fetch the character value into R0. Clicking the mouse will cause an interrupts to location 16; CLICK() can be used to fetch the coordinates of the last click into R0. The coordinates are encoded as (x<<16)+y, or –1 if there has been no mouse click since the last call to CLICK().

If .options clock is specified by the program, an interrupt to location 8 is generated every 10,000 cycles. (Remember though that interrupts are disabled until the program enters user mode — see section 6.3 of the Beta documentation.)

Introduction to assembly language

BSim incorporates an assembler: a program that converts text files into binary memory data. The simplest assembly language program is a sequence of numerical values which are converted to binary and placed in successive byte locations in memory:

     // Comments begin with a double slash and end at a newline
     /* Multi-line comments are also available, and continue until
        reaching the termination sequence, */
      
      37  3   255     // decimal (the default radix)
      0b100101        // binary (note the 0b prefix)
      0x25            // hexadecimal (note the 0x prefix)
      'a'             // character constants

Values can also be expressions; e.g., the source file

      37+0b10–0x10    24 – 0x1  4*0b110–1   0xF7 % 0x20
generates 4 bytes of binary output, each with the value 23. Note the operators have no precedence – you have to use parentheses to avoid simple left-to-right evaluation. The available operators are

OperatorOperation
unary minus
~bit-wise complement
&bit-wise AND
|bit-wise OR
+addition
subtraction
*multiplication
/division
%modulo (result is always positive!)
>>right shift
<<left shift

We can also define symbols for use in expressions:

      x = 0x1000       // address in memory of variable X
      y = 0x10004      // another address

      // Symbolic names for registers
      R0 = 0
	   R1 = 1
	   …
	   R31 = 31

Note that symbols are case-sensitive: Foo and foo are different symbols. A special symbol named "." (period) means the address of the next byte to be filled by the assembler:

      . = 0x100        // assemble into location 0x100
      1  2  3  4
      five = .         // symbol five has the value 0x104
      5  6  7  8
      . = . + 16       // skip 16 bytes
      9 10 11 12

Labels are symbols that represent memory address. They can be set with the following special syntax:

      X:               // this is an abbreviation for X = .
For example the table on the left shows what main memory will contain after assembling the program on the right.
      ---- MAIN MEMORY ----         
        byte:  3  2  1  0
                                     . = 0x1000
        1000: 09 04 01 00            sqrs:  0 1 4 9
        1004: 31 24 19 10                   16 25 36 49
        1008: 79 64 51 40                   64 81 100 121
        100C: E1 C4 A9 90                   144 169 196 225
        1010: 00 00 00 10            slen:  LONG(. – sqrs)

Macros are parameterized abbreviations:

      // macro to generate 4 consecutive bytes
      .macro consec(n) n n+1 n+2 n+3

      // invocation of above macro
      consec(37)
The macro invocation above has the same effect as
      37 38 39 40
Note that macros evaluate their arguments and substitute the resulting value for occurrences of the corresponding formal parameter in the body of the macro. Here are some macros for breaking multi-byte data into byte-size chunks
      // assemble into bytes, little-endian format
      .macro WORD(x) x%256 (x/256)%256
      .macro LONG(x) WORD(x) WORD(x>>16)
      LONG(0xdeadbeef)
which has the same effect as
      0xef 0xbe 0xad 0xde
The body of the macro includes the remainder of the line on which the .macro directive appears. Multi-line macros can be defined by enclosing the body in "{" and "}".

beta.uasm contains symbol definitions for all the registers (R0, …, R31, BP, LP, SP, XP, r0, …, r31, bp, lp, sp, xp) and macro definitions for all the Beta instructions:

OP(Ra,Rb,Rc)
Opcodes:
Reg[Rc] ← Reg[Ra] op Reg[Rb]
ADD, SUB, MUL, DIV, AND, OR, XOR
CMPEQ, CMPLT, CMPLE, SHL, SHR, SRA
OPC(Ra,literal,Rc)
Opcodes:
Reg[Rc] ← Reg[Ra] op SEXT(literal15:0)
ADDC, SUBC, MULC, DIVC, ANDC, ORC, XORC
CMPEQC, CMPLTC, CMPLEC, SHLC, SHRC, SRAC
LD(Ra,literal,Rc)Reg[Rc] ← Mem[Reg[Ra] + SEXT(literal)]
ST(Rc,literal,Ra)Mem[Reg[Ra] + SEXT(literal)] ← Reg[Rc]
JMP(Ra,Rc)Reg[Rc] ← PC + 4; PC ← Reg[Ra]
BEQ/BF(Ra,label,Rc)Reg[Rc] ← PC + 4;
if Reg[Ra] == 0 then PC ← PC + 4 + 4*SEXT(literal)
BNE/BT(Ra,label,Rc)Reg[Rc] ← PC + 4;
if Reg[Ra] != 0 then PC ← PC + 4 + 4*SEXT(literal)
LDR(label,Rc)Reg[Rc] ← Mem[PC + 4 + 4*SEXT(literal)]

Also included are some convenience macros:

      LD(label,Rc) expands to LD(R31,label,Rc)
      ST(Ra,label) expands to ST(Ra,label,R31)
      BR(label) expands to BEQ(R31,label,R31)
      CALL(label) expands to BEQ(R31,label,LP)
      RTN() expands to JMP(LP)
      DEALLOCATE(n) expands to SUBC(SP,n*4,SP)
      MOVE(Ra,Rc) expands to ADD(Ra,R31,Rc)
      CMOVE(literal,Rc) expands to ADDC(R31,literal,Rc)
      PUSH(Ra) expands to ADDC(SP,4,SP) ST(Ra,-4,SP)
      POP(Rc) expands to LD(SP,-4,Rc)  ADDC(SP,-4,SP)

      HALT() cause the simulator to stop execution

The following is a complete example assembly language program:

  .include "/shared/bsim/beta.uasm"

      . = 0         // start assembling at location 0
      LD(input,r0)  // put argument in r0
      CALL(bitrev)  // call the procedure (= BR(bitrev,r28))
      HALT()

  // reverse the bits in r0, leave result in r1
  bitrev:
      CMOVE(32,r2)  // loop counter
      CMOVE(0,r1)   // clear output register
  loop:
      ANDC(r0,1,r3) // get low-order bit
      SHLC(r1,1,r1) // shift output word by 1
      OR(r3,r1,r1)  // OR in new low-order bit
      SHRC(r0,1,r0) // done with this input bit
      SUBC(r2,1,r2) // decrement loop counter
      BNE(r2,loop)  // repeat until done
      RTN()         // return to caller  (= JMP(r28))

  input:
      LONG(0x12345) // 32-bit input (in HEX)

The BSim assembly language processor includes a few helpful directives:

.include "buffer_name"

.align
.align expression

.ascii "chars…"

.text "chars…"

.breakpoint

.protect

.unprotect

.options …

.pcheckoff …
.tcheckoff …
.verify …

CodeMirror Editor Key Bindings

MovePC keystrokeMac keystroke
Left one characterLeftLeft
Right one characterRightRight
Up one lineUpUp
Down one lineDownDown
Beginning of lineHome, Alt-LeftHome, Cmd-Left
End of lineEnd, Alt-RightEnd, Cmd-Right
Up one pagePage upPage up
Down one pagePage downPage down
Beginning of documentCtrl-Home, Alt-UpCmd-Up
End of documentCtrl-End, Ctrl-DownCmd-End, Cmd-Down
Left one groupCtrl-LeftAlt-Left
Right one groupCtrl-RightAlt-Right
Selection and delete
Select allCtrl-ACmd-A
Delete character before cursorBackspaceBackspace
Delete character after cursorDeleteDelete
Delete group before cursorCtrl-BackspaceAlt-Backspace
Delete group after cursorCtrl-DeleteAlt-Delete, Ctrl-Alt-Backspace
Delete lineCtrl-DCmd-D
Search and replace
FindCtrl-FCmd-F
Find nextCtrl-GCmd-G
Find previousShift-Ctrl-GShift-Cmd-G
ReplaceShift-Ctrl-FCmd-Alt-F
Replace allShift-Ctrl-RShift-Cmd-Alt-F
Miscellaneous
UndoCtrl-ZCmd-Z
RedoCtrl-Y, Shift-Ctrl-ZCmd-Y, Shift-Cmd-Z
Indent moreCtrl-]Cmd-]
Indent lessCtrl-[Cmd-[
Toggle overwriteInsertInsert