diff --git a/.jvmopts b/.jvmopts new file mode 100644 index 0000000..03918b6 --- /dev/null +++ b/.jvmopts @@ -0,0 +1,4 @@ +-Xms512M +-Xmx4096M +-Xss32M +-XX:MaxMetaspaceSize=1024M \ No newline at end of file diff --git a/Images/FiveStage.png b/Images/FiveStage.png new file mode 100644 index 0000000..cc6b5b0 Binary files /dev/null and b/Images/FiveStage.png differ diff --git a/Images/IDstage.png b/Images/IDstage.png new file mode 100644 index 0000000..dd0aa60 Binary files /dev/null and b/Images/IDstage.png differ diff --git a/Images/IFID.png b/Images/IFID.png new file mode 100644 index 0000000..b9fdb57 Binary files /dev/null and b/Images/IFID.png differ diff --git a/Images/MEMstage.png b/Images/MEMstage.png new file mode 100644 index 0000000..8abb443 Binary files /dev/null and b/Images/MEMstage.png differ diff --git a/exercise.org b/exercise.org index e7155b5..a5459e3 100644 --- a/exercise.org +++ b/exercise.org @@ -1,4 +1,4 @@ -* Exercise 1 +* Exercise description The task in this exercise is to implement a 5-stage pipelined processor for the [[./instructions.org][RISCV32I instruction set]]. @@ -6,14 +6,27 @@ at a time, whereas in exercise 2 your design will handle multiple instructions at a time. This is done by inserting 4 NOP instructions inbetween each source instruction, - enabling us to use the same tests for both exercise 1 and 2. + enabling us to use the same tests and harness for both exercise 1 and 2. + + Once you are done with exercise 1, you can up the difficulty by setting nopPad + to false and start reading the [[exercise2.org][ex2 guide]]. - In the project skeleton files ([[./src/main/scala/][Found here]]) you can see that a lot of code has - already been provided. + already been provided, which can make it difficult to get started. + Hopefully this document can help clear up at least some of the confusion. + First an overview of what you are designing is presented, followed by a walk-through + for getting the most basic instructions to work. + + In order to orient yourself you first need a map, thus a high level overview of the + processor you're going to design is showed underneath: + Keep in mind that this is just a high level sketch, omitting many details as well + entire features (for instance branch logic) + + #+CAPTION: A very high level processor schematic. Registers, Instruction and data memory are already implemented. + [[./Images/FiveStage.png]] - Before going further it is useful to get an overview of what is provided out - of the box. + Now that you have an idea of what you're building it is time to take inventory of + the files included in the skeleton, and what, if anything should be added. + [[./src/main/scala/Tile.scala]] This is the top level module for the system as a whole. This is where the test @@ -26,7 +39,11 @@ should be declared and wired together. Some of these modules have already been declared in order to wire up the debugging logic for your test harness. + This file corresponds to the high-level overview in its entirety. *This module is intended to be further fleshed out by you.* + As you work with this module, try keeping logic to a minimum to help readability. + If you end up with a lot of signal select logic, consider moving that to a separate + module. + [[./src/main/scala/IF.scala]] This is the instruction fetch stage. @@ -94,10 +111,11 @@ of these settings can be quite useful to alter. The main attraction is the test options. By altering the verbosity settings you may change what is output. - The settings are + The settings are: + printIfSuccessful - Enables logging on tests that succeed + Enables logging on tests that succeed. + You typically want this turned off, at least for the full test runner. + printErrors Enables logging of errors. You obviously want this one on, at least on the single @@ -147,6 +165,12 @@ In your sketch you will eventually add a box for registers, IMEM and DMEM, which should make it clear how the already finished modules fit into the grander design, making the skeleton-code less mysterious. + + To give you an idea of how a drill down looks like, here is my sketch of the ID stage: + #+CAPTION: Instruction decode stage, showing the various signals. + [[./Images/IDstage.png]] + + I would generally advice to do these on paper, but don't half-ass them. ** Adding numbers @@ -174,11 +198,11 @@ **** Step ¾: In your console, type ~testOnly FiveStage.SingleTest~ to run only the tests that you - have defined in the [[./src/test/scala/Manifest.scala][test manifest]] (currently set to ~"forward2.s"~). + have defined in the [[./src/test/scala/Manifest.scala][test manifest]] (currently set to ~forward2.s~). As you will first implement addition you should change this to the [[./src/test/resources/tests/basic/immediate/addi.s][add immediate test]]. - Luckily you do not have to deal with file paths, simply changing ~"forward2.s"~ to - ~"addi.s"~ suffices. + Luckily you do not have to deal with file paths, simply changing ~forward2.s~ to + ~addi.s~ suffices. Ensure that the addi test is run by repeating the ~testOnly FiveStage.SingleTest~ command. @@ -188,7 +212,7 @@ In [[./src/test/main/IF.scala]] you can see that the IMEM module is already set to fetch the current program counter address (line 41), however since the current PC is stuck at 0 it will fetch the same instruction over and over. Rectify this by commenting in - ~// PC := PC + 4.U~ at line 43. + ~// PC := PC + 4.U~ at line 48. You can now verify that your design fetches new instructions each cycle by running the test as in the previous step. @@ -207,10 +231,10 @@ Next you need to ensure that the registers and decoder gets the relevant data from the instruction. - This is made more convenient by the fact that `Instruction` is a class, allowing you + This is made more convenient by the fact that ~Instruction~ is a class, allowing you to access methods defined on it. - Keep in mind that it is only a class at compile and synthesis time, it will be - indistinguishable from a regular ~UIint(32.W)~ in your finished circuit. + Keep in mind that it is only a class during compile and build time, it will be + indistinguishable from a regular ~UInt(32.W)~ in your finished circuit. The methods can be accessed like this: #+BEGIN_SRC scala // Drive funct6 of myModule with the 26th to 31st bit of instruction @@ -221,9 +245,27 @@ Your IF should now have an instruction as an OUTPUT, and your ID as an INPUT, however they are not connected. This must be done in the CPU class where both the ID and IF are instantiated. - + In the overview sketch you probably noticed the barriers between IF and ID. + In accordance with the overview, it is incorrect to directly connect the two modules, + instead you must connect them using a *barrier*. + A barrier is responsible for keeping a value inbetween cycles, facilitating pipelining. + There is however one complicating matter: It takes a cycle to get the instruction from the + instruction memory, thus we don't want to delay it in the barrier! + + In order to make code readable I suggest adding a new file for your barriers, containing + four different modules for the barriers your design will need. + + Start with implementing your IF barrier module, which should contain the following: + + An input and output for PC where the output is delayed by a single cycle. + + An input and output for instruction where the output is wired directly to the input with + no delay. + + The sketch for your barrier looks like this + #+CAPTION: The barrier between IF and ID. Note the passthrough for the instruction + [[./Images/IFID.png]] + **** Step 4½: - You should now verify that the correct control signals are produced. Using printf, ensure + You can now verify that the correct control signals are produced. Using printf, ensure that: + The program counter is increasing in increments of 4 + The instruction in ID is as expected @@ -231,7 +273,8 @@ + The correct operands are fetched from the registers Keep in mind that printf might not always be cycle accurate, the point is to ensure that - your processor design at least does something! + your processor design at least does something! In general it is better to use debug signals + and println, but for quick and dirty debugging printf is passable. *** Step 5: You will now have to create the EX stage. Use the structure of the IF and ID modules to @@ -247,12 +290,24 @@ ... ) - io.aluResult := MuxLookup(0.U(32.W), io.aluOp, ALUopMap) + // MuxLookup API: https://github.com/freechipsproject/chisel3/wiki/Muxes-and-Input-Selection#muxlookup + io.aluResult := MuxLookup(io.aluOp, 0.U(32.W), ALUopMap) #+END_SRC + + As with the ID stage, you will need a barrier between ID and EX stage. + In this case, as the overview sketch indicates, all values should be delayed one cycle. + + When you have finished the barrier, instantiate it and wire ID and EX together with the barrier in the + same fashion as IF and ID. + You don't need to add every single signal for your barrier, rather you should add them as they + become needed. *** Step 6: Your MEM stage does very little when an ADDI instruction is executed, so implementing it should - be easy. All you have to do is forward signals + be easy. All you have to do is forward signals. + + From the overview sketch you can see that the same trick used in the IF/ID barrier is utilized + here, bypassing the data memory read value since it is already delayed by a cycle. *** Step 7: You now need to actually write the result back to your register bank. diff --git a/exercise2.org b/exercise2.org new file mode 100644 index 0000000..f62c7fb --- /dev/null +++ b/exercise2.org @@ -0,0 +1,109 @@ +* Exercise 2 + Safety wheels are now officially off. + To verify this, set nopPadded to false in Manifest.scala and observe as all hell + breaks loose. + + Let's break down what's going wrong and what we can do about it. + +** RAW Hazards + Consider the following program: + #+begin_src asm + main: + add x1, x1, x2 + add x1, x1, x1 + add x1, x1, x2 + #+end_src + + In your implementation this will give you wrong results since the results + of the first add operation will not be available in the registers before + x1 is fetched for the second and third operation. + + Your first task should therefore be to implement a forwarding unit + + The forwarding unit is located in the EX stage and is responsible for selecting + the ALU input from three possible sources. + These sources are: + + The value received from the register bank + + The ALU result currently in MEM + + The writeback result + + The forwarder prioritizes as follows: + + If the input register address is not the destination in either MEM or WB, select the + register. + + If the input register address is the destination register in WB, but not in MEM, select + the writeback signal. + + If the input register address is the destination register for the operation currently + in MEM, select that operation. + + There is a special case you need take into account, namely load operations. + Considering the following program: + #+begin_src asm + main: + lw x1, 0(x2) + add x1, x1, x1 + add x1, x1, x1 + #+end_src + + When the second operation (~add x1, x1, x1~) is in EX, the third clause in the forwarder + is triggered, however the result is not yet ready since fetching memory costs a cycle. + In order to fix this the forwarder must issue a signal that freezes the pipeline. + This is done by issuing a signal to the barrier registers, telling them to _not_ update + their contents, essentially repeating the last instruction. + + There are many subtleties to consider here. + For instance: What should happen to the instruction currently + in MEM? If it too is repeated the hazard detector will trigger next cycle, effectively + deadlocking your processor. + What about when the write address and read address are similar in the ID stage? + + Designing a forwarder can take very long, or it can be done very quickly, all depending + on how *methodical* you are. My advice is to design the algorithm first, then when you're + satisfied implement it on hardware. + + +** Control hazards + + Consider the following code + + #+begin_src asm + main: + beq zero, zero, target + add x1, x1, x1 + add x1, x1, x1 + j main + target: + sub x1, x2, x2 + sub x2, x2, x2 + #+end_src + + Depending on your design the two add instructions will be fetched before the beq jump happens. + Whenever a branch happens it is necessary to flush the spurious instructions that were fetched + before the branch was noticed. + However, simply waiting until the branch has been decided is not acceptable since that guarantees + lost cycles. + In your first iteration, simply assume branches will not be taken, and if they are taken issue + a warning to the barriers that hold spurious instructions telling them to render them impotent + by setting the control signals to do nothing. + +* Putting the pedal to the metal + Once you have a design that RAW and control hazards you're ready to up the ante and add some + improvements to your design. + Some suggestions: + +** Branch predictor + Instead of assuming branch not taken, use a branch predictor. There are many different schemes, + but I advice you to stick to a simple one, such as 1-bit or 2-bit. + +** Fast branch handling + Certaing branches like BEQ and BNE can be calculated very quickly, wheras size comparison branches + (BGE, BLE and friends) take longer. It is therefore feasible to do these checks in the ID stage. + +** Adding a data cache + Unless you have already done the two suggested improvements, do not attempt to create a cache. + The first thing you need to do is to add a latency for memory fetching, if not you will have + nothing to improve upon. + + If you still insist, start with the BTreeManyO3.s program and analyze the memory access pattern. + What sort of eviction policy and cache size would you choose for this pattern? + You should try writing additional benchmarking programs, it is important to have something measurable, + and the current programs are not made to test cache performance!! diff --git a/instructions.org b/instructions.org index e323c7c..c4c9ea0 100644 --- a/instructions.org +++ b/instructions.org @@ -2,6 +2,8 @@ 4.2. Register-Register Arithmetic Instructions -------------------------------------------------------------------------- +These do not render well on github, try using your text editor. + * ADD - Summary : Addition with 3 GPRs, no overflow exception diff --git a/src/main/scala/IF.scala b/src/main/scala/IF.scala index 1ed12a7..22ede75 100644 --- a/src/main/scala/IF.scala +++ b/src/main/scala/IF.scala @@ -8,13 +8,18 @@ class InstructionFetch extends MultiIOModule { val testHarness = IO( new Bundle { val IMEMsetup = Input(new IMEMsetupSignals) - val PC = Output(UInt()) + val PC = Output(UInt()) } ) /** - * TODO: Add signals for handling events such as jumps + * TODO: Add input signals for handling events such as jumps + + * TODO: Add output signal for the instruction. + * The instruction is of type Bundle, which means that you must + * use the same syntax used in the testHarness for IMEM setup signals + * further up. */ val io = IO( new Bundle { @@ -35,7 +40,7 @@ class InstructionFetch extends MultiIOModule { /** * TODO: Your code here. - * + * * You should expand on or rewrite the code below. */ IMEM.io.instructionAddress := PC @@ -47,11 +52,10 @@ class InstructionFetch extends MultiIOModule { /** - * Setup. You should not change this code + * Setup. You should not change this code. */ when(testHarness.IMEMsetup.setup) { PC := 0.U - // TODO: You must set the instruction to Instruction.NOP here. - // throw new Exception("Just making sure you're seeing the line above") + io.instruction := Instruction.NOP } } diff --git a/src/main/scala/ToplevelSignals.scala b/src/main/scala/ToplevelSignals.scala index 80a630c..fe31613 100644 --- a/src/main/scala/ToplevelSignals.scala +++ b/src/main/scala/ToplevelSignals.scala @@ -22,14 +22,17 @@ class Instruction extends Bundle(){ def immediateJType = Cat(instruction(31), instruction(19, 12), instruction(20), instruction(30, 25), instruction(24, 21), 0.U(1.W)).asSInt def immediateZType = instruction(19, 15).zext + def bubble(): Instruction = { + val bubbled = Wire(new Instruction) + bubbled.instruction := instruction + bubbled.instruction(6, 0) := BitPat.bitPatToUInt(BitPat("b0010011")) + bubbled + } } object Instruction { - def bubble(i: Instruction) = - i.opcode := BitPat.bitPatToUInt(BitPat("b0010011")) - - def default: Instruction = { + def NOP: Instruction = { val w = Wire(new Instruction) - w.instruction := 0.U + w.instruction := BitPat.bitPatToUInt(BitPat("b00000000000000000000000000010011")) w } } diff --git a/src/test/resources/tests/basic/forward1.s b/src/test/resources/tests/basic/forward1.s index 205a781..b6d7d97 100644 --- a/src/test/resources/tests/basic/forward1.s +++ b/src/test/resources/tests/basic/forward1.s @@ -1,204 +1,204 @@ main: - ori gp, gp, 0xFFFFFE09 - and gp, gp, ra - xor ra, ra, sp - sra ra, sp, sp + sltiu gp, ra, 0x01AE + srli sp, sp, 0x0005 + addi ra, sp, 0x0177 + srai sp, ra, 0x0003 + sub sp, ra, sp + slli sp, ra, 0x000B + add sp, gp, ra + slli gp, sp, 0x0006 + ori sp, ra, 0xFFFFFF64 + and gp, gp, gp + andi gp, gp, 0x0084 + xori ra, ra, 0xFFFFFEB4 or sp, ra, ra - xori ra, sp, 0x003D - srli sp, sp, 0xFFFFFFF2 - addi ra, sp, 0x0012 - add ra, gp, sp - ori gp, ra, 0xFFFFFFB8 - sll ra, ra, ra - sll sp, gp, ra - slt ra, gp, ra - srai gp, gp, 0xFFFFFFFB - slli ra, ra, 0x0007 - sub sp, gp, sp - andi ra, gp, 0x002D - sub gp, gp, sp - srai ra, gp, 0x0005 - or sp, ra, sp - xori ra, gp, 0xFFFFFF54 - sll ra, sp, ra - sub gp, gp, sp - add ra, sp, sp - sll ra, gp, ra - add gp, sp, sp - ori gp, sp, 0xFFFFFE68 - srli sp, gp, 0xFFFFFFF1 - sltui ra, ra, 0xFFFFFE5D - srli ra, gp, 0x0006 - srai sp, sp, 0x0005 - andi sp, sp, 0x0129 - and sp, sp, sp - slli gp, ra, 0x0001 - or gp, gp, gp - or sp, gp, gp - slli gp, gp, 0x0006 - srl sp, ra, gp - sltui gp, ra, 0xFFFFFEC3 - add sp, gp, sp - xori ra, ra, 0xFFFFFFA2 - or gp, gp, sp - and sp, gp, gp - srai gp, sp, 0x0008 - add sp, sp, ra - slti sp, ra, 0xFFFFFFF7 - srli gp, ra, 0xFFFFFFFD - sll gp, ra, gp - sltu sp, sp, gp - srli gp, ra, 0x0002 - ori gp, sp, 0xFFFFFF28 - srl ra, gp, ra - slti gp, ra, 0x0054 - or gp, ra, ra - ori sp, gp, 0x01D9 + addi sp, ra, 0x0078 + sltiu sp, sp, 0xFFFFFF1E + srli gp, sp, 0x0000 + slti sp, ra, 0xFFFFFEF7 + srai ra, ra, 0x0001 + or sp, ra, gp + xor sp, sp, ra + sub sp, ra, sp + sub ra, gp, ra + sltiu gp, sp, 0xFFFFFE85 + addi sp, gp, 0x017C + sltiu ra, gp, 0xFFFFFF64 + xori sp, gp, 0x00A1 + xor ra, sp, gp + ori gp, ra, 0x00B6 + add ra, ra, sp + sltiu gp, ra, 0xFFFFFFEC + sltu gp, sp, ra + sll sp, ra, gp + add gp, ra, ra + or gp, ra, gp + xor sp, ra, sp + addi sp, gp, 0xFFFFFF4C + xor ra, sp, gp + xori ra, sp, 0xFFFFFF72 + xori gp, sp, 0xFFFFFE95 + or ra, ra, ra + slti ra, gp, 0xFFFFFE75 + slli sp, sp, 0x0004 + sltiu ra, ra, 0xFFFFFE25 + add sp, ra, gp + sltiu gp, gp, 0xFFFFFFDB + addi sp, sp, 0x003D + sll ra, ra, sp + ori ra, ra, 0x012C + add gp, ra, gp + xori sp, sp, 0x0157 + slti gp, sp, 0xFFFFFF2A and sp, ra, ra - addi sp, gp, 0x0054 - slli gp, ra, 0xFFFFFFF2 - ori sp, sp, 0x0093 - add gp, gp, gp - and gp, gp, gp - sltui gp, ra, 0x00DE - slli sp, gp, 0x000D - slli sp, ra, 0xFFFFFFF5 - sltui sp, ra, 0xFFFFFF0E - and ra, gp, ra - add gp, sp, sp - slti ra, sp, 0x008C - srli ra, sp, 0x0000 - addi sp, sp, 0x0168 - slli ra, ra, 0xFFFFFFF3 - addi ra, gp, 0x012A - or sp, gp, ra - add ra, sp, gp - and gp, ra, ra - slli ra, gp, 0xFFFFFFF6 - or sp, gp, sp - or gp, ra, ra - ori gp, ra, 0x00EB - or sp, gp, ra - ori gp, sp, 0x01DA - andi ra, ra, 0xFFFFFFE9 - addi gp, sp, 0x00C9 - sltui ra, ra, 0xFFFFFF13 - sltui ra, ra, 0xFFFFFF3A - sltui sp, gp, 0xFFFFFE5A - ori sp, sp, 0xFFFFFFFE - and gp, sp, gp - sltui sp, ra, 0x0034 - srl gp, gp, ra - sll gp, sp, ra - ori ra, gp, 0xFFFFFEB6 - sll ra, sp, ra - sra ra, gp, sp - sub ra, sp, gp - xor gp, gp, sp - sub ra, ra, sp - srl gp, gp, sp - andi ra, ra, 0xFFFFFFCB - ori ra, ra, 0xFFFFFE1B - andi ra, ra, 0xFFFFFEC8 - sltui sp, gp, 0x0108 + add gp, ra, ra + sltiu ra, gp, 0xFFFFFE56 + sra gp, gp, ra + xori sp, gp, 0xFFFFFF0D sub sp, gp, ra - slti ra, sp, 0x015D - slli sp, sp, 0x0004 - xor gp, sp, ra - srl ra, gp, ra - sltui ra, ra, 0xFFFFFF3C - add sp, sp, sp - add gp, gp, ra - andi sp, sp, 0xFFFFFF3A - srli ra, sp, 0x0004 - ori sp, gp, 0xFFFFFEAB - ori sp, ra, 0xFFFFFE95 - slli sp, sp, 0xFFFFFFF2 - xori gp, sp, 0x0040 - slti gp, sp, 0xFFFFFED1 - or sp, sp, sp - sltui sp, gp, 0x01B4 - addi ra, gp, 0x002D - and sp, gp, gp - or ra, ra, ra - or ra, gp, ra - or ra, gp, ra - sra ra, ra, gp - sra gp, ra, sp - sub ra, sp, ra + slti ra, ra, 0x0154 + slli ra, ra, 0x000A + ori ra, gp, 0xFFFFFEC2 + ori ra, sp, 0x0075 + addi gp, sp, 0x0079 + xor gp, ra, sp + srli ra, sp, 0x0008 srai ra, ra, 0x000F - sltu sp, sp, ra - slli ra, gp, 0xFFFFFFF5 - slti gp, gp, 0x00E0 - addi gp, ra, 0xFFFFFF72 - srl ra, ra, gp - sltui gp, sp, 0xFFFFFEAA - xor sp, ra, gp - and gp, sp, ra - srli gp, gp, 0x0003 - xori ra, ra, 0x01BD - sub ra, gp, sp + slli gp, gp, 0x0006 + sra sp, gp, gp + add sp, sp, sp + srai ra, sp, 0x0001 + slli gp, ra, 0x0010 + andi ra, ra, 0xFFFFFFA8 + add sp, ra, sp + srai ra, gp, 0x000E + srai ra, sp, 0x0005 + addi ra, gp, 0xFFFFFF83 + xor gp, sp, ra + srai sp, gp, 0x0004 + srli ra, ra, 0x0007 sll gp, ra, gp - xori ra, sp, 0x0065 - or ra, sp, ra - slt sp, gp, ra - addi ra, sp, 0xFFFFFE34 - slli gp, sp, 0x0007 - sll ra, sp, gp - sltui gp, gp, 0xFFFFFE62 - slti sp, sp, 0x0019 - xori ra, gp, 0x0092 - sltui gp, sp, 0xFFFFFF29 - srl sp, ra, gp - xori sp, gp, 0xFFFFFF4C - add sp, ra, gp - add sp, gp, ra + xori gp, gp, 0x0163 + add ra, gp, gp + srli gp, gp, 0x000B + add sp, ra, ra + sltu ra, ra, sp + sll sp, ra, ra + ori sp, sp, 0xFFFFFF6B + slli gp, gp, 0x0006 + xori sp, ra, 0x00A7 + add sp, ra, ra + add ra, gp, gp + addi gp, gp, 0xFFFFFFE9 + sra sp, ra, gp + add gp, ra, ra + ori gp, gp, 0x0002 + addi gp, gp, 0x002F + sll sp, sp, ra + srli sp, ra, 0x000E + ori gp, sp, 0x00EB + sra gp, ra, sp sra sp, sp, gp - slli sp, ra, 0x0008 - srl sp, sp, sp + and gp, ra, ra + sra ra, ra, gp add sp, gp, ra - andi sp, sp, 0x0039 - sll ra, gp, sp - andi gp, ra, 0xFFFFFECC - sll sp, sp, sp - sub sp, sp, ra - srai ra, sp, 0x0008 - xor gp, ra, sp - add sp, sp, sp - sub gp, ra, gp - xori gp, sp, 0x01EE - and ra, ra, ra - ori gp, ra, 0xFFFFFE96 - slli ra, gp, 0x0002 - srli gp, ra, 0x000D - add ra, sp, sp - andi sp, gp, 0xFFFFFEC0 - andi sp, gp, 0xFFFFFE7A - xori ra, sp, 0x0169 - xori gp, sp, 0xFFFFFE02 - andi ra, ra, 0xFFFFFFD1 - xor ra, sp, gp - xori gp, gp, 0x00AB - srl ra, ra, gp - and ra, ra, sp - xori gp, sp, 0x005D - srai sp, sp, 0x000A - addi ra, sp, 0xFFFFFE19 + srl gp, sp, gp + add ra, ra, sp + srai gp, ra, 0x000E + sltu gp, gp, sp + srli sp, ra, 0x0004 + ori gp, sp, 0xFFFFFE6E + and gp, ra, ra + ori gp, ra, 0xFFFFFFAF + srl ra, ra, ra or sp, ra, ra - addi ra, gp, 0x0084 - ori sp, sp, 0xFFFFFF3D - xor gp, ra, gp - sra ra, ra, gp - xori ra, sp, 0x0040 - srai gp, gp, 0x0002 - xori ra, ra, 0xFFFFFE9A - sra ra, sp, sp - ori gp, sp, 0xFFFFFFB8 - sll sp, ra, ra - sll sp, ra, gp - sll gp, sp, sp - sra gp, ra, ra - srli gp, gp, 0x0001 + ori gp, sp, 0x0018 + and gp, gp, gp + sll gp, sp, gp + srli gp, sp, 0x0006 + add gp, ra, ra + add gp, ra, sp + sra sp, ra, ra + ori sp, ra, 0x0022 + and gp, gp, gp + add ra, sp, ra + sll sp, gp, gp + ori gp, sp, 0x008E + add sp, ra, sp + and sp, gp, gp + addi ra, sp, 0x0145 + and sp, gp, gp + sll gp, ra, sp + addi sp, sp, 0xFFFFFFAF + xori sp, ra, 0xFFFFFE2C + srl gp, ra, gp + sub ra, sp, gp + add sp, ra, ra + slli sp, sp, 0x0006 + sltu gp, sp, ra + sub gp, ra, sp + xori ra, ra, 0xFFFFFF9A + addi sp, sp, 0xFFFFFE12 + slli ra, ra, 0x0003 + slli gp, ra, 0x0004 + add gp, gp, gp + xori ra, ra, 0xFFFFFED7 + andi gp, gp, 0xFFFFFE05 + and gp, gp, sp + addi gp, gp, 0xFFFFFEE5 + slli ra, gp, 0x000A + sll sp, gp, gp + and ra, gp, sp + ori ra, gp, 0xFFFFFE22 + srl sp, sp, gp + srli ra, sp, 0x0005 + slli ra, ra, 0x0005 + srai ra, ra, 0x0007 + srli ra, gp, 0x000F + andi gp, gp, 0xFFFFFF96 + sra sp, gp, gp + srai gp, gp, 0x000F + sub sp, sp, gp + sltiu ra, ra, 0xFFFFFF41 + and sp, sp, sp + xor gp, sp, ra + srai gp, sp, 0x000A + xori gp, gp, 0x00D3 + or gp, sp, sp + sltu gp, ra, gp + slli ra, gp, 0x0002 + or sp, gp, ra + addi ra, ra, 0x002B + addi gp, ra, 0x0035 + slli sp, gp, 0x0008 + addi gp, sp, 0x015E + xor ra, gp, sp + or ra, gp, ra + sll ra, gp, ra + sll gp, gp, ra + srli gp, ra, 0x000C + slt sp, ra, sp + sltiu sp, sp, 0xFFFFFE1C + ori sp, ra, 0xFFFFFE83 + andi sp, sp, 0xFFFFFEFC + addi ra, ra, 0xFFFFFF85 + ori gp, ra, 0x0084 + sll gp, gp, ra + xori gp, sp, 0xFFFFFF6D + sll gp, sp, gp + sra ra, sp, ra + xor ra, gp, sp + srl ra, ra, sp + srl ra, ra, sp + andi gp, ra, 0xFFFFFE7B + srai ra, sp, 0x000F + sub sp, sp, ra + or sp, gp, gp + slt ra, ra, gp + or gp, gp, sp + srli ra, sp, 0x000B + andi ra, gp, 0xFFFFFFD4 + slli ra, gp, 0x0009 done #regset x1, 123 #regset x2, -40 diff --git a/src/test/resources/tests/basic/forward2.s b/src/test/resources/tests/basic/forward2.s index 9b5e973..b49b85b 100644 --- a/src/test/resources/tests/basic/forward2.s +++ b/src/test/resources/tests/basic/forward2.s @@ -1,205 +1,205 @@ main: - sltui gp, ra, 0x01AE - srli sp, sp, 0xFFFFFFFB - addi ra, sp, 0x0177 - sub sp, ra, sp - slli sp, ra, 0x000B - add sp, gp, ra - slli gp, sp, 0x0006 - ori sp, ra, 0xFFFFFF64 - and gp, gp, gp - andi gp, gp, 0x0084 - xori ra, ra, 0xFFFFFEB4 - or sp, ra, ra - addi sp, ra, 0x0078 - srli gp, sp, 0x0000 - srl sp, gp, sp - andi ra, gp, 0xFFFFFFF4 - srai ra, ra, 0xFFFFFFFF - sltu gp, sp, gp - or sp, ra, gp - sub ra, gp, ra - addi sp, gp, 0x017C - sltui ra, gp, 0xFFFFFF64 - xori sp, gp, 0x00A1 - xor ra, sp, gp - ori gp, ra, 0x00B6 - add ra, ra, sp - sltui gp, ra, 0xFFFFFFEC - sltu gp, sp, ra - sll sp, ra, gp - add gp, ra, ra - or gp, ra, gp - xor sp, ra, sp - addi sp, gp, 0xFFFFFF4C - xor ra, sp, gp - xori ra, sp, 0xFFFFFF72 - xori gp, sp, 0xFFFFFE95 - or ra, ra, ra - slti ra, gp, 0xFFFFFE75 - slli sp, sp, 0xFFFFFFFC - sltui ra, ra, 0xFFFFFE25 - add sp, ra, gp - sltui gp, gp, 0xFFFFFFDB - addi sp, sp, 0x003D - sll ra, ra, sp - ori ra, ra, 0x012C - add gp, ra, gp - xori sp, sp, 0x0157 - slti gp, sp, 0xFFFFFF2A - and sp, ra, ra - add gp, ra, ra - sltui ra, gp, 0xFFFFFE56 - sra gp, gp, ra - xori sp, gp, 0xFFFFFF0D - sub sp, gp, ra - slti ra, ra, 0x0154 - slli ra, ra, 0x000A - ori ra, gp, 0xFFFFFEC2 - ori ra, sp, 0x0075 - addi gp, sp, 0x0079 - xor gp, ra, sp - srli ra, sp, 0xFFFFFFF8 - slli gp, gp, 0x0006 - sra sp, gp, gp - add sp, sp, sp - slli gp, ra, 0xFFFFFFF0 - add sp, ra, sp - srai ra, sp, 0x0005 - addi ra, gp, 0xFFFFFF83 - xor gp, sp, ra - srli ra, ra, 0x0007 - sll gp, ra, gp - xori gp, gp, 0x0163 - add ra, gp, gp - add sp, ra, ra - sltu ra, ra, sp - sll sp, ra, ra - ori sp, sp, 0xFFFFFF6B - slli gp, gp, 0xFFFFFFFA - xori sp, ra, 0x00A7 - add sp, ra, ra - add ra, gp, gp - addi gp, gp, 0xFFFFFFE9 - sra sp, ra, gp - add gp, ra, ra - ori gp, gp, 0x0002 - addi gp, gp, 0x002F - sll sp, sp, ra - srli sp, ra, 0xFFFFFFF2 - ori gp, sp, 0x00EB - sra gp, ra, sp - sra sp, sp, gp - and gp, ra, ra - sra ra, ra, gp - add sp, gp, ra - srl gp, sp, gp - add ra, ra, sp - srai gp, ra, 0xFFFFFFF2 - srli sp, ra, 0xFFFFFFFC - ori gp, sp, 0xFFFFFE6E - and gp, ra, ra - ori gp, ra, 0xFFFFFFAF - srl ra, ra, ra - or sp, ra, ra - ori gp, sp, 0x0018 - and gp, gp, gp - slti gp, ra, 0x00C6 - sll gp, sp, gp - srli gp, sp, 0xFFFFFFFA - add gp, ra, ra - add gp, ra, sp - sra sp, ra, ra - ori sp, ra, 0x0022 - and gp, gp, gp - add ra, sp, ra - sll sp, gp, gp - ori gp, sp, 0x008E - slti ra, gp, 0x00B5 - add sp, ra, sp - and sp, gp, gp - addi ra, sp, 0x0145 - and sp, gp, gp - sll gp, ra, sp - addi sp, sp, 0xFFFFFFAF - xori sp, ra, 0xFFFFFE2C - srl gp, ra, gp - sub ra, sp, gp - add sp, ra, ra - slli sp, sp, 0x0006 - sub gp, ra, sp - sltu sp, ra, gp - xori ra, ra, 0xFFFFFF9A - addi sp, sp, 0xFFFFFE12 - slli ra, ra, 0xFFFFFFFD - add gp, gp, gp - xori ra, ra, 0xFFFFFED7 - andi gp, gp, 0xFFFFFE05 - and gp, gp, sp - addi gp, gp, 0xFFFFFEE5 - slli ra, gp, 0xFFFFFFF6 - sll sp, gp, gp - and ra, gp, sp - ori ra, gp, 0xFFFFFE22 - srl sp, sp, gp - srli ra, sp, 0x0005 - slli ra, ra, 0xFFFFFFFB - srai ra, ra, 0xFFFFFFF9 - srli ra, gp, 0xFFFFFFF1 - andi gp, gp, 0xFFFFFF96 - sra sp, gp, gp - srai gp, gp, 0x000F - sub sp, sp, gp - sltui ra, ra, 0xFFFFFF41 - and sp, sp, sp - xor gp, sp, ra - srai gp, sp, 0xFFFFFFF6 - xori gp, gp, 0x00D3 - or gp, sp, sp - sltu gp, ra, gp - slli ra, gp, 0x0002 - or sp, gp, ra - addi ra, ra, 0x002B - addi gp, ra, 0x0035 - slli sp, gp, 0x0008 - addi gp, sp, 0x015E - xor ra, gp, sp - or ra, gp, ra - sll ra, gp, ra - sll gp, gp, ra - srli gp, ra, 0xFFFFFFF4 - slt sp, ra, sp - sltui sp, sp, 0xFFFFFE1C - ori sp, ra, 0xFFFFFE83 - andi sp, sp, 0xFFFFFEFC - addi ra, ra, 0xFFFFFF85 - ori gp, ra, 0x0084 - sll gp, gp, ra - xori gp, sp, 0xFFFFFF6D - sll gp, sp, gp - sra ra, sp, ra - xor ra, gp, sp - srl ra, ra, sp - srl ra, ra, sp - andi gp, ra, 0xFFFFFE7B - srai ra, sp, 0xFFFFFFF1 - sub sp, sp, ra - or sp, gp, gp - slt ra, ra, gp - or gp, gp, sp - srli ra, sp, 0xFFFFFFF5 - andi ra, gp, 0xFFFFFFD4 - sra sp, sp, sp - add sp, ra, sp - sub gp, ra, sp - xori ra, gp, 0x0131 - add sp, sp, ra - addi sp, gp, 0x0003 - sll ra, ra, ra - slli gp, ra, 0x000E - andi ra, gp, 0xFFFFFE88 - srai ra, gp, 0xFFFFFFFA - done + ori gp, gp, 0xFFFFFE09 + and gp, gp, ra + srli sp, ra, 0x0002 + xor ra, ra, sp + or sp, ra, ra + xori ra, sp, 0x003D + addi ra, sp, 0x0012 + add ra, gp, sp + ori gp, ra, 0xFFFFFFB8 + sll ra, ra, ra + sll sp, gp, ra + slt ra, gp, ra + srai gp, gp, 0x0005 + slli ra, ra, 0x0007 + sub sp, gp, sp + andi ra, gp, 0x002D + sub gp, gp, sp + srai ra, gp, 0x0005 + or sp, ra, sp + xori ra, gp, 0xFFFFFF54 + sll ra, sp, ra + sub gp, gp, sp + add ra, sp, sp + sll ra, gp, ra + add gp, sp, sp + ori gp, sp, 0xFFFFFE68 + srli sp, gp, 0x000F + sltiu ra, ra, 0xFFFFFE5D + srli ra, gp, 0x0006 + srai sp, sp, 0x0005 + andi sp, sp, 0x0129 + and sp, sp, sp + slli gp, ra, 0x0001 + or gp, gp, gp + or sp, gp, gp + slli gp, gp, 0x0006 + srl sp, ra, gp + sltiu gp, ra, 0xFFFFFEC3 + add sp, gp, sp + srli ra, sp, 0x0001 + xori ra, ra, 0xFFFFFFA2 + or gp, gp, sp + and sp, gp, gp + srai gp, sp, 0x0008 + add sp, sp, ra + slti sp, ra, 0xFFFFFFF7 + srli gp, ra, 0x0003 + sll gp, ra, gp + sltu sp, sp, gp + srli gp, ra, 0x0002 + ori gp, sp, 0xFFFFFF28 + srl ra, gp, ra + or gp, ra, ra + ori sp, gp, 0x01D9 + and sp, ra, ra + addi sp, gp, 0x0054 + slli gp, ra, 0x000E + ori sp, sp, 0x0093 + srai sp, ra, 0x000F + slti ra, gp, 0xFFFFFFCB + add gp, gp, gp + and gp, gp, gp + sltiu gp, ra, 0x00DE + slli sp, gp, 0x000D + slli sp, ra, 0x000B + sltiu sp, ra, 0xFFFFFF0E + and ra, gp, ra + add gp, sp, sp + slti ra, sp, 0x008C + srli ra, sp, 0x0000 + addi sp, sp, 0x0168 + slli ra, ra, 0x000D + addi ra, gp, 0x012A + or sp, gp, ra + add ra, sp, gp + and gp, ra, ra + slli ra, gp, 0x000A + or sp, gp, sp + or gp, ra, ra + srli ra, sp, 0x0002 + ori gp, ra, 0x00EB + or sp, gp, ra + ori gp, sp, 0x01DA + andi ra, ra, 0xFFFFFFE9 + addi gp, sp, 0x00C9 + sltiu ra, ra, 0xFFFFFF13 + sltiu ra, ra, 0xFFFFFF3A + sltiu sp, gp, 0xFFFFFE5A + ori sp, sp, 0xFFFFFFFE + and gp, sp, gp + sltiu sp, ra, 0x0034 + srl gp, gp, ra + sll gp, sp, ra + ori ra, gp, 0xFFFFFEB6 + sll ra, sp, ra + sra ra, gp, sp + sub ra, sp, gp + xor gp, gp, sp + sub ra, ra, sp + srl gp, gp, sp + andi ra, ra, 0xFFFFFFCB + ori ra, ra, 0xFFFFFE1B + andi ra, ra, 0xFFFFFEC8 + sltiu sp, gp, 0x0108 + sub sp, gp, ra + slti ra, sp, 0x015D + slli sp, sp, 0x0004 + xor gp, sp, ra + srl ra, gp, ra + sltiu ra, ra, 0xFFFFFF3C + add sp, sp, sp + add gp, gp, ra + slli gp, gp, 0x0001 + andi sp, sp, 0xFFFFFF3A + slt gp, sp, gp + srli ra, sp, 0x0004 + ori sp, gp, 0xFFFFFEAB + ori sp, ra, 0xFFFFFE95 + slli sp, sp, 0x000E + xori gp, sp, 0x0040 + slti gp, sp, 0xFFFFFED1 + or sp, sp, sp + sltiu sp, gp, 0x01B4 + addi ra, gp, 0x002D + and sp, gp, gp + or ra, ra, ra + or ra, gp, ra + srli ra, ra, 0x0004 + or ra, gp, ra + sra ra, ra, gp + slli ra, gp, 0x000B + slti gp, gp, 0x00E0 + addi gp, ra, 0xFFFFFF72 + sltiu gp, sp, 0xFFFFFEAA + xor sp, ra, gp + and gp, sp, ra + srli gp, gp, 0x0003 + xori ra, ra, 0x01BD + srl ra, ra, gp + srai ra, gp, 0x0006 + sub ra, gp, sp + sll gp, ra, gp + xori ra, sp, 0x0065 + and ra, gp, ra + or ra, sp, ra + slt sp, gp, ra + addi ra, sp, 0xFFFFFE34 + slli gp, sp, 0x0007 + sll ra, sp, gp + sltiu gp, gp, 0xFFFFFE62 + slti sp, sp, 0x0019 + xori ra, gp, 0x0092 + sltiu gp, sp, 0xFFFFFF29 + srl sp, ra, gp + xori sp, gp, 0xFFFFFF4C + add sp, ra, gp + add sp, gp, ra + sra sp, sp, gp + slli sp, ra, 0x0008 + srl sp, sp, sp + add sp, gp, ra + andi sp, sp, 0x0039 + sll ra, gp, sp + andi gp, ra, 0xFFFFFECC + sll sp, sp, sp + sub sp, sp, ra + srai ra, sp, 0x0008 + xor gp, ra, sp + add sp, sp, sp + sub gp, ra, gp + xori gp, sp, 0x01EE + and ra, ra, ra + ori gp, ra, 0xFFFFFE96 + slli ra, gp, 0x0002 + srli gp, ra, 0x000D + srli sp, gp, 0x0005 + add ra, sp, sp + andi sp, gp, 0xFFFFFEC0 + andi sp, gp, 0xFFFFFE7A + xori ra, sp, 0x0169 + xori gp, sp, 0xFFFFFE02 + andi ra, ra, 0xFFFFFFD1 + xor ra, sp, gp + xori gp, gp, 0x00AB + srl ra, ra, gp + and ra, ra, sp + xori gp, sp, 0x005D + srai sp, sp, 0x000A + addi ra, sp, 0xFFFFFE19 + or sp, ra, ra + addi ra, gp, 0x0084 + ori sp, sp, 0xFFFFFF3D + xor gp, ra, gp + sra ra, ra, gp + xori ra, sp, 0x0040 + srai gp, gp, 0x0002 + xori ra, ra, 0xFFFFFE9A + sra ra, sp, sp + ori gp, sp, 0xFFFFFFB8 + sll sp, ra, ra + done #regset x1, 123 #regset x2, -40 #regset x3, 0xFFEE diff --git a/src/test/scala/RISCV/DataTypes.scala b/src/test/scala/RISCV/DataTypes.scala index 12e91c2..180e854 100644 --- a/src/test/scala/RISCV/DataTypes.scala +++ b/src/test/scala/RISCV/DataTypes.scala @@ -158,12 +158,13 @@ object Data { rightShifted } - def splitLoHi(loBits: Int): (Int, Int) = { - val hiBits = 32 - loBits - val sep = 31 - loBits - val lo = i.field(31, loBits) - val hi = i.field(sep, hiBits) - (lo, hi) + def splitHiLo(hiBits: Int): (Int, Int) = { + val loBits = 32 - hiBits + val sep = 31 - hiBits + val hi = i.field(31, hiBits) + val lo = i.field(sep, loBits) + say(s"split lo hi for $i with $hiBits high bits and got low: $lo, high: $hi") + (hi, lo) } def log2: Int = math.ceil(math.log(i.toDouble)/math.log(2.0)).toInt diff --git a/src/test/scala/RISCV/Ops.scala b/src/test/scala/RISCV/Ops.scala index e627d90..f77a351 100644 --- a/src/test/scala/RISCV/Ops.scala +++ b/src/test/scala/RISCV/Ops.scala @@ -93,14 +93,17 @@ object Ops { def or( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), OR) def xor( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), XOR) def and( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), AND) - def sll( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), SLL) - def srl( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), SRL) - def sra( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), SRA) def slt( rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), SLT) def sltu(rd: Int, rs1: Int, imm: Int) = ArithImm(Reg(rd), Reg(rs1), Imm(imm), SLTU) def nop = add(0, 0, 0) } + case class ArithImmShift(rd: Reg, rs1: Reg, shamt: Imm, op: ArithOp) extends Op with IType + object ArithImmShift { + def sll( rd: Int, rs1: Int, imm: Int) = ArithImmShift(Reg(rd), Reg(rs1), Imm(imm), SLL) + def srl( rd: Int, rs1: Int, imm: Int) = ArithImmShift(Reg(rd), Reg(rs1), Imm(imm), SRL) + def sra( rd: Int, rs1: Int, imm: Int) = ArithImmShift(Reg(rd), Reg(rs1), Imm(imm), SRA) + } case class LUI(rd: Reg, imm: Imm) extends Op with UType case class AUIPC(rd: Reg, imm: Imm) extends Op with UType diff --git a/src/test/scala/RISCV/Parser.scala b/src/test/scala/RISCV/Parser.scala index f987d48..50da76d 100644 --- a/src/test/scala/RISCV/Parser.scala +++ b/src/test/scala/RISCV/Parser.scala @@ -84,12 +84,12 @@ object Parser { stringWs("xori") ~> arithImm.mapN{ArithImm.xor}, stringWs("andi") ~> arithImm.mapN{ArithImm.and}, - stringWs("slli") ~> arithImm.mapN{ArithImm.sll}, - stringWs("srli") ~> arithImm.mapN{ArithImm.srl}, - stringWs("srai") ~> arithImm.mapN{ArithImm.sra}, + stringWs("slli") ~> arithImm.mapN{ArithImmShift.sll}, + stringWs("srli") ~> arithImm.mapN{ArithImmShift.srl}, + stringWs("srai") ~> arithImm.mapN{ArithImmShift.sra}, stringWs("slti") ~> arithImm.mapN{ArithImm.slt}, - stringWs("sltui") ~> arithImm.mapN{ArithImm.sltu}, + stringWs("sltiu") ~> arithImm.mapN{ArithImm.sltu}, // pseudos stringWs("not") ~> (reg <~ sep, reg, ok(-1)).mapN{ArithImm.xor}, @@ -98,8 +98,11 @@ object Parser { // seqz rd, rs1 => sltiu rd, rs1, 1 stringWs("seqz") ~> (reg <~ sep, reg, ok(1)).mapN{ArithImm.sltu}, - stringWs("li") ~> (reg ~ sep ~ int).collect{ - case((a, b), c) if (c.nBitsS <= 12) => ArithImm.add(a, 0, c) + stringWs("li") ~> (reg ~ sep ~ (hex | int)).collect{ + case((a, b), c) if (c.nBitsS <= 12) => { + say(s"for c: $c, nBitsS was ${c.nBitsS}") + ArithImm.add(a, 0, c) + } }, @@ -122,16 +125,16 @@ object Parser { //////////////////////////////////////////// //// load/store - stringWs("sw") ~> (reg <~ sep, int <~ char('('), reg <~ char(')')).mapN{case (rs2, offset, rs1) => SW(rs2, rs1, offset)}, - stringWs("lw") ~> (reg <~ sep, int <~ char('('), reg <~ char(')')).mapN{case (rd, offset, rs1) => LW(rd, rs1, offset)}, + stringWs("sw") ~> (reg <~ sep, (hex | int) <~ char('('), reg <~ char(')')).mapN{case (rs2, offset, rs1) => SW(rs2, rs1, offset)}, + stringWs("lw") ~> (reg <~ sep, (hex | int) <~ char('('), reg <~ char(')')).mapN{case (rd, offset, rs1) => LW(rd, rs1, offset)}, //////////////////////////////////////////// //// others - stringWs("auipc") ~> (reg <~ sep, int).mapN{AUIPC.apply}, - stringWs("lui") ~> (reg <~ sep, int).mapN{LUI.apply}, + stringWs("auipc") ~> (reg <~ sep, (hex | int)).mapN{AUIPC.apply}, + stringWs("lui") ~> (reg <~ sep, (hex | int)).mapN{LUI.apply}, many(whitespace) ~> string("nop") ~> ok(Arith.add(0, 0, 0)), many(whitespace) ~> string("done") ~> ok(DONE), @@ -140,19 +143,18 @@ object Parser { ).map(_.widen[Op]).reduce(_|_) - // def getShiftsHalfWord(offset: Int): (Int, Int) = (offset % 4) match { - // case 0 => (16, 16) - // case 1 => ( - // } - val multipleInstructions: Parser[List[Op]] = List( - stringWs("li") ~> (reg <~ sep, int.map(_.splitLoHi(12))).mapN{ case(rd, (lo, hi)) => List( + // stringWs("li") ~> (reg <~ sep, (hex | int).map(_.splitLoHi(20))).mapN{ case(rd, (hi, lo)) => { + stringWs("li") ~> (reg <~ sep, (hex | int).map(_.splitHiLo(20))).mapN{ case(rd, (hi, lo)) => { + say("hello?") + List( + ArithImm.add(rd, rd, lo), LUI(rd, hi), - ArithImm.add(rd, 0, lo) - )}.map(_.widen[Op]), + )}}.map(_.widen[Op]), - // NOTE: THESE ARE NOT PSEUDO-OPS IN RISV32I! + // NOTE: THESE ARE NOT PSEUDO-OPS IN RISC-V32I! // NOTE: USES A SPECIAL REGISTER + // NOTE: PROBABLY BROKEN, NOT EXHAUSTIVELY TESTED!!! stringWs("lh") ~> (reg <~ sep, int <~ char('('), reg <~ char(')')).mapN{ case (rd, offset, rs1) if (offset % 4 == 3) => { val placeHolder = if(rd == Reg("a0").value) Reg("a1").value else Reg("a0").value @@ -160,16 +162,16 @@ object Parser { SW(placeHolder, 0, 2048), LW(placeHolder, rs1.value, (offset & 0xFFFFFF1C)), LW(rd.value, rs1.value, (offset & 0xFFFFFF1C) + 4), - ArithImm.sra(placeHolder, placeHolder, 24), - ArithImm.sll(rd.value, rd.value, 24), - ArithImm.sra(rd.value, rd.value, 16), + ArithImmShift.sra(placeHolder, placeHolder, 24), + ArithImmShift.sll(rd.value, rd.value, 24), + ArithImmShift.sra(rd.value, rd.value, 16), Arith.add(rd, rd, placeHolder), LW(placeHolder, 0, 2048)).reverse } case (rd, offset, rs1) if (offset % 4 == 2) => { List( LW(rd, rs1, (offset & 0xFFFFFF1C)), - ArithImm.sra(rd, rd, 16) + ArithImmShift.sra(rd, rd, 16) ).reverse } @@ -177,8 +179,8 @@ object Parser { val leftShift = if((offset % 4) == 0) 16 else 8 List( LW(rd, rs1, (offset & 0xFFFFFF1C)), - ArithImm.sll(rd, rd, leftShift), - ArithImm.sra(rd, rd, 16), + ArithImmShift.sll(rd, rd, leftShift), + ArithImmShift.sra(rd, rd, 16), ).reverse } }.map(_.widen[Op]), diff --git a/src/test/scala/RISCV/VM.scala b/src/test/scala/RISCV/VM.scala index fe545bd..203161f 100644 --- a/src/test/scala/RISCV/VM.scala +++ b/src/test/scala/RISCV/VM.scala @@ -23,16 +23,17 @@ case class VM( def stepInstruction: Either[Finished, ExecutionTrace[VM]] = { if (pc.value == 0xEB1CEB1C) Left(Success) else getOp flatMap { - case op: Branch => executeBranch(op) - case op: Arith => executeArith(op) - case op: ArithImm => executeArithImm(op) - case op: AUIPC => executeAUIPC(op) - case op: LUI => executeLUI(op) - case op: JALR => executeJALR(op) - case op: JAL => executeJAL(op) - case op: LW => executeLW(op) - case op: SW => executeSW(op) - case DONE => Left(Success) + case op: Branch => executeBranch(op) + case op: Arith => executeArith(op) + case op: ArithImm => executeArithImm(op) + case op: ArithImmShift => executeArithImmShift(op) + case op: AUIPC => executeAUIPC(op) + case op: LUI => executeLUI(op) + case op: JALR => executeJALR(op) + case op: JAL => executeJAL(op) + case op: LW => executeLW(op) + case op: SW => executeSW(op) + case DONE => Left(Success) } } @@ -75,6 +76,13 @@ case class VM( } + private def executeArithImmShift(op: ArithImmShift) = { + val (regUpdate, nextRegs) = regs.arithImm(op.rd, op.rs1, op.shamt, op.op.run) + val nextVM = this.copy(regs = nextRegs) + Right(step(nextVM, regUpdate.toList:_*)) + } + + private def executeLUI(op: LUI) = { val (regUpdate, nextRegs) = regs + (op.rd -> (op.imm.value << 12)) val nextVM = this.copy(regs = nextRegs) diff --git a/src/test/scala/RISCV/assembler.scala b/src/test/scala/RISCV/assembler.scala index 298a85b..876ef49 100644 --- a/src/test/scala/RISCV/assembler.scala +++ b/src/test/scala/RISCV/assembler.scala @@ -125,12 +125,11 @@ object assembler { } /** - * Currently not used, thus we allow too larg shifts. + * Used by SRI, SRAI, SLLI */ - def setShiftTypeImmediate(instruction: Int, immediate: Int): Int = { + def setShiftTypeImmediate(shamt: Int, addr: Addr): Int => InstructionFragment = { val points = List((24, 5)) - val withField = applyImmediate(5, immediate, points)(instruction) - withField + applyImmediateU(shamt, points, addr) } def setOpCode(opcode: Int): Int => Int = setField(0, 7, opcode) @@ -142,16 +141,17 @@ object assembler { def setOpCode(op: Op): Int => Int = op match { - case x: Branch => setOpCode("1100011".binary) - case x: Arith => setOpCode("0110011".binary) - case x: ArithImm => setOpCode("0010011".binary) - case x: LW => setOpCode("0000011".binary) - case x: SW => setOpCode("0100011".binary) - case x: JALR => setOpCode("1100111".binary) - case x: JAL => setOpCode("1101111".binary) - case x: AUIPC => setOpCode("0110111".binary) - case x: LUI => setOpCode("0010111".binary) - case DONE => setOpCode("0010011".binary) // done is turned into a NOP in the assembler. + case x: Branch => setOpCode("1100011".binary) + case x: Arith => setOpCode("0110011".binary) + case x: ArithImm => setOpCode("0010011".binary) + case x: ArithImmShift => setOpCode("0010011".binary) + case x: LW => setOpCode("0000011".binary) + case x: SW => setOpCode("0100011".binary) + case x: JALR => setOpCode("1100111".binary) + case x: JAL => setOpCode("1101111".binary) + case x: AUIPC => setOpCode("0010111".binary) + case x: LUI => setOpCode("0110111".binary) + case DONE => setOpCode("0010011".binary) // done is turned into a NOP in the assembler. } def setComparisonFunct(cmp: Comparison): Int => Int = cmp match { @@ -195,7 +195,6 @@ object assembler { setRs1(op.rs1.value) def assembleSType(op: SType): Int => Int = { - // say("stype") instruction => (setRs1(op.rs1.value) andThen setRs2(op.rs2.value))(instruction) @@ -214,16 +213,17 @@ object assembler { def assembleImmediate(op: Op, addr: Addr, labelMap: Map[Label, Addr]): Int => Either[(String, Addr), Int] = op match { - case DONE => instruction => Right(instruction) - case op: Arith => instruction => Right(instruction) - case op: ArithImm => setItypeImmediate(op.imm.value, addr) - case op: Branch => setBranchDestination(labelMap, op, addr) - case op: JALR => instruction => labelMap.lift(op.dst).toRight(s"label ${op.dst} not found", addr).flatMap(addr => setItypeImmediate(addr.value, addr)(instruction)) - case op: AUIPC => setUtypeImmediate(op.imm.value, addr) - case op: LUI => setUtypeImmediate(op.imm.value, addr) - case op: LW => setItypeImmediate(op.offset.value, addr) - case op: SW => setStypeImmediate(op.offset.value, addr) - case op: JAL => instruction => { + case DONE => instruction => Right(instruction) + case op: Arith => instruction => Right(instruction) + case op: ArithImm => setItypeImmediate(op.imm.value, addr) + case op: ArithImmShift => setShiftTypeImmediate(op.shamt.value, addr) + case op: Branch => setBranchDestination(labelMap, op, addr) + case op: JALR => instruction => labelMap.lift(op.dst).toRight(s"label ${op.dst} not found", addr).flatMap(addr => setItypeImmediate(addr.value, addr)(instruction)) + case op: AUIPC => setUtypeImmediate(op.imm.value, addr) + case op: LUI => setUtypeImmediate(op.imm.value, addr) + case op: LW => setItypeImmediate(op.offset.value, addr) + case op: SW => setStypeImmediate(op.offset.value, addr) + case op: JAL => instruction => { val addressDistance = labelMap .lift(op.dst).toRight(s"label ${op.dst} not found", addr) .map(absoluteAddr => absoluteAddr - addr) @@ -246,14 +246,18 @@ object assembler { val opcode = setOpCode(op) val extras: Int => Int = (instruction: Int) => op match { - case op: Branch => setComparisonFunct(op.comp)(instruction) - case op: ArithImm => setArithFunct(op.op)(instruction) - case op: Arith => setArithFunct(op.op)(instruction) - case op: JALR => setFunct3("000".binary)(instruction) - case op: LW => setFunct3("010".binary)(instruction) - case op: SW => setFunct3("010".binary)(instruction) - case DONE => (setFunct3("000".binary) andThen setFunct7("0000000".binary))(instruction) - case _ => instruction + case op: Branch => setComparisonFunct(op.comp)(instruction) + case op: ArithImm => setArithFunct(op.op)(instruction) + case op: ArithImmShift => setArithFunct(op.op)(instruction) + case op: Arith => setArithFunct(op.op)(instruction) + case op: JALR => setFunct3("000".binary)(instruction) + case op: LW => setFunct3("010".binary)(instruction) + case op: SW => setFunct3("010".binary)(instruction) + case DONE => (setFunct3("000".binary) andThen setFunct7("0000000".binary))(instruction) + + case op: AUIPC => instruction + case op: JAL => instruction + case op: LUI => instruction } val withOp = opcode(0) diff --git a/src/test/scala/RISCV/deleteMe.scala b/src/test/scala/RISCV/deleteMe.scala deleted file mode 100644 index 0ed9892..0000000 --- a/src/test/scala/RISCV/deleteMe.scala +++ /dev/null @@ -1,178 +0,0 @@ -package FiveStage -import cats.data.Writer -import cats._ -import cats.data.{ Op => _ } -import cats.implicits._ - -object DTree { - - // opaques WHEN - type Feature = String - type Value = String - type Cls = String - - case class TrainingData(values: Map[Feature, Value], cls: Cls) - - type TestData = Map[Feature, Value] - - // Base - // def predict(data: TestData): Cls = "Died" - - // Gendered - def predictStatic(data: TestData): Cls = - if(data("gender") == "female") - "survived" - else "died" - - - sealed trait Tree - case class Node(feature: Feature, children: Map[Value, Tree]) extends Tree - case class Leaf(cls: Cls) extends Tree - - val genderBased: Tree = Node( - "gender", Map( - "female" -> Leaf("survived"), - "male" -> Leaf("died"), - )) - - - def predict(data: TestData)(tree: Tree): Cls = - tree match { - case Leaf(cls) => cls - case Node(feature, children) => predict(data)(children(data(feature))) - } - - val data = Map("gender" -> "female", "family size" -> "0", "ticket" -> "1") - - predict(data)(genderBased) // true - - - def entropy(classes: List[Cls]): Double = { - val total = classes.size - classes.groupBy(identity) - .mapValues { group => - val prop = group.size / total - prop * math.log(1.0 / prop) - }.values.sum - } - - def bucketedEntropy(data: List[TrainingData], feature: Feature): Double = { - val total = data.size - val bucketed = data.groupBy(_.values(feature)) - .mapValues(_.map(_.cls)) - .toMap - bucketed.values.map { classes => - val prop = classes.size / total - prop * entropy(classes) - }.sum - } - - def best(data: List[TrainingData], features: Set[Feature]): Feature = features.minBy(bucketedEntropy(data, _)) - - def mostCommonCls(data: List[TrainingData]): Cls = ??? - - def build(data: List[TrainingData], features: Set[Feature]): Tree = { - if(features.nonEmpty) { - val feature = best(data, features) - val buckets = data.groupBy(_.values(feature)) - Node(feature, buckets.mapValues(build(_, features - feature))) - } else { - Leaf(mostCommonCls(data)) - } - } - - def withHKT { - - sealed trait Tree[A] - case class Node[A](feature: Feature, children: Map[Value, A]) extends Tree[A] - case class Leaf[A](cls: Cls) extends Tree[A] - - // import matryoshka._ - // import matryoshka.data.Fix - // import matryoshka.implicits._ - - case class Fix[F[_]](unfix: F[Fix[F]]) - case class Cofree[F[_], A](head: A, tail: F[Cofree[F, A]]){ - def counit: A = head - def map[B](f: A => B)(implicit ev: Functor[F]): Cofree[F, B] = Cofree(f(head), tail.map(_.map(f))) - - /** - * Coflatmap alters the value of the node based on its context, then recursively - * alters its tail independently (which makes sense as it's the only thing Cofree[F, A] => B can do. - */ - def coflatMap[B](fa: Cofree[F, A] => B)(implicit ev: Functor[F]): Cofree[F, B] = { - val b = fa(this) - val fb = tail.map(_.coflatMap(fa)) - Cofree(b, fb) - } - } - - implicit val treeFunctor: Functor[Tree] = new Functor[Tree] { - def map[A, B](fa: Tree[A])(f: A => B): Tree[B] = fa match { - case Node(name, children) => Node(name, children.mapValues(f)) - case Leaf(cls) => Leaf(cls) - } - } - - val genderBased: Fix[Tree] = - Fix(Node( - "gender", - Map( - "female" -> Fix(Leaf[Fix[Tree]]("survived")), - "male" -> Fix(Leaf[Fix[Tree]]("died")) - ))) - - def build: ((List[TrainingData], Set[Feature])) => Tree[(List[TrainingData], Set[Feature])] = { - case (data, features) => - if(features.nonEmpty) { - val feature = best(data, features) - val buckets = data.groupBy(_.values(feature)) - val next = buckets.mapValues { subset => (subset, features - feature) } - Node(feature, next) - } else { - Leaf(mostCommonCls(data)) - } - } - - def explore(testData: TestData): Fix[Tree] => Cls Either Fix[Tree] = - fix => fix.unfix match { - case Leaf(cls) => Left(cls) - case Node(feature, children) => Right(children.get(testData(feature)).get) - } - - // Anamorphism: Generalized unfold, builds structures - def ana[F[_]: Functor, A](f: A => F[A])(a: A): Fix[F] = - Fix( (f(a)).map(ana(f)) ) - - // Catamorphism: Generalized fold, tears structures down. - def cata[F[_]: Functor, A](fa: F[A] => A)(f: Fix[F]): A = { - fa(f.unfix.map(cata(fa))) - } - - // def hyloSimple[F[_] : Functor, A, B](f: F[B] => B)(g: A => F[A]): A => B - def hyloSimple[F[_]: Functor, A, B](f: F[B] => B)(g: A => F[A])(a: A): B = - cata(f)(ana(g)(a)) - - // A more powerful cata - def para[F[_]: Functor, A](f: F[(Fix[F], A)] => A)(fa: Fix[F]): A = - f(fa.unfix.map(x => (x, para(f)(x)))) - - // A more powerful ana - def apo[F[_]: Functor, A](f: A => F[Either[Fix[F], A]])(a: A): Fix[F] = { - Fix(f(a).map{ - case Right(a) => apo(f)(a) - case Left(fix) => fix - }) - } - - // When we have cofree - def histo[F[_]: Functor, A](f: F[Cofree[F, A]] => A)(fix: Fix[F]): A = { - def toCofree(fix: Fix[F]): Cofree[F, A] = - Cofree(histo(f)(fix), fix.unfix.map(toCofree)) - - f(fix.unfix.map(toCofree)) - } - - - } -} diff --git a/src/test/scala/RISCV/deleteMe2.scala b/src/test/scala/RISCV/deleteMe2.scala deleted file mode 100644 index 74662cb..0000000 --- a/src/test/scala/RISCV/deleteMe2.scala +++ /dev/null @@ -1,164 +0,0 @@ -package FiveStage -import cats.data.Writer -import cats._ -import cats.data.{ Op => _ } -import cats.implicits._ - -import fileUtils.say - -object DeletDis { - - def delet = { - - case class Fix[F[_]](unfix: F[Fix[F]]) - case class Cofree[F[_], A](head: A, tail: F[Cofree[F, A]]){ - def counit: A = head - def map[B](f: A => B)(implicit ev: Functor[F]): Cofree[F, B] = Cofree(f(head), tail.map(_.map(f))) - - /** - * Coflatmap alters the value of the node based on its context, then recursively - * alters its tail independently (which makes sense as it's the only thing Cofree[F, A] => B can do. - */ - def coflatMap[B](fa: Cofree[F, A] => B)(implicit ev: Functor[F]): Cofree[F, B] = { - val b = fa(this) - val fb = tail.map(_.coflatMap(fa)) - Cofree(b, fb) - } - } - - // Anamorphism: Generalized unfold, builds structures - def ana[F[_]: Functor, A](f: A => F[A])(a: A): Fix[F] = - Fix( (f(a)).map(ana(f)) ) - - // Catamorphism: Generalized fold, tears structures down. - def cata[F[_]: Functor, A](fa: F[A] => A)(f: Fix[F]): A = { - fa(f.unfix.map(cata(fa))) - } - - // def hyloSimple[F[_] : Functor, A, B](f: F[B] => B)(g: A => F[A]): A => B - def hylo[F[_]: Functor, A, B](f: F[B] => B)(g: A => F[A])(a: A): B = - cata(f)(ana(g)(a)) - - // A more powerful cata - def para[F[_]: Functor, A](f: F[(Fix[F], A)] => A)(fa: Fix[F]): A = - f(fa.unfix.map(x => (x, para(f)(x)))) - - // A more powerful ana - def apo[F[_]: Functor, A](f: A => F[Either[Fix[F], A]])(a: A): Fix[F] = { - Fix(f(a).map{ - case Right(a) => apo(f)(a) - case Left(fix) => fix - }) - } - - // When we have cofree - def histo[F[_]: Functor, A](f: F[Cofree[F, A]] => A)(fix: Fix[F]): A = { - def toCofree(fix: Fix[F]): Cofree[F, A] = - Cofree(histo(f)(fix), fix.unfix.map(toCofree)) - - f(fix.unfix.map(toCofree)) - } - - sealed trait StackR - final case class DoneR(result: Int = 1) extends StackR - final case class MoreR(stack: StackR, next: Int) extends StackR - - def unfoldStackR(n: Int): StackR = - if(n > 0) MoreR(unfoldStackR(n-1), n) else DoneR() - - say(unfoldStackR(5)) - - sealed trait Stack[A] - final case class Done[A](result: Int) extends Stack[A] - final case class More[A](a: A, next: Int) extends Stack[A] - - object Stack { - implicit val stackFunctor: Functor[Stack] = new Functor[Stack] { - def map[A, B](fa: Stack[A])(f: A => B): Stack[B] = fa match { - case Done(result) => Done(result) - case More(a, next) => More(f(a), next) - } - } - - def done[A](result: Int = 1): Stack[A] = Done(result) - def more[A](a: A, next: Int): Stack[A] = More(a, next) - } - - import Stack._ - - val stackCoalgebra: Int => Stack[Int] = - n => if(n > 0) more(n - 1, n) else done() - - say(ana(stackCoalgebra)(5)) - - val stackAlgebra: Stack[Int] => Int = { - case Done(result) => result - case More(acc, next) => acc * next - } - - say(cata(stackAlgebra)(ana(stackCoalgebra)(5))) - say(hylo(stackAlgebra)(stackCoalgebra)(5)) - - - sealed trait Nat[A] - final case class Zero[A]() extends Nat[A] - final case class Succ[A](prev: A) extends Nat[A] - - object Nat { - implicit val natFunctor: Functor[Nat] = new Functor[Nat] { - override def map[A, B](na: Nat[A])(f: A => B): Nat[B] = - na match { - case Zero() => Zero() - case Succ(a) => Succ(f(a)) - } - } - } - - val natAlgebra: Nat[Int] => Int = { - case Zero() => 1 - case Succ(n) => { - say(s"nat alg succ $n") - n + 1 - } - } - - val natAlgebraS: Nat[String] => String = { - case Zero() => "N" - case Succ(n) => n match { - case "N" => "NI" - case "NI" => "NIG" - case "NIG" => "NIGG" - case "NIGG" => "NIGGE" - case "NIGGE" => "NIGGER :-" - case s => s + "D" - } - } - - val natCoalgebra: Int => Nat[Int] = - n => if (n == 0) Zero() else Succ(n - 1) - - val b = ana(natCoalgebra)(9) - val c = cata(natAlgebraS)(b) - say(c) - - - val natAlgebraPara: Nat[(Fix[Nat], Int)] => Int = { - case Zero() => 1 - case Succ((fix, acc)) => { - say(s"nat para alg succ $fix, $acc") - cata(natAlgebra)(fix) * acc - } - } - - val build = ana(natCoalgebra)(_) - say("built") - val tear = para(natAlgebraPara)(_) - say(tear(build(5))) - // say(ana(natCoalgebra)(5)) - - val lastThreeSteps: Fix[Stack] = Fix(More(Fix(More(Fix(More(Fix(Done(1)),1)),2)),3)) - - val stackCoalgebraApo: Int => Stack[Either[Fix[Stack], Int]] = - n => if(n > 3) more(n - 1, n).map(_.asRight) else lastThreeSteps.unfix.map(_.asLeft) - } -} diff --git a/src/test/scala/RISCV/printUtils.scala b/src/test/scala/RISCV/printUtils.scala index 77fe516..58adefa 100644 --- a/src/test/scala/RISCV/printUtils.scala +++ b/src/test/scala/RISCV/printUtils.scala @@ -81,16 +81,17 @@ object PrintUtils { val UNKNOWN = "UNKNOWN" def printInstruction(op: Ops.Op, labelMap: Map[Label, Addr]): fansi.Str = op match { - case op: Branch => fansi.Color.Red(s"B${op.comp}\t${op.rs1.show}, ${op.rs2.show}, ${op.dst.show}\t[${labelMap.lift(op.dst).getOrElse(UNKNOWN)}]") - case op: Arith => s"${op.op}\t${op.rd.show}, ${op.rs1.show}, ${op.rs2.show}" - case op: ArithImm => s"${op.op}I\t${op.rd.show}, ${op.rs1.show}, ${op.imm.show}" - case op: JALR => fansi.Color.Green(s"JALR\t${op.rd.show}, ${op.rs1.show}, ${op.dst.show}\t[${labelMap.lift(op.dst).getOrElse(UNKNOWN)}]") - case op: JAL => fansi.Color.Magenta(s"JAL\t${op.rd.show}, ${op.dst.show} [${labelMap.lift(op.dst).getOrElse(UNKNOWN)}]") - case op: LW => s"LW\t${op.rd.show}, ${op.offset.show}(${op.rs1.show})" - case op: SW => s"SW\t${op.rs2.show}, ${op.offset.show}(${op.rs1.show})" - case op: LUI => s"LUI\t${op.rd.show}, ${op.imm.show}" - case op: AUIPC => s"AUIPC\t${op.rd.show}, ${op.imm.show}" - case DONE => s"DONE" + case op: Branch => fansi.Color.Red(s"B${op.comp}\t${op.rs1.show}, ${op.rs2.show}, ${op.dst.show}\t[${labelMap.lift(op.dst).getOrElse(UNKNOWN)}]") + case op: Arith => s"${op.op}\t${op.rd.show}, ${op.rs1.show}, ${op.rs2.show}" + case op: ArithImm => s"${op.op}I\t${op.rd.show}, ${op.rs1.show}, ${op.imm.show}" + case op: ArithImmShift => s"${op.op}I\t${op.rd.show}, ${op.rs1.show}, ${op.shamt.show}" + case op: JALR => fansi.Color.Green(s"JALR\t${op.rd.show}, ${op.rs1.show}, ${op.dst.show}\t[${labelMap.lift(op.dst).getOrElse(UNKNOWN)}]") + case op: JAL => fansi.Color.Magenta(s"JAL\t${op.rd.show}, ${op.dst.show} [${labelMap.lift(op.dst).getOrElse(UNKNOWN)}]") + case op: LW => s"LW\t${op.rd.show}, ${op.offset.show}(${op.rs1.show})" + case op: SW => s"SW\t${op.rs2.show}, ${op.offset.show}(${op.rs1.show})" + case op: LUI => s"LUI\t${op.rd.show}, ${op.imm.show}" + case op: AUIPC => s"AUIPC\t${op.rd.show}, ${op.imm.show}" + case DONE => s"DONE" } @@ -118,7 +119,7 @@ object PrintUtils { def printBinary(bin: Map[Addr, Int]): String = { - bin.toList.sortBy(_._1.value).map{ case(addr, op) => s"$addr: ${op.hs}" }.mkString("\n","\n","\n") + bin.toList.sortBy(_._1.value).map{ case(addr, op) => s"$addr: ${op.hs}\t--\t${op.binary}" }.mkString("\n","\n","\n") } @@ -346,7 +347,8 @@ object PrintUtils { def printLogSideBySide(trace: List[ExecutionTraceEvent], chiselTrace: List[CircuitTrace], program: Program): String = { import LogParser._ + val header = "ADDRESS -- VM UPDATES --- DEVICE UNDER TEST UPDATES --- CORRESPONDING SOURCE LINE\n" val traces = mergeTraces(trace, chiselTrace).map(x => printMergedTraces((x), program)) - traces.map(_.mkString("\n")).mkString("\n", "\n--------------------------------------------------------------------------+------------------------------------------------------+-------------------------------\n", "\n") + "\n" + header + (traces.map(_.mkString("\n")).mkString("\n", "\n--------------------------------------------------------------------------+------------------------------------------------------+-------------------------------\n", "\n")) } } diff --git a/src/test/scala/TestUtils.scala b/src/test/scala/TestUtils.scala index 5943fd7..acaa741 100644 --- a/src/test/scala/TestUtils.scala +++ b/src/test/scala/TestUtils.scala @@ -75,7 +75,7 @@ object TestUtils { val entry = hasLeft + (leftIndex << 1) + (hasRight << 8) + (rightIndex << 9) + (root.value << 16) - say(s"with leftIndex: ${leftIndex.hs}, rightIndex: ${rightIndex.hs}, value: ${root.value.hs} we got ${entry.hs}") + // say(s"with leftIndex: ${leftIndex.hs}, rightIndex: ${rightIndex.hs}, value: ${root.value.hs} we got ${entry.hs}") entry :: foldAnno(root.left) ::: foldAnno(root.right) }.getOrElse(Nil) @@ -98,8 +98,8 @@ object TestUtils { */ def generateHazardsForward(steps: Int) : Unit = { - // val r = new scala.util.Random(0xF01D1EF7) - val r = new scala.util.Random(0xF01D1EF8) + val r = new scala.util.Random(0xF01D1EF7) + // val r = new scala.util.Random(0xF01D1EF8) import Ops._ val active = List(1, 2, 3) @@ -136,9 +136,9 @@ object TestUtils { (s"ori ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(imm).show}", ArithImm.or(rd, rs1, imm)), (s"xori ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(imm).show}", ArithImm.xor(rd, rs1, imm)), (s"andi ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(imm).show}", ArithImm.and(rd, rs1, imm)), - (s"slli ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(shift).show}", ArithImm.sll(rd, rs1, shift)), - (s"srli ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(shift).show}", ArithImm.srl(rd, rs1, shift)), - (s"srai ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(shift).show}", ArithImm.sra(rd, rs1, shift)), + (s"slli ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(math.abs(shift).toInt % 32).show}", ArithImmShift.sll(rd, rs1, math.abs(shift).toInt % 32)), + (s"srli ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(math.abs(shift).toInt % 32).show}", ArithImmShift.srl(rd, rs1, math.abs(shift).toInt % 32)), + (s"srai ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(math.abs(shift).toInt % 32).show}", ArithImmShift.sra(rd, rs1, math.abs(shift).toInt % 32)), (s"slti ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(imm).show}", ArithImm.slt(rd, rs1, imm)), (s"sltiu ${Reg(rd).show}, ${Reg(rs1).show}, ${Imm(imm).show}", ArithImm.sltu(rd, rs1, imm))) (rd, choices.shuffle(r).head) diff --git a/src/test/scala/testConf.scala b/src/test/scala/testConf.scala deleted file mode 100644 index 721cc38..0000000 --- a/src/test/scala/testConf.scala +++ /dev/null @@ -1,43 +0,0 @@ -// package FiveStage -// import chisel3._ -// import chisel3.iotesters._ -// import org.scalatest.{Matchers, FlatSpec} -// import spire.math.{UInt => Uint} -// import fileUtils._ -// import cats.implicits._ - -// import RISCVutils._ -// import RISCVasm._ -// import riscala._ - -// import utilz._ - -// class AllTests extends FlatSpec with Matchers { - -// val results = fileUtils.getAllTests.map{f => -// val result = TestRunner.runTest(f.getPath, false) -// (f.getName, result) -// } - -// makeReport(results) -// } - - -// /** -// This is for you to run more verbose testing. -// */ -// class SelectedTests extends FlatSpec with Matchers { - -// val tests = List( -// "matMul.s" -// ) - -// if(!tests.isEmpty){ -// val results = fileUtils.getAllTests.filter(f => tests.contains(f.getName)).map{ f => -// val result = TestRunner.runTest(f.getPath, true) -// (f.getName, result) -// } - -// makeReport(results) -// } -// }