diff --git a/README.md b/README.md index b630afe..2672aae 100644 --- a/README.md +++ b/README.md @@ -2,38 +2,78 @@ hwdbg

+

+Website +Docs +Published Researches +License +

+ ## Description -**hwdbg** is a chip-level debugger written in chisel. (This is a work in progress and not yet ready for testing!). -## Test +**hwdbg** is a chip-level debugger designed for black-box chip fuzzing and reverse engineering. It is written in Chisel and Verilog. (⚠️ This project is a work in progress and is not yet ready for testing.) + +## Deployment Board + +[This repository](https://github.com/HyperDbg/hwdbg-fpga) contains pre-built TCL files to facilitate project creation for running **hwdbg** on various FPGA development boards. + +## Output -You should now have a working Chisel3 project. +For generating SystemVerilog files, you need to install [Chisel](https://www.chisel-lang.org/docs/installation). Once installed, use the following commands: -You can run the included test with: ```sh -sbt test +$ sbt run ``` -Alternatively, if you use Mill: +This command prompts you to select a component. The `hwdbg.Main` class contains the debugger for synthesis purposes, while the `hwdbg.MainWithInitializedBRAM` class includes a pre-initialized Block RAM (BRAM), primarily for simulation and testing. + +After selecting the appropriate class for synthesis (option `1`) or simulation (option `2`), the output should look like this: + ```sh -mill hwdbg.test -``` +$ sbt run +[info] welcome to sbt 1.9.7 (Eclipse Adoptium Java 17.0.10) +[info] loading settings for project hwdbg-build-build-build from metals.sbt ... +[info] loading project definition from /home/sina/HyperDbg/hwdbg/project/project/project +[info] loading settings for project hwdbg-build-build from metals.sbt ... +[info] loading project definition from /home/sina/HyperDbg/hwdbg/project/project +[success] Generated .bloop/hwdbg-build-build.json +[success] Total time: 1 s, completed Apr 16, 2024, 1:49:05 PM +[info] loading settings for project hwdbg-build from metals.sbt,plugins.sbt ... +[info] loading project definition from /home/sina/HyperDbg/hwdbg/project +[success] Total time: 0 s, completed Apr 16, 2024, 1:49:05 PM +[info] loading settings for project root from build.sbt ... +[info] set current project to hwdbg (in build file:/home/sina/HyperDbg/hwdbg/) -You should see a whole bunch of output that ends with something like the following lines +Multiple main classes detected. Select one to run: + [1] hwdbg.Main + [2] hwdbg.MainWithInitializedBRAM + +Enter number: 2 +[info] running hwdbg.MainWithInitializedBRAM ``` -[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0 -[info] All tests passed. -[success] Total time: 5 s, completed Dec 16, 2020 12:18:44 PM + +The generated code for the debugger can be found in the `generated` directory. + +## Testbenches + +To test **hwdbg**, [cocotb](https://www.cocotb.org/) should be installed. After that, first, run the debugger (generated SystemVerilog files) and then run the following commands: + +```sh +cd sim +./test_module.sh ``` -If you see the above then the test was successful. -### ModelSim +The above command generates a waves file at `./sim/sim_build/DebuggerModuleTestingBRAM.fst` which can be read using [GTKWave](https://gtkwave.sourceforge.net/). -If you want to use ModelSim instead of GTKWave, you can configure the `modelsim.config` file. Please visit here for more information. +```sh +cd sim +gtkwave ./sim_build/DebuggerModuleTestingBRAM.fst +``` -## Output +### ModelSim -The final generated codes for fuzzy controllers are available in the `generated` directory. +If you prefer to use ModelSim instead of GTKWave, you can configure the `modelsim.config` file. Please visit here for more information. ## License -**hwdbg** and all its submodules and repos, unless a license is otherwise specified, are licensed under **GPLv3** LICENSE. + +**hwdbg** and all its submodules and repos, unless a license is otherwise specified, are licensed under **GPLv3** LICENSE. \ No newline at end of file diff --git a/src/main/scala/hwdbg/configs/constants.scala b/src/main/scala/hwdbg/configs/constants.scala new file mode 100644 index 0000000..eb8f925 --- /dev/null +++ b/src/main/scala/hwdbg/configs/constants.scala @@ -0,0 +1,33 @@ +/** @file + * constants.scala + * @author + * Sina Karvandi (sina@hyperdbg.org) + * @brief + * Constant values + * @details + * @version 0.1 + * @date + * 2024-04-16 + * + * @copyright + * This project is released under the GNU Public License v3. + */ +package hwdbg.constants + +import chisel3._ +import chisel3.util._ + +/** @brief + * Shared value with HyperDbg + * @warning + * used in HyperDbg + */ +object HyperDbgSharedConstants { + + // + // Constant indicator of a HyperDbg packet + // + val INDICATOR_OF_HYPERDBG_PACKET: Long = + 0x4859504552444247L // HYPERDBG = 0x4859504552444247 + +} diff --git a/src/main/scala/hwdbg/interpreter/interpreter.scala b/src/main/scala/hwdbg/interpreter/interpreter.scala index 9fe68f3..fd295bb 100644 --- a/src/main/scala/hwdbg/interpreter/interpreter.scala +++ b/src/main/scala/hwdbg/interpreter/interpreter.scala @@ -21,6 +21,7 @@ import circt.stage.ChiselStage import hwdbg.configs._ import hwdbg.types._ import hwdbg.utils._ +import hwdbg.constants._ object DebuggerPacketInterpreterEnums { object State extends ChiselEnum { @@ -82,6 +83,11 @@ class DebuggerPacketInterpreter( val regInterpretationDone = RegInit(false.B) val regFoundValidPacket = RegInit(false.B) + // + // Rising-edge detector for interpretation signal + // + val risingEdgePlInSignal = io.plInSignal & !RegNext(io.plInSignal) + // // Structure (as register) of the received packet buffer // @@ -117,7 +123,7 @@ class DebuggerPacketInterpreter( // // Check whether the interrupt from the PS is received or not // - when(io.plInSignal === true.B) { + when(risingEdgePlInSignal === true.B) { state := sInit } @@ -175,6 +181,7 @@ class DebuggerPacketInterpreter( // Goes to the next section // state := sReadTypeOfThePacket + } is(sReadTypeOfThePacket) { @@ -189,9 +196,28 @@ class DebuggerPacketInterpreter( regRdWrAddr := regReceivedPacketBuffer.Offset.requestedActionOfThePacket.U // - // Goes to the next section + // Check whether the indicator is valid or not // - state := sReadRequestedActionOfThePacket + when( + regReceivedPacketBuffer.Indicator === HyperDbgSharedConstants.INDICATOR_OF_HYPERDBG_PACKET.U + ) { + + // + // Indicator of packet is valid + // (Goes to the next section) + // + state := sReadRequestedActionOfThePacket + }.otherwise { + + // + // Type of packet is not valid + // (interpretation was done but not found a valid packet, + // so, go to the idle state) + // + regInterpretationDone := true.B + state := sIdle + } + } is(sReadRequestedActionOfThePacket) { @@ -201,9 +227,28 @@ class DebuggerPacketInterpreter( regReceivedPacketBuffer.RequestedActionOfThePacket := io.rdData // - // Reading all values + // Check whether the type of the packet is valid or not // - state := sDone + when( + regReceivedPacketBuffer.Indicator === HyperDbgSharedConstants.INDICATOR_OF_HYPERDBG_PACKET.U + ) { + + // + // Type of packet is valid + // All the values are now valid + // (Goes to the next section) + // + state := sDone + }.otherwise { + + // + // Type of packet is not valid + // (interpretation was done but not found a valid packet, + // so, go to the idle state) + // + regInterpretationDone := true.B + state := sIdle + } } is(sDone) { diff --git a/src/main/scala/hwdbg/libs/mem/init_reg_mem_from_file.scala b/src/main/scala/hwdbg/libs/mem/init_reg_mem_from_file.scala index 59bcfd2..87e45f6 100644 --- a/src/main/scala/hwdbg/libs/mem/init_reg_mem_from_file.scala +++ b/src/main/scala/hwdbg/libs/mem/init_reg_mem_from_file.scala @@ -70,12 +70,18 @@ class InitRegMemFromFile( VecInit(InitRegMemFromFileTools.readmemh(debug, memoryFile, width)) ) + // + // This because the address of the saved registers are using 4 bytes granularities + // E.g., 4 Rsh 2 = 1 | 8 Rsh 2 = 2 | 12 Rsh 2 = 3 + // + val actualAddr = io.addr >> 2 + when(io.enable) { - val rdwrPort = mem(io.addr) + val rdwrPort = mem(actualAddr) io.dataOut := rdwrPort when(io.write) { - mem(io.addr) := io.dataIn + mem(actualAddr) := io.dataIn } }.otherwise { io.dataOut := 0.U diff --git a/src/main/scala/hwdbg/main.scala b/src/main/scala/hwdbg/main.scala index dc1b117..14fb288 100644 --- a/src/main/scala/hwdbg/main.scala +++ b/src/main/scala/hwdbg/main.scala @@ -94,10 +94,55 @@ class DebuggerMain( io.rdData ) + // + // Assign to the output (for testing) + // + when(interpretationDone === true.B && foundValidPacket === true.B) { + + when(requestedActionOfThePacket === 0x12345678.U) { + + io.outputPin(0) := 1.U + io.outputPin(1) := 0.U + io.outputPin(2) := 0.U + io.outputPin(3) := 0.U + }.elsewhen(requestedActionOfThePacket === 0x12345670.U) { + + io.outputPin(0) := 1.U + io.outputPin(1) := 1.U + io.outputPin(2) := 0.U + io.outputPin(3) := 0.U + }.elsewhen(requestedActionOfThePacket === 0x12345600.U) { + + io.outputPin(0) := 1.U + io.outputPin(1) := 1.U + io.outputPin(2) := 1.U + io.outputPin(3) := 0.U + }.elsewhen(requestedActionOfThePacket === 0x12345000.U) { + + io.outputPin(0) := 1.U + io.outputPin(1) := 1.U + io.outputPin(2) := 1.U + io.outputPin(3) := 1.U + }.otherwise { + + io.outputPin(0) := 0.U + io.outputPin(1) := 0.U + io.outputPin(2) := 0.U + io.outputPin(3) := 0.U + } + } + .otherwise { + + io.outputPin(0) := 0.U + io.outputPin(1) := 0.U + io.outputPin(2) := 0.U + io.outputPin(3) := 0.U + } + // // Configure the output signals // - for (i <- 0 until numberOfOutputPins) { + for (i <- 4 until numberOfOutputPins) { io.outputPin(i) := requestedActionOfThePacket(i) }